Compare commits
138 Commits
v0.17.15
...
f9ee43b1f0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9ee43b1f0 | ||
|
|
bb2ede229c | ||
|
|
2d12ab3a19 | ||
|
|
efeb24b0f0 | ||
|
|
0e8ddee6c5 | ||
|
|
bf0bb1d47b | ||
|
|
bce60ee6c7 | ||
|
|
b0a47f5222 | ||
|
|
58bac2e290 | ||
|
|
84361c3c31 | ||
|
|
d0a7a28349 | ||
|
|
10b8891cf0 | ||
|
|
3a4fcf6d7b | ||
|
|
19ea76dc4c | ||
|
|
42942d1ac4 | ||
|
|
43215dfc4b | ||
|
|
5728194085 | ||
|
|
1501ebd92a | ||
|
|
0299fde47b | ||
|
|
11680aedbb | ||
|
|
ad0b73ff62 | ||
|
|
f38746ff96 | ||
|
|
8ee7a90eca | ||
|
|
d06d8ebfff | ||
|
|
d3e4d7e62c | ||
|
|
80ff30401a | ||
|
|
4657515b61 | ||
|
|
90dcb9ee1a | ||
|
|
4e606f4e91 | ||
|
|
9c0dc60746 | ||
|
|
58a5749d67 | ||
|
|
7d0d89f1a6 | ||
|
|
f92121f093 | ||
|
|
2604d034fe | ||
|
|
3219da77e9 | ||
|
|
ea3fb8d09e | ||
|
|
074cefed5d | ||
|
|
7070e620c8 | ||
|
|
1cd62bb163 | ||
|
|
529b8d453d | ||
|
|
486eaeae52 | ||
|
|
a2931ea290 | ||
|
|
edb79e8156 | ||
|
|
ed5abe0350 | ||
|
|
3806f02fa5 | ||
|
|
7d23fe4acb | ||
|
|
c650f268f6 | ||
|
|
55800e307f | ||
|
|
2671306688 | ||
|
|
20e9d085c0 | ||
|
|
1c1a006723 | ||
|
|
a0fd8ff8b6 | ||
|
|
720325fcb9 | ||
|
|
fcc1cba0cf | ||
|
|
8ca17ba3ff | ||
|
|
942a789b9e | ||
|
|
293e687077 | ||
|
|
9929b888c5 | ||
|
|
e66e30c14a | ||
|
|
adf225e192 | ||
|
|
4c2dc5e8df | ||
|
|
e1a9222b1f | ||
|
|
86c673ee51 | ||
|
|
6aefa078da | ||
|
|
dd743035f5 | ||
|
|
045deb6954 | ||
|
|
8e169dbde8 | ||
|
|
90c428cf44 | ||
|
|
7ac2c282f6 | ||
|
|
ad58d38ab1 | ||
|
|
5ea940d8c4 | ||
|
|
c0dca683b5 | ||
|
|
35635e10ea | ||
|
|
dfda067c08 | ||
|
|
09117c4704 | ||
|
|
6083fd5097 | ||
|
|
e104297b13 | ||
|
|
ed3927a8c3 | ||
|
|
b62b907dc8 | ||
|
|
769125a894 | ||
|
|
6ccebcfe17 | ||
|
|
8894701806 | ||
|
|
012e0f76a9 | ||
|
|
d58f41b999 | ||
|
|
95916a8736 | ||
|
|
69a288db8f | ||
|
|
bb8a436604 | ||
|
|
b58f266561 | ||
|
|
4e41024ba8 | ||
|
|
323f8a72aa | ||
|
|
bb4d3023c6 | ||
|
|
2208a0fca0 | ||
|
|
3cd6f3d726 | ||
|
|
8b1d72fb54 | ||
|
|
73480d4a53 | ||
|
|
120dc453d7 | ||
|
|
eae441b18b | ||
|
|
4f411ef78e | ||
|
|
35ec325990 | ||
|
|
54758fd705 | ||
|
|
e7183025cf | ||
|
|
03a2e9356c | ||
|
|
0eb4212e40 | ||
|
|
22ca0a7c96 | ||
|
|
33fc59bd5c | ||
|
|
2f6a3392e6 | ||
|
|
75f3efc6a0 | ||
|
|
19e4185668 | ||
|
|
bbb5fd7832 | ||
|
|
8806ef602e | ||
|
|
6f5ebb1a4d | ||
|
|
7cd03d0ec0 | ||
|
|
00c5233f3b | ||
|
|
a08328ae02 | ||
|
|
a6a20b4332 | ||
|
|
732e2aee79 | ||
|
|
74c3d3a313 | ||
|
|
3ebc93e65c | ||
|
|
7e8e67694d | ||
|
|
00f63a2ec5 | ||
|
|
5a30e4aec9 | ||
|
|
43aecd2467 | ||
|
|
622ae07b32 | ||
|
|
63f443d4e4 | ||
|
|
688328e6b0 | ||
|
|
0fc4957b21 | ||
|
|
5e88b23980 | ||
|
|
986f0dcdc8 | ||
|
|
48f2ee9252 | ||
|
|
73d6eaaffc | ||
|
|
b1dbc4fa87 | ||
|
|
2e9ea4a783 | ||
|
|
a475232432 | ||
|
|
bc99af5b1b | ||
|
|
06dc22544f | ||
|
|
70c1b04bf6 | ||
|
|
41c957cd8f | ||
|
|
e3a0eacf1d |
175
.github/workflows/main.yml
vendored
175
.github/workflows/main.yml
vendored
@@ -39,7 +39,9 @@ jobs:
|
||||
os.execute('echo "version-string=' .. version.string:gsub("%a", "") .. '" >> $GITHUB_OUTPUT')
|
||||
os.execute('echo "version-code=' .. tostring(version.code) .. '" >> $GITHUB_OUTPUT')
|
||||
|
||||
local note = require 'parts.updateLog'
|
||||
local f = io.open("updateLog.txt", 'r')
|
||||
local note = f:read("*a")
|
||||
f:close()
|
||||
local p1 = note:find("\n%d") + 1
|
||||
local p2 = note:find("\n", p1) - 1
|
||||
os.execute('echo "update-title=' .. note:sub(p1, p2) .. '" >> $GITHUB_OUTPUT')
|
||||
@@ -90,7 +92,7 @@ jobs:
|
||||
- name: Build core love package
|
||||
uses: love-actions/love-actions-core@v1
|
||||
with:
|
||||
build-list: ./media/ ./parts/ ./Zframework/ ./conf.lua ./main.lua ./version.lua
|
||||
build-list: ./media/ ./parts/ ./Zframework/ ./conf.lua ./main.lua ./version.lua ./legals.md ./license.txt
|
||||
package-path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||
- name: Upload core love package
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -213,87 +215,6 @@ jobs:
|
||||
name: ${{ needs.get-info.outputs.update-title }}
|
||||
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||
|
||||
build-ios:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Process app name
|
||||
id: process-app-name
|
||||
shell: python3 {0}
|
||||
run: |
|
||||
import os
|
||||
import re
|
||||
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
||||
f.write('bundle-id=org.26f-studio.techmino\n')
|
||||
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
||||
- name: Download core love package
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||
- name: Download ColdClear
|
||||
uses: ./.github/actions/get-cc
|
||||
with:
|
||||
platform: iOS
|
||||
dir: ./ColdClear
|
||||
- name: Build iOS packages
|
||||
id: build-packages
|
||||
uses: love-actions/love-actions-ios@v1
|
||||
with:
|
||||
app-name: ${{ needs.get-info.outputs.app-name }}
|
||||
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
||||
copyright: "Copyright © 2019-2023 26F-Studio. Some Rights Reserved."
|
||||
icon-path: ./.github/build/iOS/${{ env.BUILD_TYPE }}/icon
|
||||
love-patch: ./.github/build/iOS/love.patch
|
||||
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||
libs-path: ./ColdClear/arm64/
|
||||
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
||||
version-string: ${{ needs.get-info.outputs.version-string }}
|
||||
output-folder: ${{ env.OUTPUT_FOLDER }}
|
||||
apple-development-base64: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_BASE64 }}
|
||||
apple-development-password: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_PWD }}
|
||||
api-key: ${{ secrets.APPLE_API_KEY }}
|
||||
api-key-id: ${{ secrets.APPLE_API_KEY_ID }}
|
||||
api-issuer-id: ${{ secrets.APPLE_API_ISSUER_ID }}
|
||||
team-id: ${{ secrets.APPLE_DEVELOPER_TEAM_ID }}
|
||||
apple-id: ${{ secrets.APPLE_APPLE_ID }}
|
||||
external-test: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||
store-release: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
- name: Upload logs artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.base-name }}_iOS_logs
|
||||
path: |
|
||||
${{ env.OUTPUT_FOLDER }}/DistributionSummary.plist
|
||||
${{ env.OUTPUT_FOLDER }}/ExportOptions.plist
|
||||
${{ env.OUTPUT_FOLDER }}/Packaging.log
|
||||
- name: Upload ipa artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.base-name }}_iOS_ipa
|
||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.ipa
|
||||
- name: Prepare for release
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ${{ env.RELEASE_FOLDER }}
|
||||
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.ipa ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_iOS.ipa
|
||||
- name: Upload release
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
artifacts: ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_iOS.ipa
|
||||
body: ${{ needs.get-info.outputs.update-note }}
|
||||
name: ${{ needs.get-info.outputs.update-title }}
|
||||
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
@@ -377,90 +298,6 @@ jobs:
|
||||
name: ${{ needs.get-info.outputs.update-title }}
|
||||
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||
|
||||
build-macos-appstore:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Process app name
|
||||
id: process-app-name
|
||||
shell: python3 {0}
|
||||
run: |
|
||||
import os
|
||||
import re
|
||||
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
||||
f.write('bundle-id=org.26f-studio.techmino\n')
|
||||
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
||||
- name: Download core love package
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||
- name: Download ColdClear
|
||||
uses: ./.github/actions/get-cc
|
||||
with:
|
||||
platform: macOS
|
||||
dir: ./ColdClear
|
||||
- name: Process ColdClear
|
||||
shell: bash
|
||||
run: |
|
||||
rm ./ColdClear/universal/libcold_clear.a
|
||||
- name: Build macOS packages
|
||||
id: build-packages
|
||||
uses: love-actions/love-actions-macos-appstore@v1
|
||||
with:
|
||||
app-name: ${{ needs.get-info.outputs.app-name }}
|
||||
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
||||
copyright: "Copyright © 2019-2023 26F-Studio. Some Rights Reserved."
|
||||
icon-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/icon.icns
|
||||
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||
libs-path: ./ColdClear/universal/
|
||||
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
||||
version-string: ${{ needs.get-info.outputs.version-string }}
|
||||
output-folder: ${{ env.OUTPUT_FOLDER }}
|
||||
apple-development-base64: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_BASE64 }}
|
||||
apple-development-password: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_PWD }}
|
||||
api-key: ${{ secrets.APPLE_API_KEY }}
|
||||
api-key-id: ${{ secrets.APPLE_API_KEY_ID }}
|
||||
api-issuer-id: ${{ secrets.APPLE_API_ISSUER_ID }}
|
||||
team-id: ${{ secrets.APPLE_DEVELOPER_TEAM_ID }}
|
||||
apple-id: ${{ secrets.APPLE_APPLE_ID }}
|
||||
external-test: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||
store-release: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
- name: Upload logs artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.base-name }}_macOS_appstore_logs
|
||||
path: |
|
||||
${{ env.OUTPUT_FOLDER }}/DistributionSummary.plist
|
||||
${{ env.OUTPUT_FOLDER }}/ExportOptions.plist
|
||||
${{ env.OUTPUT_FOLDER }}/Packaging.log
|
||||
- name: Upload pkg artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.base-name }}_macOS_appstore_pkg
|
||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg
|
||||
- name: Prepare for release
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ${{ env.RELEASE_FOLDER }}
|
||||
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_appstore.pkg
|
||||
- name: Upload release
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
artifacts: ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_appstore.pkg
|
||||
body: ${{ needs.get-info.outputs.update-note }}
|
||||
name: ${{ needs.get-info.outputs.update-title }}
|
||||
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||
|
||||
build-macos-portable:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
@@ -684,9 +521,7 @@ jobs:
|
||||
auto-test,
|
||||
build-core,
|
||||
build-android,
|
||||
build-ios,
|
||||
build-linux,
|
||||
build-macos-appstore,
|
||||
build-macos-portable,
|
||||
build-web,
|
||||
build-windows,
|
||||
@@ -719,6 +554,6 @@ jobs:
|
||||
"fields":[
|
||||
{"name":"Version","value":"${{ needs.get-info.outputs.version-string }}","inline": true},
|
||||
{"name":"Package Name","value":"${{ needs.get-info.outputs.base-name }}","inline": true},
|
||||
{"name":"Status","value":"**Automatic Test:** ${{ needs.auto-test.result }}\n**Core:** ${{ needs.build-core.result }}\n**Android:** ${{ needs.build-android.result }}\n**iOS:** ${{ needs.build-ios.result }}\n**Linux:** ${{ needs.build-linux.result }}\n**macOS App Store:** ${{ needs.build-macos-appstore.result }}\n**macOS portable:** ${{ needs.build-macos-portable.result }}\n**Windows:** ${{ needs.build-windows.result }}"}
|
||||
{"name":"Status","value":"**Automatic Test:** ${{ needs.auto-test.result }}\n**Core:** ${{ needs.build-core.result }}\n**Android:** ${{ needs.build-android.result }}\n**Linux:** ${{ needs.build-linux.result }}\n**macOS portable:** ${{ needs.build-macos-portable.result }}\n**Windows:** ${{ needs.build-windows.result }}"}
|
||||
]
|
||||
}'
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "Zframework"]
|
||||
path = Zframework
|
||||
url = https://github.com/26F-Studio/Zframework.git
|
||||
Submodule Zframework deleted from c498582a8c
57
Zframework/background.lua
Normal file
57
Zframework/background.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
local gc_clear=love.graphics.clear
|
||||
local BGs={
|
||||
none={draw=function() gc_clear(.08,.08,.084) end}
|
||||
}
|
||||
local BGlist={'none'}
|
||||
local BG={
|
||||
default='none',
|
||||
locked=false,
|
||||
cur='none',
|
||||
init=false,
|
||||
resize=false,
|
||||
update=NULL,
|
||||
draw=BGs.none.draw,
|
||||
event=false,
|
||||
discard=NULL,
|
||||
}
|
||||
|
||||
function BG.lock() BG.locked=true end
|
||||
function BG.unlock() BG.locked=false end
|
||||
function BG.add(name,bg)
|
||||
BGs[name]=bg
|
||||
BGlist[#BGlist+1]=name
|
||||
end
|
||||
function BG.getList()
|
||||
return BGlist
|
||||
end
|
||||
function BG.remList(name)
|
||||
table.remove(BGlist,TABLE.find(BGlist,name))
|
||||
end
|
||||
function BG.send(...)
|
||||
if BG.event then
|
||||
BG.event(...)
|
||||
end
|
||||
end
|
||||
function BG.setDefault(bg)
|
||||
BG.default=bg
|
||||
end
|
||||
function BG.set(name,...)
|
||||
name=name or BG.default
|
||||
if not BGs[name] or BG.locked then return end
|
||||
if name~=BG.cur then
|
||||
BG.discard()
|
||||
BG.cur=name
|
||||
local bg=BGs[name]
|
||||
|
||||
BG.init= bg.init or NULL
|
||||
BG.resize= bg.resize or NULL
|
||||
BG.update= bg.update or NULL
|
||||
BG.draw= bg.draw or NULL
|
||||
BG.event= bg.event or NULL
|
||||
BG.discard=bg.discard or NULL
|
||||
BG.init()
|
||||
if ... then BG.send(...) end
|
||||
end
|
||||
return true
|
||||
end
|
||||
return BG
|
||||
350
Zframework/bgm.lua
Normal file
350
Zframework/bgm.lua
Normal file
@@ -0,0 +1,350 @@
|
||||
local audio=love.audio
|
||||
local effectsSupported=audio.isEffectsSupported()
|
||||
|
||||
local nameList={}
|
||||
local srcLib={}-- Stored bgm objects: {name='foo', source=bar, ...}, more info at function _addFile()
|
||||
local lastLoadNames={}
|
||||
local nowPlay={}
|
||||
local lastPlay=NONE-- Directly stored last played bgm name(s)
|
||||
|
||||
local defaultBGM=false
|
||||
local maxLoadedCount=3
|
||||
local volume=1
|
||||
|
||||
local function task_setVolume(obj,ve,time,stop)
|
||||
local vs=obj.vol
|
||||
local t=0
|
||||
while true do
|
||||
t=time~=0 and math.min(t+coroutine.yield()/time,1) or 1
|
||||
local v=MATH.mix(vs,ve,t)
|
||||
obj.vol=v
|
||||
obj.source:setVolume(v*volume)
|
||||
if t==1 then
|
||||
obj.volChanging=false
|
||||
break
|
||||
end
|
||||
end
|
||||
if stop then
|
||||
obj.source:stop()
|
||||
end
|
||||
obj.volChanging=false
|
||||
return true
|
||||
end
|
||||
local function task_setPitch(obj,pe,time)
|
||||
local ps=obj.pitch
|
||||
local t=0
|
||||
while true do
|
||||
t=time~=0 and math.min(t+coroutine.yield()/time,1) or 1
|
||||
local p=MATH.mix(ps,pe,t)
|
||||
obj.pitch=p
|
||||
obj.source:setPitch(p)
|
||||
if t==1 then
|
||||
obj.pitchChanging=false
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
local function task_setLowgain(obj,pe,time)
|
||||
local ps=obj.lowgain
|
||||
local t=0
|
||||
while true do
|
||||
t=time~=0 and math.min(t+coroutine.yield()/time,1) or 1
|
||||
local p=MATH.mix(ps,pe,t)
|
||||
obj.lowgain=p
|
||||
obj.source:setFilter{type='bandpass',lowgain=obj.lowgain^9.42,highgain=obj.highgain^9.42,volume=1}
|
||||
if t==1 then
|
||||
obj.lowgainChanging=false
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
local function task_setHighgain(obj,pe,time)
|
||||
local ps=obj.highgain
|
||||
local t=0
|
||||
while true do
|
||||
t=time~=0 and math.min(t+coroutine.yield()/time,1) or 1
|
||||
local p=MATH.mix(ps,pe,t)
|
||||
obj.highgain=p
|
||||
obj.source:setFilter{type='bandpass',lowgain=obj.lowgain^9.42,highgain=obj.highgain^9.42,volume=1}
|
||||
if t==1 then
|
||||
obj.highgainChanging=false
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
local function _clearTask(obj,mode)
|
||||
local taskFunc=
|
||||
mode=='volume' and task_setVolume or
|
||||
mode=='pitch' and task_setPitch or
|
||||
mode=='lowgain' and task_setLowgain or
|
||||
mode=='highgain' and task_setHighgain or
|
||||
'any'
|
||||
TASK.removeTask_iterate(function(task)
|
||||
return task.args[1]==obj and (taskFunc=='any' or task.code==taskFunc)
|
||||
end,obj)
|
||||
end
|
||||
|
||||
local function _updateSources()
|
||||
local n=#lastLoadNames
|
||||
while #lastLoadNames>maxLoadedCount and n>0 do
|
||||
local name=lastLoadNames[n]
|
||||
if srcLib[name].source and not srcLib[name].source:isPlaying() then
|
||||
srcLib[name].source=srcLib[name].source:release() and nil
|
||||
_clearTask(srcLib[name],'any')
|
||||
end
|
||||
n=n-1
|
||||
end
|
||||
end
|
||||
local function _addFile(name,path)
|
||||
if not srcLib[name] then
|
||||
table.insert(nameList,name)
|
||||
srcLib[name]={
|
||||
name=name,path=path,source=false,
|
||||
vol=0,volChanging=false,
|
||||
pitch=1,pitchChanging=false,
|
||||
lowgain=1,lowgainChanging=false,
|
||||
highgain=1,highgainChanging=false,
|
||||
}
|
||||
end
|
||||
end
|
||||
local function _tryLoad(name)
|
||||
if srcLib[name] then
|
||||
local obj=srcLib[name]
|
||||
if obj.source then
|
||||
return true
|
||||
elseif love.filesystem.getInfo(obj.path) then
|
||||
obj.source=audio.newSource(obj.path,'stream')
|
||||
obj.source:setLooping(true)
|
||||
table.insert(lastLoadNames,1,name)
|
||||
return true
|
||||
else
|
||||
LOG(STRING.repD("Wrong path for BGM '$1': $2",obj.name,obj.path),5)
|
||||
end
|
||||
elseif name then
|
||||
LOG("No BGM: "..name,5)
|
||||
end
|
||||
end
|
||||
|
||||
local BGM={}
|
||||
|
||||
function BGM.getList() return nameList end
|
||||
function BGM.getCount() return #nameList end
|
||||
|
||||
function BGM.setDefault(bgms)
|
||||
if type(bgms)=='string' then
|
||||
bgms={bgms}
|
||||
elseif type(bgms)=='table' then
|
||||
for i=1,#bgms do assert(type(bgms[i])=='string',"BGM list must be list of strings") end
|
||||
else
|
||||
error("BGM.setDefault(bgms): bgms must be string or table")
|
||||
end
|
||||
defaultBGM=bgms
|
||||
end
|
||||
function BGM.setMaxSources(count)
|
||||
assert(type(count)=='number' and count>0 and count%1==0,"BGM.setMaxSources(count): count must be positive integer")
|
||||
maxLoadedCount=count
|
||||
_updateSources()
|
||||
end
|
||||
function BGM.setVol(vol)
|
||||
assert(type(vol)=='number' and vol>=0 and vol<=1,"BGM.setVol(vol): count must be in range 0~1")
|
||||
volume=vol
|
||||
for i=1,#nowPlay do
|
||||
local bgm=nowPlay[i]
|
||||
if not bgm.volChanging then
|
||||
bgm.source:setVolume(bgm.vol*vol)
|
||||
end
|
||||
end
|
||||
end
|
||||
function BGM.init(name,path)
|
||||
if type(name)=='table' then
|
||||
for k,v in next,name do
|
||||
_addFile(k,v)
|
||||
end
|
||||
else
|
||||
_addFile(name,path)
|
||||
end
|
||||
table.sort(nameList)
|
||||
LOG(BGM.getCount().." BGM files added")
|
||||
end
|
||||
|
||||
function BGM.play(bgms,args)
|
||||
if not args then args='' end
|
||||
if not bgms then bgms=defaultBGM end
|
||||
if not bgms then return end
|
||||
|
||||
if type(bgms)=='string' then bgms={bgms} end
|
||||
assert(type(bgms)=='table',"BGM.play(name,args): name must be string or table")
|
||||
|
||||
if
|
||||
TABLE.compare(lastPlay,bgms) and
|
||||
srcLib[lastPlay[1]] and srcLib[lastPlay[1]].source and
|
||||
srcLib[lastPlay[1]].source:isPlaying()
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
BGM.stop()
|
||||
|
||||
if not STRING.sArg(args,'-preLoad') then
|
||||
lastPlay=bgms
|
||||
end
|
||||
|
||||
for i=1,#bgms do
|
||||
local bgm=bgms[i]
|
||||
assert(type(bgm)=='string',"BGM list can only be list of string")
|
||||
if _tryLoad(bgm) and not STRING.sArg(args,'-preLoad') then
|
||||
local obj=srcLib[bgms[i]]
|
||||
obj.vol=0
|
||||
obj.pitch=1
|
||||
obj.lowgain=1
|
||||
obj.highgain=1
|
||||
obj.volChanging=false
|
||||
obj.pitchChanging=false
|
||||
obj.lowgainChanging=false
|
||||
obj.highgainChanging=false
|
||||
|
||||
_clearTask(obj)
|
||||
|
||||
local source=obj.source
|
||||
source:setLooping(not STRING.sArg(args,'-noloop'))
|
||||
source:setPitch(1)
|
||||
source:seek(0)
|
||||
source:setFilter()
|
||||
if STRING.sArg(args,'-sdin') then
|
||||
obj.vol=1
|
||||
source:setVolume(volume)
|
||||
BGM.set(bgm,'volume',1,0)
|
||||
else
|
||||
source:setVolume(0)
|
||||
BGM.set(bgm,'volume',1,.626)
|
||||
end
|
||||
source:play()
|
||||
|
||||
table.insert(nowPlay,obj)
|
||||
return true
|
||||
end
|
||||
end
|
||||
_updateSources()
|
||||
end
|
||||
function BGM.stop(time)
|
||||
if #nowPlay>0 then
|
||||
for i=1,#nowPlay do
|
||||
local obj=nowPlay[i]
|
||||
_clearTask(obj,'volume')
|
||||
if time==0 then
|
||||
obj.source:stop()
|
||||
obj.volChanging=false
|
||||
else
|
||||
TASK.new(task_setVolume,obj,0,time or .626,true)
|
||||
obj.volChanging=true
|
||||
end
|
||||
end
|
||||
TABLE.cut(nowPlay)
|
||||
lastPlay=NONE
|
||||
end
|
||||
end
|
||||
|
||||
---@param mode
|
||||
---| 'volume'
|
||||
---| 'lowgain'
|
||||
---| 'highgain'
|
||||
---| 'volume'
|
||||
---| 'pitch'
|
||||
---| 'seek'
|
||||
function BGM.set(bgms,mode,...)
|
||||
if type(bgms)=='string' then
|
||||
if bgms=='all' then
|
||||
bgms=nowPlay
|
||||
else
|
||||
bgms={srcLib[bgms]}
|
||||
end
|
||||
elseif type(bgms)=='table' then
|
||||
bgms=TABLE.shift(bgms)
|
||||
for i=1,#bgms do
|
||||
assert(type(bgms[i])=='string',"BGM list must be list of strings")
|
||||
bgms[i]=srcLib[bgms[i]]
|
||||
end
|
||||
else
|
||||
error("BGM.play(name,args): name must be string or table")
|
||||
end
|
||||
for i=1,#bgms do
|
||||
local obj=bgms[i]
|
||||
if obj.source then
|
||||
if mode=='volume' then
|
||||
_clearTask(obj,'volume')
|
||||
|
||||
local vol,time=...
|
||||
if not time then time=1 end
|
||||
|
||||
assert(type(vol)=='number' and vol>=0 and vol<=1,"BGM.set(...,volume): volume must be in range 0~1")
|
||||
assert(type(time)=='number' and time>=0,"BGM.set(...,time): time must be positive number")
|
||||
|
||||
TASK.new(task_setVolume,obj,vol,time)
|
||||
elseif mode=='pitch' then
|
||||
_clearTask(obj,'pitch')
|
||||
|
||||
local pitch,changeTime=...
|
||||
if not pitch then pitch=1 end
|
||||
if not changeTime then changeTime=1 end
|
||||
|
||||
assert(type(pitch)=='number' and pitch>0 and pitch<=32,"BGM.set(...,pitch): pitch must be in range 0~32")
|
||||
assert(type(changeTime)=='number' and changeTime>=0,"BGM.set(...,time): time must be positive number")
|
||||
|
||||
TASK.new(task_setPitch,obj,pitch,changeTime)
|
||||
elseif mode=='seek' then
|
||||
local time=...
|
||||
assert(type(time)=='number',"BGM.set(...,time): time must be number")
|
||||
obj.source:seek(MATH.clamp(time,0,obj.source:getDuration()))
|
||||
elseif mode=='lowgain' then
|
||||
if effectsSupported then
|
||||
_clearTask(obj,'lowgain')
|
||||
local lowgain,changeTime=...
|
||||
if not lowgain then lowgain=1 end
|
||||
if not changeTime then changeTime=1 end
|
||||
|
||||
assert(type(lowgain)=='number' and lowgain>=0 and lowgain<=1,"BGM.set(...,lowgain,highgain): lowgain must be in range 0~1")
|
||||
assert(type(changeTime)=='number' and changeTime>=0,"BGM.set(...,time): time must be positive number")
|
||||
|
||||
TASK.new(task_setLowgain,obj,lowgain,changeTime)
|
||||
obj.lowgain=lowgain
|
||||
obj.source:setFilter{type='bandpass',lowgain=obj.lowgain,highgain=obj.highgain,volume=1}
|
||||
end
|
||||
elseif mode=='highgain' then
|
||||
if effectsSupported then
|
||||
_clearTask(obj,'highgain')
|
||||
local highgain,changeTime=...
|
||||
if not highgain then highgain=1 end
|
||||
if not changeTime then changeTime=1 end
|
||||
|
||||
assert(type(highgain)=='number' and highgain>=0 and highgain<=1,"BGM.set(...,lowgain,highgain): highgain must be in range 0~1")
|
||||
assert(type(changeTime)=='number' and changeTime>=0,"BGM.set(...,time): time must be positive number")
|
||||
|
||||
TASK.new(task_setHighgain,obj,highgain,changeTime)
|
||||
obj.highgain=highgain
|
||||
obj.source:setFilter{type='bandpass',lowgain=obj.lowgain,highgain=obj.highgain,volume=1}
|
||||
end
|
||||
else
|
||||
error("BGM.set(...,mode): mode must be 'volume', 'pitch', or 'seek'")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BGM.getPlaying()
|
||||
return TABLE.shift(lastPlay)
|
||||
end
|
||||
function BGM.isPlaying()
|
||||
return #nowPlay>0 and nowPlay[1].source:isPlaying()
|
||||
end
|
||||
function BGM.tell()
|
||||
if nowPlay[1] then
|
||||
return nowPlay[1].source:tell()
|
||||
end
|
||||
end
|
||||
function BGM.getDuration()
|
||||
if nowPlay[1] then
|
||||
return nowPlay[1].source:getDuration()
|
||||
end
|
||||
end
|
||||
|
||||
return BGM
|
||||
366
Zframework/bitop.lua
Normal file
366
Zframework/bitop.lua
Normal file
@@ -0,0 +1,366 @@
|
||||
local M = {_TYPE='module', _NAME='bitop.funcs', _VERSION='1.0-0'}
|
||||
|
||||
local floor = math.floor
|
||||
|
||||
local MOD = 2 ^ 32
|
||||
local MODM = MOD - 1
|
||||
|
||||
local function memoize(f)
|
||||
|
||||
local mt = {}
|
||||
local t = setmetatable({}, mt)
|
||||
|
||||
function mt:__index(k)
|
||||
local v = f(k)
|
||||
t[k] = v
|
||||
return v
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
local function make_bitop_uncached(t, m)
|
||||
local function bitop(a, b)
|
||||
local res, p = 0, 1
|
||||
while a ~= 0 and b ~= 0 do
|
||||
local am, bm = a % m, b % m
|
||||
res = res + t[am][bm] * p
|
||||
a = (a - am) / m
|
||||
b = (b - bm) / m
|
||||
p = p * m
|
||||
end
|
||||
res = res + (a + b) * p
|
||||
return res
|
||||
end
|
||||
return bitop
|
||||
end
|
||||
|
||||
local function make_bitop(t)
|
||||
local op1 = make_bitop_uncached(t, 2 ^ 1)
|
||||
local op2 = memoize(function(a)
|
||||
return memoize(function(b)
|
||||
return op1(a, b)
|
||||
end)
|
||||
end)
|
||||
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
|
||||
end
|
||||
|
||||
-- ok? probably not if running on a 32-bit int Lua number type platform
|
||||
function M.tobit(x)
|
||||
return x % 2 ^ 32
|
||||
end
|
||||
|
||||
M.bxor = make_bitop{[0]={[0]=0, [1]=1}, [1]={[0]=1, [1]=0}, n=4}
|
||||
local bxor = M.bxor
|
||||
|
||||
function M.bnot(a)
|
||||
return MODM - a
|
||||
end
|
||||
local bnot = M.bnot
|
||||
|
||||
function M.band(a, b)
|
||||
return ((a + b) - bxor(a, b)) / 2
|
||||
end
|
||||
local band = M.band
|
||||
|
||||
function M.bor(a, b)
|
||||
return MODM - band(MODM - a, MODM - b)
|
||||
end
|
||||
local bor = M.bor
|
||||
|
||||
local lshift, rshift -- forward declare
|
||||
|
||||
function M.rshift(a, disp) -- Lua5.2 insipred
|
||||
if disp < 0 then
|
||||
return lshift(a, -disp)
|
||||
end
|
||||
return floor(a % 2 ^ 32 / 2 ^ disp)
|
||||
end
|
||||
rshift = M.rshift
|
||||
|
||||
function M.lshift(a, disp) -- Lua5.2 inspired
|
||||
if disp < 0 then
|
||||
return rshift(a, -disp)
|
||||
end
|
||||
return (a * 2 ^ disp) % 2 ^ 32
|
||||
end
|
||||
lshift = M.lshift
|
||||
|
||||
function M.tohex(x, n) -- BitOp style
|
||||
n = n or 8
|
||||
local up
|
||||
if n <= 0 then
|
||||
if n == 0 then
|
||||
return ''
|
||||
end
|
||||
up = true
|
||||
n = -n
|
||||
end
|
||||
x = band(x, 16 ^ n - 1)
|
||||
return ('%0' .. n .. (up and 'X' or 'x')):format(x)
|
||||
end
|
||||
local tohex = M.tohex
|
||||
|
||||
function M.extract(n, field, width) -- Lua5.2 inspired
|
||||
width = width or 1
|
||||
return band(rshift(n, field), 2 ^ width - 1)
|
||||
end
|
||||
local extract = M.extract
|
||||
|
||||
function M.replace(n, v, field, width) -- Lua5.2 inspired
|
||||
width = width or 1
|
||||
local mask1 = 2 ^ width - 1
|
||||
v = band(v, mask1) -- required by spec?
|
||||
local mask = bnot(lshift(mask1, field))
|
||||
return band(n, mask) + lshift(v, field)
|
||||
end
|
||||
local replace = M.replace
|
||||
|
||||
function M.bswap(x) -- BitOp style
|
||||
local a = band(x, 0xff);
|
||||
x = rshift(x, 8)
|
||||
local b = band(x, 0xff);
|
||||
x = rshift(x, 8)
|
||||
local c = band(x, 0xff);
|
||||
x = rshift(x, 8)
|
||||
local d = band(x, 0xff)
|
||||
return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
|
||||
end
|
||||
local bswap = M.bswap
|
||||
|
||||
function M.rrotate(x, disp) -- Lua5.2 inspired
|
||||
disp = disp % 32
|
||||
local low = band(x, 2 ^ disp - 1)
|
||||
return rshift(x, disp) + lshift(low, 32 - disp)
|
||||
end
|
||||
local rrotate = M.rrotate
|
||||
|
||||
function M.lrotate(x, disp) -- Lua5.2 inspired
|
||||
return rrotate(x, -disp)
|
||||
end
|
||||
local lrotate = M.lrotate
|
||||
|
||||
M.rol = M.lrotate -- LuaOp inspired
|
||||
M.ror = M.rrotate -- LuaOp insipred
|
||||
|
||||
function M.arshift(x, disp) -- Lua5.2 inspired
|
||||
local z = rshift(x, disp)
|
||||
if x >= 0x80000000 then
|
||||
z = z + lshift(2 ^ disp - 1, 32 - disp)
|
||||
end
|
||||
return z
|
||||
end
|
||||
local arshift = M.arshift
|
||||
|
||||
function M.btest(x, y) -- Lua5.2 inspired
|
||||
return band(x, y) ~= 0
|
||||
end
|
||||
|
||||
--
|
||||
-- Start Lua 5.2 "bit32" compat section.
|
||||
--
|
||||
|
||||
M.bit32 = {} -- Lua 5.2 'bit32' compatibility
|
||||
|
||||
local function bit32_bnot(x)
|
||||
return (-1 - x) % MOD
|
||||
end
|
||||
M.bit32.bnot = bit32_bnot
|
||||
|
||||
local function bit32_bxor(a, b, c, ...)
|
||||
local z
|
||||
if b then
|
||||
a = a % MOD
|
||||
b = b % MOD
|
||||
z = bxor(a, b)
|
||||
if c then
|
||||
z = bit32_bxor(z, c, ...)
|
||||
end
|
||||
return z
|
||||
elseif a then
|
||||
return a % MOD
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
M.bit32.bxor = bit32_bxor
|
||||
|
||||
local function bit32_band(a, b, c, ...)
|
||||
local z
|
||||
if b then
|
||||
a = a % MOD
|
||||
b = b % MOD
|
||||
z = ((a + b) - bxor(a, b)) / 2
|
||||
if c then
|
||||
z = bit32_band(z, c, ...)
|
||||
end
|
||||
return z
|
||||
elseif a then
|
||||
return a % MOD
|
||||
else
|
||||
return MODM
|
||||
end
|
||||
end
|
||||
M.bit32.band = bit32_band
|
||||
|
||||
local function bit32_bor(a, b, c, ...)
|
||||
local z
|
||||
if b then
|
||||
a = a % MOD
|
||||
b = b % MOD
|
||||
z = MODM - band(MODM - a, MODM - b)
|
||||
if c then
|
||||
z = bit32_bor(z, c, ...)
|
||||
end
|
||||
return z
|
||||
elseif a then
|
||||
return a % MOD
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
M.bit32.bor = bit32_bor
|
||||
|
||||
function M.bit32.btest(...)
|
||||
return bit32_band(...) ~= 0
|
||||
end
|
||||
|
||||
function M.bit32.lrotate(x, disp)
|
||||
return lrotate(x % MOD, disp)
|
||||
end
|
||||
|
||||
function M.bit32.rrotate(x, disp)
|
||||
return rrotate(x % MOD, disp)
|
||||
end
|
||||
|
||||
function M.bit32.lshift(x, disp)
|
||||
if disp > 31 or disp < -31 then
|
||||
return 0
|
||||
end
|
||||
return lshift(x % MOD, disp)
|
||||
end
|
||||
|
||||
function M.bit32.rshift(x, disp)
|
||||
if disp > 31 or disp < -31 then
|
||||
return 0
|
||||
end
|
||||
return rshift(x % MOD, disp)
|
||||
end
|
||||
|
||||
function M.bit32.arshift(x, disp)
|
||||
x = x % MOD
|
||||
if disp >= 0 then
|
||||
if disp > 31 then
|
||||
return (x >= 0x80000000) and MODM or 0
|
||||
else
|
||||
local z = rshift(x, disp)
|
||||
if x >= 0x80000000 then
|
||||
z = z + lshift(2 ^ disp - 1, 32 - disp)
|
||||
end
|
||||
return z
|
||||
end
|
||||
else
|
||||
return lshift(x, -disp)
|
||||
end
|
||||
end
|
||||
|
||||
function M.bit32.extract(x, field, ...)
|
||||
local width = ... or 1
|
||||
if field < 0 or field > 31 or width < 0 or field + width > 32 then
|
||||
error'out of range'
|
||||
end
|
||||
x = x % MOD
|
||||
return extract(x, field, ...)
|
||||
end
|
||||
|
||||
function M.bit32.replace(x, v, field, ...)
|
||||
local width = ... or 1
|
||||
if field < 0 or field > 31 or width < 0 or field + width > 32 then
|
||||
error'out of range'
|
||||
end
|
||||
x = x % MOD
|
||||
v = v % MOD
|
||||
return replace(x, v, field, ...)
|
||||
end
|
||||
|
||||
--
|
||||
-- Start LuaBitOp "bit" compat section.
|
||||
--
|
||||
|
||||
M.bit = {} -- LuaBitOp "bit" compatibility
|
||||
|
||||
function M.bit.tobit(x)
|
||||
x = x % MOD
|
||||
if x >= 0x80000000 then
|
||||
x = x - MOD
|
||||
end
|
||||
return x
|
||||
end
|
||||
local bit_tobit = M.bit.tobit
|
||||
|
||||
function M.bit.tohex(x, ...)
|
||||
return tohex(x % MOD, ...)
|
||||
end
|
||||
|
||||
function M.bit.bnot(x)
|
||||
return bit_tobit(bnot(x % MOD))
|
||||
end
|
||||
|
||||
local function bit_bor(a, b, c, ...)
|
||||
if c then
|
||||
return bit_bor(bit_bor(a, b), c, ...)
|
||||
elseif b then
|
||||
return bit_tobit(bor(a % MOD, b % MOD))
|
||||
else
|
||||
return bit_tobit(a)
|
||||
end
|
||||
end
|
||||
M.bit.bor = bit_bor
|
||||
|
||||
local function bit_band(a, b, c, ...)
|
||||
if c then
|
||||
return bit_band(bit_band(a, b), c, ...)
|
||||
elseif b then
|
||||
return bit_tobit(band(a % MOD, b % MOD))
|
||||
else
|
||||
return bit_tobit(a)
|
||||
end
|
||||
end
|
||||
M.bit.band = bit_band
|
||||
|
||||
local function bit_bxor(a, b, c, ...)
|
||||
if c then
|
||||
return bit_bxor(bit_bxor(a, b), c, ...)
|
||||
elseif b then
|
||||
return bit_tobit(bxor(a % MOD, b % MOD))
|
||||
else
|
||||
return bit_tobit(a)
|
||||
end
|
||||
end
|
||||
M.bit.bxor = bit_bxor
|
||||
|
||||
function M.bit.lshift(x, n)
|
||||
return bit_tobit(lshift(x % MOD, n % 32))
|
||||
end
|
||||
|
||||
function M.bit.rshift(x, n)
|
||||
return bit_tobit(rshift(x % MOD, n % 32))
|
||||
end
|
||||
|
||||
function M.bit.arshift(x, n)
|
||||
return bit_tobit(arshift(x % MOD, n % 32))
|
||||
end
|
||||
|
||||
function M.bit.rol(x, n)
|
||||
return bit_tobit(lrotate(x % MOD, n % 32))
|
||||
end
|
||||
|
||||
function M.bit.ror(x, n)
|
||||
return bit_tobit(rrotate(x % MOD, n % 32))
|
||||
end
|
||||
|
||||
function M.bit.bswap(x)
|
||||
return bit_tobit(bswap(x % MOD))
|
||||
end
|
||||
|
||||
return M
|
||||
235
Zframework/color.lua
Normal file
235
Zframework/color.lua
Normal file
@@ -0,0 +1,235 @@
|
||||
local abs=math.abs
|
||||
|
||||
-- Converts from HSV to RGB color. All arguments should be between 0 and 1, inclusively.
|
||||
local function HSVToRGB(h,s,v,a)
|
||||
if s<=0 then return v,v,v,a end
|
||||
h=h%1*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 function RGBToHSV(r,g,b,a)
|
||||
local max=math.max(r,g,b) -- = value
|
||||
local min=math.min(r,g,b)
|
||||
local chroma=max-min
|
||||
local hue=(
|
||||
max==min and 0 or
|
||||
max==r and (g-b)/chroma%6/6 or
|
||||
max==g and (2+(b-r)/chroma)/6 or
|
||||
(4+(r-g)/chroma)/6
|
||||
)
|
||||
local saturation=max==0 and 0 or chroma/max
|
||||
return hue,saturation,max,a
|
||||
end
|
||||
|
||||
local COLOR={
|
||||
hsv=HSVToRGB, -- backwards compatibility
|
||||
HSVToRGB=HSVToRGB,
|
||||
RGBToHSV=RGBToHSV,
|
||||
|
||||
|
||||
red= {HSVToRGB(0.00, 0.89, 0.91)},
|
||||
fire= {HSVToRGB(0.04, 0.93, 0.94)},
|
||||
orange= {HSVToRGB(0.09, 0.99, 0.96)},
|
||||
yellow= {HSVToRGB(0.15, 0.82, 0.90)},
|
||||
lime= {HSVToRGB(0.20, 0.89, 0.88)},
|
||||
jade= {HSVToRGB(0.25, 1.00, 0.82)},
|
||||
green= {HSVToRGB(0.33, 1.00, 0.81)},
|
||||
aqua= {HSVToRGB(0.47, 1.00, 0.76)},
|
||||
cyan= {HSVToRGB(0.53, 1.00, 0.88)},
|
||||
navy= {HSVToRGB(0.56, 1.00, 1.00)},
|
||||
sea= {HSVToRGB(0.61, 1.00, 1.00)},
|
||||
blue= {HSVToRGB(0.64, 1.00, 0.95)},
|
||||
violet= {HSVToRGB(0.74, 1.00, 0.91)},
|
||||
purple= {HSVToRGB(0.80, 1.00, 0.81)},
|
||||
magenta= {HSVToRGB(0.86, 1.00, 0.78)},
|
||||
wine= {HSVToRGB(0.92, 0.98, 0.91)},
|
||||
|
||||
lRed= {HSVToRGB(0.00, 0.38, 0.93)},
|
||||
lFire= {HSVToRGB(0.04, 0.45, 0.91)},
|
||||
lOrange= {HSVToRGB(0.10, 0.53, 0.92)},
|
||||
lYellow= {HSVToRGB(0.14, 0.61, 0.95)},
|
||||
lLime= {HSVToRGB(0.20, 0.66, 0.92)},
|
||||
lJade= {HSVToRGB(0.26, 0.56, 0.90)},
|
||||
lGreen= {HSVToRGB(0.34, 0.49, 0.89)},
|
||||
lAqua= {HSVToRGB(0.47, 0.59, 0.86)},
|
||||
lCyan= {HSVToRGB(0.51, 0.77, 0.88)},
|
||||
lNavy= {HSVToRGB(0.54, 0.80, 0.95)},
|
||||
lSea= {HSVToRGB(0.57, 0.72, 0.97)},
|
||||
lBlue= {HSVToRGB(0.64, 0.44, 0.96)},
|
||||
lViolet= {HSVToRGB(0.72, 0.47, 0.95)},
|
||||
lPurple= {HSVToRGB(0.80, 0.62, 0.89)},
|
||||
lMagenta= {HSVToRGB(0.86, 0.61, 0.89)},
|
||||
lWine= {HSVToRGB(0.93, 0.57, 0.92)},
|
||||
|
||||
dRed= {HSVToRGB(0.00, 0.80, 0.48)},
|
||||
dFire= {HSVToRGB(0.04, 0.80, 0.34)},
|
||||
dOrange= {HSVToRGB(0.07, 0.80, 0.39)},
|
||||
dYellow= {HSVToRGB(0.12, 0.80, 0.37)},
|
||||
dLime= {HSVToRGB(0.20, 0.80, 0.26)},
|
||||
dJade= {HSVToRGB(0.29, 0.80, 0.27)},
|
||||
dGreen= {HSVToRGB(0.33, 0.80, 0.26)},
|
||||
dAqua= {HSVToRGB(0.46, 0.80, 0.24)},
|
||||
dCyan= {HSVToRGB(0.50, 0.80, 0.30)},
|
||||
dNavy= {HSVToRGB(0.58, 0.80, 0.42)},
|
||||
dSea= {HSVToRGB(0.64, 0.80, 0.40)},
|
||||
dBlue= {HSVToRGB(0.67, 0.80, 0.34)},
|
||||
dViolet= {HSVToRGB(0.71, 0.80, 0.35)},
|
||||
dPurple= {HSVToRGB(0.76, 0.80, 0.32)},
|
||||
dMagenta= {HSVToRGB(0.87, 0.80, 0.28)},
|
||||
dWine= {HSVToRGB(0.92, 0.80, 0.28)},
|
||||
|
||||
black= {HSVToRGB(0.04, 0.04, 0.14)},
|
||||
dGray= {HSVToRGB(0.02, 0.05, 0.44)},
|
||||
gray= {HSVToRGB(0.02, 0.05, 0.65)},
|
||||
lGray= {HSVToRGB(0.02, 0.06, 0.86)},
|
||||
white= {HSVToRGB(0.01, 0.02, 0.99)},
|
||||
|
||||
xGray= {HSVToRGB(0.00, 0.00, 0.35,.8)},
|
||||
lxGray= {HSVToRGB(0.00, 0.00, 0.62,.8)},
|
||||
dxGray= {HSVToRGB(0.00, 0.00, 0.16,.8)},
|
||||
}
|
||||
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',
|
||||
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',
|
||||
X='xGray',lX='lxGray',dX='dxGray',
|
||||
-- Remain letter: EIKQTU
|
||||
} do
|
||||
COLOR[k]=COLOR[v]
|
||||
end
|
||||
setmetatable(COLOR,{__index=function(_,k)
|
||||
error("No color: "..tostring(k))
|
||||
end})
|
||||
|
||||
|
||||
do-- Random generators
|
||||
local rnd=math.random
|
||||
local list_norm={'red','fire','orange','yellow','lime','jade','green','aqua','cyan','navy','sea','blue','violet','purple','magenta','wine'}
|
||||
local len_list_norm=#list_norm
|
||||
function COLOR.random_norm()
|
||||
return COLOR[list_norm[rnd(len_list_norm)]]
|
||||
end
|
||||
|
||||
local list_bright={'lRed','lFire','lOrange','lYellow','lLime','lJade','lGreen','lAqua','lCyan','lNavy','lSea','lBlue','lViolet','lPurple','lMagenta','lWine'}
|
||||
local len_list_bright=#list_bright
|
||||
function COLOR.random_bright()
|
||||
return COLOR[list_bright[rnd(len_list_bright)]]
|
||||
end
|
||||
|
||||
local list_dark={'dRed','dFire','dOrange','dYellow','dLime','dJade','dGreen','dAqua','dCyan','dNavy','dSea','dBlue','dViolet','dPurple','dMagenta','dWine'}
|
||||
local len_list_dark=#list_dark
|
||||
function COLOR.random_dark()
|
||||
return COLOR[list_dark[rnd(len_list_dark)]]
|
||||
end
|
||||
end
|
||||
|
||||
do-- Rainbow generators
|
||||
local twoThirdsOfPi=2*math.pi/3
|
||||
local sin=math.sin
|
||||
function COLOR.rainbow(phase,alpha)
|
||||
return
|
||||
sin(phase)*.4+.6,
|
||||
sin(phase+twoThirdsOfPi)*.4+.6,
|
||||
sin(phase-twoThirdsOfPi)*.4+.6,
|
||||
alpha
|
||||
end
|
||||
function COLOR.rainbow_light(phase,alpha)
|
||||
return
|
||||
sin(phase)*.2+.7,
|
||||
sin(phase+twoThirdsOfPi)*.2+.7,
|
||||
sin(phase-twoThirdsOfPi)*.2+.7,
|
||||
alpha
|
||||
end
|
||||
function COLOR.rainbow_dark(phase,alpha)
|
||||
return
|
||||
sin(phase)*.2+.4,
|
||||
sin(phase+twoThirdsOfPi)*.2+.4,
|
||||
sin(phase-twoThirdsOfPi)*.2+.4,
|
||||
alpha
|
||||
end
|
||||
function COLOR.rainbow_gray(phase,alpha)
|
||||
return
|
||||
sin(phase)*.16+.5,
|
||||
sin(phase+twoThirdsOfPi)*.16+.5,
|
||||
sin(phase-twoThirdsOfPi)*.16+.5,
|
||||
alpha
|
||||
end
|
||||
end
|
||||
|
||||
do -- Color interpolation https://www.alanzucconi.com/2016/01/06/colour-interpolation/
|
||||
local lerp=MATH.mix
|
||||
function COLOR.interpolateRGB(rgba1,rgba2,t)
|
||||
return
|
||||
lerp(rgba1[1],rgba2[1],t),
|
||||
lerp(rgba1[2],rgba2[2],t),
|
||||
lerp(rgba1[3],rgba2[3],t),
|
||||
((rgba1[4] and rgba2[4]) and lerp(rgba1[4],rgba1[4],t) or nil)
|
||||
end
|
||||
|
||||
function COLOR.interpolateHSV(hsv1,hsv2,t)
|
||||
local hue1,hue2=hsv1[1],hsv2[1]
|
||||
if hue1>hue2 then
|
||||
hue1,hue2=hue2,hue1
|
||||
t=1-t
|
||||
end
|
||||
|
||||
local hueDiff=hue2-hue1
|
||||
local finalHue=.0
|
||||
if hueDiff>.5 then
|
||||
hue1=hue1+1
|
||||
finalHue=(hue1+t*(hue2-hue1))%1;
|
||||
else
|
||||
finalHue=hue1+t*hueDiff
|
||||
end
|
||||
|
||||
return finalHue,
|
||||
lerp(hsv1[2],hsv2[2],t),
|
||||
lerp(hsv1[3],hsv2[3],t),
|
||||
((hsv1[4] and hsv2[4]) and lerp(hsv1[4],hsv1[4],t) or nil)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns either color1 or color2 based on time.
|
||||
Args:
|
||||
- color1, color2: colors to switch between
|
||||
- period: the length of time in a cycle in seconds. ("wavelength")
|
||||
- percentage [optional]: percentage of time in the color1 phase (default: 50%)
|
||||
]]
|
||||
function COLOR.flicker(color1,color2,period,percentage)
|
||||
percentage=percentage or .5
|
||||
return TIME()%period>percentage*period and color1 or color2
|
||||
end
|
||||
|
||||
local lerpRGB,lerpHSV=COLOR.interpolateRGB,COLOR.interpolateHSV
|
||||
local tau=MATH.tau
|
||||
--[[
|
||||
Oscillates between color1 and color2 over time in a sinusoidal fashion.
|
||||
Args:
|
||||
- color1, color2: colors to switch between.
|
||||
[FORMAT IS BASED ON TYPE, WHICH DEFAULTS TO HSV]
|
||||
Use COLOR.HSVtoRGB() and/or COLOR.RGBtoHSV to convert between color formats.
|
||||
- period: the length of time in a cycle in seconds. (wavelength)
|
||||
- type [optional]: the type of interpolation, defaulting to 'hsv'.
|
||||
Supported values: nil, 'hsv', 'rgb'
|
||||
]]
|
||||
function COLOR.sine(color1,color2,period,type)
|
||||
type=type or 'hsv'
|
||||
local t=math.sin(tau*TIME()/period)
|
||||
if type=='hsv' then
|
||||
return lerpHSV(color1, color2, t)
|
||||
elseif type=='rgb' then
|
||||
return lerpRGB(color1, color2, t)
|
||||
end
|
||||
end
|
||||
|
||||
return COLOR
|
||||
48
Zframework/diacritics.txt
Normal file
48
Zframework/diacritics.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
Á=A,Ă=A,Ắ=A,Ặ=A,Ằ=A,Ẳ=A,Ẵ=A,Ǎ=A,Â=A,Ấ=A,Ậ=A,Ầ=A,Ẩ=A,Ẫ=A,Ä=A,Ạ=A,À=A,Ả=A,Ā=A,Ą=A,Å=A,Ǻ=A,Ã=A,Æ=AE,Ǽ=AE
|
||||
Ḅ=B,Ɓ=B,ʚ=B,ɞ=B
|
||||
Ć=C,Č=C,Ç=C,Ĉ=C,Ċ=C,Ɔ=C,ʗ=C
|
||||
Ď=D,Ḓ=D,Ḍ=D,Ɗ=D,Ḏ=D,Dz=DZ,Dž=DZ,Đ=D,Ð=D,DZ=DZ,DŽ=DZ
|
||||
É=E,Ĕ=E,Ě=E,Ê=E,Ế=E,Ệ=E,Ề=E,Ể=E,Ễ=E,Ë=E,Ė=E,Ẹ=E,È=E,Ẻ=E,Ē=E,Ę=E,Ẽ=E,Ɛ=E,Ə=E
|
||||
Ƒ=F
|
||||
Ǵ=G,Ğ=G,Ǧ=G,Ģ=G,Ĝ=G,Ġ=G,Ḡ=G,ʛ=G
|
||||
Ḫ=H,Ĥ=H,Ḥ=H,Ħ=H
|
||||
Í=I,Ĭ=I,Ǐ=I,Î=I,Ï=I,İ=I,Ị=I,Ì=I,Ỉ=I,Ī=I,Į=I,Ĩ=I,IJ=IJ
|
||||
Ĵ=J
|
||||
Ķ=K,Ḳ=K,Ƙ=K,Ḵ=K
|
||||
Ĺ=L,Ƚ=L,Ľ=L,Ļ=L,Ḽ=L,Ḷ=L,Ḹ=L,Ḻ=L,Ŀ=L,Lj=Lj,Ł=L,LJ=LJ
|
||||
Ḿ=M,Ṁ=M,Ṃ=M
|
||||
Ń=N,Ň=N,Ņ=N,Ṋ=N,Ṅ=N,Ṇ=N,Ǹ=N,Ɲ=N,Ṉ=N,Nj=Nj,Ñ=N,NJ=NJ
|
||||
Ó=O,Ŏ=O,Ǒ=O,Ô=O,Ố=O,Ộ=O,Ồ=O,Ổ=O,Ỗ=O,Ö=O,Ọ=O,Ő=O,Ò=O,Ỏ=O,Ơ=O,Ớ=O,Ợ=O,Ờ=O,Ở=O,Ỡ=O,Ō=O,Ɵ=O,Ǫ=O,Ø=O,Ǿ=O,Õ=O,Œ=OE,ɶ=Oe
|
||||
Þ=P
|
||||
Ŕ=R,Ř=R,Ŗ=R,Ṙ=R,Ṛ=R,Ṝ=R,Ṟ=R,ʁ=R
|
||||
Ś=S,Š=S,Ş=S,Ŝ=S,Ș=S,Ṡ=S,Ṣ=S,ẞ=S
|
||||
Ť=T,Ţ=T,Ṱ=T,Ț=T,Ṭ=T,Ṯ=T,Ŧ=T,Þ=T,Ð=T
|
||||
Ú=U,Ŭ=U,Ǔ=U,Û=U,Ü=U,Ǘ=U,Ǚ=U,Ǜ=U,Ǖ=U,Ụ=U,Ű=U,Ù=U,Ủ=U,Ư=U,Ứ=U,Ự=U,Ừ=U,Ử=U,Ữ=U,Ū=U,Ų=U,Ů=U,Ũ=U
|
||||
Ẃ=W,Ŵ=W,Ẅ=W,Ẁ=W,ʬ=W
|
||||
Ý=Y,Ŷ=Y,Ÿ=Y,Ẏ=Y,Ỵ=Y,Ỳ=Y,Ƴ=Y,Ỷ=Y,Ȳ=Y,Ỹ=Y
|
||||
Ź=Z,Ž=Z,Ż=Z,Ẓ=Z,Ẕ=Z,Ƶ=Z
|
||||
á=a,ă=a,ắ=a,ặ=a,ằ=a,ẳ=a,ẵ=a,ǎ=a,â=a,ấ=a,ậ=a,ầ=a,ẩ=a,ẫ=a,ä=a,ạ=a,à=a,ả=a,ā=a,ą=a,å=a,ǻ=a,ã=a,æ=a,ǽ=a,ɑ=a,ɐ=a,ɒ=a
|
||||
ḅ=b,ɓ=b,ß=b
|
||||
ć=c,č=c,ç=c,ĉ=c,ɕ=c,ċ=c
|
||||
ď=d,ḓ=d,ḍ=d,ɗ=d,ḏ=d,đ=d,ɖ=d,ʤ=d,dz=d,ʣ=d,ʥ=d,dž=d,ð=d
|
||||
é=e,ĕ=e,ě=e,ê=e,ế=e,ệ=e,ề=e,ể=e,ễ=e,ë=e,ė=e,ẹ=e,è=e,ẻ=e,ē=e,ę=e,ẽ=e,ʒ=e,ǯ=e,ʓ=e,ɘ=e,ɜ=e,ɝ=e,ə=e,ɚ=e,ʚ=e,ɞ=e
|
||||
ƒ=f,ſ=f,ʩ=f,fi=f,fl=f,ʃ=f,ʆ=f,ʅ=f,ɟ=f,ʄ=f
|
||||
ǵ=g,ğ=g,ǧ=g,ģ=g,ĝ=g,ġ=g,ɠ=g,ḡ=g,ɡ=g,ɣ=g
|
||||
ḫ=h,ĥ=h,ḥ=h,ɦ=h,ẖ=h,ħ=h,ɧ=h,ɥ=h,ʮ=h,ʯ=h,ų=h
|
||||
í=i,ĭ=i,ǐ=i,î=i,ï=i,ị=i,ì=i,ỉ=i,ī=i,į=i,ɨ=i,ĩ=i,ɩ=i,ı=i,ij=ij,ɟ=i
|
||||
ǰ=j,ĵ=j,ʝ=j,ȷ=j,ɟ=j,ʄ=j
|
||||
ķ=k,ḳ=k,ƙ=k,ḵ=k,ĸ=k,ʞ=k
|
||||
ĺ=l,ƚ=l,ɬ=l,ľ=l,ļ=l,ḽ=l,ḷ=l,ḹ=l,ḻ=l,ŀ=l,ɫ=l,ɭ=l,ł=l,ƛ=l,ɮ=lz,lj=lj,ʪ=ls,ʫ=lz
|
||||
ḿ=m,ṁ=m,ṃ=m,ɱ=m,ɯ=m,ɰ=m
|
||||
ʼn=n,ń=n,ň=n,ņ=n,ṋ=n,ṅ=n,ṇ=n,ǹ=n,ɲ=n,ṉ=n,ɳ=n,ñ=n,nj=nj,ŋ=n,Ŋ=n
|
||||
ó=o,ŏ=o,ǒ=o,ô=o,ố=o,ộ=o,ồ=o,ổ=o,ỗ=o,ö=o,ọ=o,ő=o,ò=o,ỏ=o,ơ=o,ớ=o,ợ=o,ờ=o,ở=o,ỡ=o,ō=o,ǫ=o,ø=o,ǿ=o,õ=o,ɛ=o,ɔ=o,ɵ=o,ʘ=o,œ=oe
|
||||
ɸ=p,þ=p
|
||||
ʠ=q
|
||||
ŕ=r,ř=r,ŗ=r,ṙ=r,ṛ=r,ṝ=r,ɾ=r,ṟ=r,ɼ=r,ɽ=r,ɿ=r,ɹ=r,ɻ=r,ɺ=r
|
||||
ś=s,š=s,ş=s,ŝ=s,ș=s,ṡ=s,ṣ=s,ʂ=s,ſ=s,ʃ=s,ʆ=s,ß=s,ʅ=s
|
||||
ť=t,ţ=t,ṱ=t,ț=t,ẗ=t,ṭ=t,ṯ=t,ʈ=t,ŧ=t,ʨ=t,ʧ=t,þ=t,ð=t,ʦ=t,ʇ=t
|
||||
ʉ=u,ú=u,ŭ=u,ǔ=u,û=u,ü=u,ǘ=u,ǚ=u,ǜ=u,ǖ=u,ụ=u,ű=u,ù=u,ủ=u,ư=u,ứ=u,ự=u,ừ=u,ử=u,ữ=u,ū=u,ų=u,ů=u,ũ=u,ʊ=u
|
||||
ʋ=v,ʌ=v
|
||||
ẃ=w,ŵ=w,ẅ=w,ẁ=w,ʍ=w
|
||||
ý=y,ŷ=y,ÿ=y,ẏ=y,ỵ=y,ỳ=y,ƴ=y,ỷ=y,ȳ=y,ỹ=y,ʎ=y
|
||||
ź=z,ž=z,ʑ=z,ż=z,ẓ=z,ẕ=z,ʐ=z,ƶ=z
|
||||
112
Zframework/file.lua
Normal file
112
Zframework/file.lua
Normal file
@@ -0,0 +1,112 @@
|
||||
local fs=love.filesystem
|
||||
local FILE={}
|
||||
function FILE.isSafe(file)
|
||||
return SYSTEM=='Web' or fs.getRealDirectory(file)~=fs.getSaveDirectory()
|
||||
end
|
||||
function FILE.load(name,args)
|
||||
if not args then args='' end
|
||||
if fs.getInfo(name) then
|
||||
local F=fs.newFile(name)
|
||||
assert(F:open'r','open error')
|
||||
local s=F:read() F:close()
|
||||
local mode=
|
||||
STRING.sArg(args,'-luaon') and 'luaon' or
|
||||
STRING.sArg(args,'-lua') and 'lua' or
|
||||
STRING.sArg(args,'-json') and 'json' or
|
||||
STRING.sArg(args,'-string') and 'string' or
|
||||
s:sub(1,9):find('return%s*%{') and 'luaon' or
|
||||
(s:sub(1,1)=='[' and s:sub(-1)==']' or s:sub(1,1)=='{' and s:sub(-1)=='}') and 'json' or
|
||||
'string'
|
||||
if mode=='luaon' then
|
||||
local func,err_mes=loadstring(s)
|
||||
if func then
|
||||
setfenv(func,{})
|
||||
local res=func()
|
||||
return assert(res,'decode error')
|
||||
else
|
||||
error('decode error: '..err_mes)
|
||||
end
|
||||
elseif mode=='lua' then
|
||||
local func,err_mes=loadstring(s)
|
||||
if func then
|
||||
local res=func()
|
||||
return assert(res,'run error')
|
||||
else
|
||||
error('compile error: '..err_mes)
|
||||
end
|
||||
elseif mode=='json' then
|
||||
local res=JSON.decode(s)
|
||||
if res then
|
||||
return res
|
||||
end
|
||||
error('decode error')
|
||||
elseif mode=='string' then
|
||||
return s
|
||||
else
|
||||
error('unknown mode')
|
||||
end
|
||||
elseif not STRING.sArg(args,'-canskip') then
|
||||
error('no file')
|
||||
end
|
||||
end
|
||||
function FILE.save(data,name,args)
|
||||
if not args then args='' end
|
||||
if STRING.sArg(args,'-d') and fs.getInfo(name) then
|
||||
error('duplicate')
|
||||
end
|
||||
|
||||
if type(data)=='table' then
|
||||
if STRING.sArg(args,'-luaon') then
|
||||
if STRING.sArg(args,'-expand') then
|
||||
data=TABLE.dump(data)
|
||||
else
|
||||
data='return'..TABLE.dumpDeflate(data)
|
||||
end
|
||||
if not data then
|
||||
error('encode error')
|
||||
end
|
||||
else
|
||||
data=JSON.encode(data)
|
||||
if not data then
|
||||
error('encode error')
|
||||
end
|
||||
end
|
||||
else
|
||||
data=tostring(data)
|
||||
end
|
||||
|
||||
local F=fs.newFile(name)
|
||||
assert(F:open('w'),'open error')
|
||||
F:write(data) F:flush() F:close()
|
||||
end
|
||||
function FILE.clear(path)
|
||||
if not FILE.isSafe(path) and fs.getInfo(path).type=='directory' then
|
||||
for _,name in next,fs.getDirectoryItems(path) do
|
||||
name=path..'/'..name
|
||||
if not FILE.isSafe(name) then
|
||||
local t=fs.getInfo(name).type
|
||||
if t=='file' then
|
||||
fs.remove(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function FILE.clear_s(path)
|
||||
if path=='' or (not FILE.isSafe(path) and fs.getInfo(path).type=='directory') then
|
||||
for _,name in next,fs.getDirectoryItems(path) do
|
||||
name=path..'/'..name
|
||||
if not FILE.isSafe(name) then
|
||||
local t=fs.getInfo(name).type
|
||||
if t=='file' then
|
||||
fs.remove(name)
|
||||
elseif t=='directory' then
|
||||
FILE.clear_s(name)
|
||||
fs.remove(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
fs.remove(path)
|
||||
end
|
||||
end
|
||||
return FILE
|
||||
59
Zframework/font.lua
Normal file
59
Zframework/font.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
local set=GC.setFont
|
||||
local fontFiles,fontCache={},{}
|
||||
local defaultFont,defaultFallBack
|
||||
local curFont=false-- Current using font object
|
||||
|
||||
local FONT={}
|
||||
function FONT.setDefault(name) defaultFont=name end
|
||||
function FONT.setFallback(name) defaultFallBack=name end
|
||||
function FONT.rawget(s)
|
||||
if not fontCache[s] then
|
||||
fontCache[s]=GC.setNewFont(s,'light',GC.getDPIScale()*SCR.k*2)
|
||||
end
|
||||
return fontCache[s]
|
||||
end
|
||||
function FONT.rawset(s)
|
||||
set(fontCache[s] or FONT.rawget(s))
|
||||
end
|
||||
function FONT.load(fonts)
|
||||
for name,path in next,fonts do
|
||||
assert(love.filesystem.getInfo(path),STRING.repD("Font file $1($2) not exist!",name,path))
|
||||
fontFiles[name]=love.filesystem.newFile(path)
|
||||
fontCache[name]={}
|
||||
end
|
||||
FONT.reset()
|
||||
end
|
||||
function FONT.get(size,name)
|
||||
if not name then name=defaultFont end
|
||||
local f=fontCache[name][size]
|
||||
if not f then
|
||||
f=GC.setNewFont(fontFiles[name],size,'light',GC.getDPIScale()*SCR.k*2)
|
||||
if defaultFallBack and name~=defaultFallBack then
|
||||
f:setFallbacks(FONT.get(size,defaultFallBack))
|
||||
end
|
||||
fontCache[name][size]=f
|
||||
end
|
||||
return f
|
||||
end
|
||||
function FONT.set(size,name)
|
||||
if not name then name=defaultFont end
|
||||
|
||||
local f=fontCache[name][size]
|
||||
if f~=curFont then
|
||||
curFont=f or FONT.get(size,name)
|
||||
set(curFont)
|
||||
end
|
||||
end
|
||||
function FONT.reset()
|
||||
for name,cache in next,fontCache do
|
||||
if type(cache)=='table' then
|
||||
for size in next,cache do
|
||||
cache[size]=FONT.get(size,name)
|
||||
end
|
||||
else
|
||||
fontCache[name]=FONT.rawget(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return FONT
|
||||
184
Zframework/gcExtend.lua
Normal file
184
Zframework/gcExtend.lua
Normal file
@@ -0,0 +1,184 @@
|
||||
local gc=love.graphics
|
||||
local setColor,printf,draw=gc.setColor,gc.printf,gc.draw
|
||||
local sin,cos=math.sin,math.cos
|
||||
|
||||
local GC=setmetatable({},{
|
||||
__index=gc,
|
||||
__metatable=true
|
||||
})
|
||||
function GC.mStr(obj,x,y) printf(obj,x-626,y,1252,'center') end-- Printf a string with 'center'
|
||||
function GC.simpX(obj,x,y) draw(obj,x-obj:getWidth()*.5,y) end-- Simply draw an obj with x=obj:getWidth()/2
|
||||
function GC.simpY(obj,x,y) draw(obj,x,y-obj:getHeight()*.5) end-- Simply draw an obj with y=obj:getWidth()/2
|
||||
function GC.X(obj,x,y,a,k) draw(obj,x,y,a,k,nil,obj:getWidth()*.5,0) end-- Draw an obj with x=obj:getWidth()/2
|
||||
function GC.Y(obj,x,y,a,k) draw(obj,x,y,a,k,nil,0,obj:getHeight()*.5) end-- Draw an obj with y=obj:getWidth()/2
|
||||
function GC.mDraw(obj,x,y,a,k) draw(obj,x,y,a,k,nil,obj:getWidth()*.5,obj:getHeight()*.5) end-- Draw an obj with both middle X & Y
|
||||
function GC.outDraw(obj,div,x,y,a,k)
|
||||
local w,h=obj:getWidth()*.5,obj:getHeight()*.5
|
||||
draw(obj,x-div,y-div,a,k,nil,w,h)
|
||||
draw(obj,x-div,y+div,a,k,nil,w,h)
|
||||
draw(obj,x+div,y-div,a,k,nil,w,h)
|
||||
draw(obj,x+div,y+div,a,k,nil,w,h)
|
||||
end
|
||||
function GC.shadedPrint(str,x,y,mode,d,clr1,clr2)
|
||||
local w=1280
|
||||
if mode=='center' then
|
||||
x=x-w*.5
|
||||
elseif mode=='right' then
|
||||
x=x-w
|
||||
end
|
||||
if not d then d=1 end
|
||||
setColor(clr1 or COLOR.D)
|
||||
printf(str,x-d,y-d,w,mode)
|
||||
printf(str,x-d,y+d,w,mode)
|
||||
printf(str,x+d,y-d,w,mode)
|
||||
printf(str,x+d,y+d,w,mode)
|
||||
setColor(clr2 or COLOR.Z)
|
||||
printf(str,x,y,w,mode)
|
||||
end
|
||||
function GC.regPolygon(mode,x,y,R,segments,phase)
|
||||
local l={}
|
||||
local ang=phase or 0
|
||||
local angStep=6.283185307179586/segments
|
||||
for i=1,segments do
|
||||
l[2*i-1]=x+R*cos(ang)
|
||||
l[2*i]=y+R*sin(ang)
|
||||
ang=ang+angStep
|
||||
end
|
||||
gc.polygon(mode,l)
|
||||
end
|
||||
function GC.regRoundPolygon(mode,x,y,R,segments,r,phase)
|
||||
local X,Y={},{}
|
||||
local ang=phase or 0
|
||||
local angStep=6.283185307179586/segments
|
||||
for i=1,segments do
|
||||
X[i]=x+R*cos(ang)
|
||||
Y[i]=y+R*sin(ang)
|
||||
ang=ang+angStep
|
||||
end
|
||||
X[segments+1]=x+R*cos(ang)
|
||||
Y[segments+1]=y+R*sin(ang)
|
||||
local halfAng=6.283185307179586/segments/2
|
||||
local erasedLen=r*math.tan(halfAng)
|
||||
if mode=='line' then
|
||||
erasedLen=erasedLen+1-- Fix 1px cover
|
||||
for i=1,segments do
|
||||
-- Line
|
||||
local x1,y1,x2,y2=X[i],Y[i],X[i+1],Y[i+1]
|
||||
local dir=math.atan2(y2-y1,x2-x1)
|
||||
gc.line(x1+erasedLen*cos(dir),y1+erasedLen*sin(dir),x2-erasedLen*cos(dir),y2-erasedLen*sin(dir))
|
||||
|
||||
-- Arc
|
||||
ang=ang+angStep
|
||||
local R2=R-r/cos(halfAng)
|
||||
local arcCX,arcCY=x+R2*cos(ang),y+R2*sin(ang)
|
||||
gc.arc('line','open',arcCX,arcCY,r,ang-halfAng,ang+halfAng)
|
||||
end
|
||||
elseif mode=='fill' then
|
||||
local L={}
|
||||
for i=1,segments do
|
||||
-- Line
|
||||
local x1,y1,x2,y2=X[i],Y[i],X[i+1],Y[i+1]
|
||||
local dir=math.atan2(y2-y1,x2-x1)
|
||||
L[4*i-3]=x1+erasedLen*cos(dir)
|
||||
L[4*i-2]=y1+erasedLen*sin(dir)
|
||||
L[4*i-1]=x2-erasedLen*cos(dir)
|
||||
L[4*i]=y2-erasedLen*sin(dir)
|
||||
|
||||
-- Arc
|
||||
ang=ang+angStep
|
||||
local R2=R-r/cos(halfAng)
|
||||
local arcCX,arcCY=x+R2*cos(ang),y+R2*sin(ang)
|
||||
gc.arc('fill','open',arcCX,arcCY,r,ang-halfAng,ang+halfAng)
|
||||
end
|
||||
gc.polygon('fill',L)
|
||||
else
|
||||
error("Draw mode should be 'line' or 'fill'")
|
||||
end
|
||||
end
|
||||
do-- function GC.DO(L)
|
||||
local cmds={
|
||||
origin="origin",
|
||||
move="translate",
|
||||
scale="scale",
|
||||
rotate="rotate",
|
||||
shear="shear",
|
||||
clear="clear",
|
||||
|
||||
setCL="setColor",
|
||||
setCM="setColorMask",
|
||||
setLW="setLineWidth",
|
||||
setLS="setLineStyle",
|
||||
setLJ="setLineJoin",
|
||||
setBM="setBlendMode",
|
||||
|
||||
print="print",
|
||||
rawFT=function(...)FONT.rawset(...) end,
|
||||
setFT=function(...)FONT.set(...) end,
|
||||
mText=GC.mStr,
|
||||
mDraw=GC.mDraw,
|
||||
mDrawX=GC.X,
|
||||
mDrawY=GC.Y,
|
||||
mOutDraw=GC.outDraw,
|
||||
|
||||
draw="draw",
|
||||
line="line",
|
||||
fRect=function(...)gc.rectangle('fill',...) end,
|
||||
dRect=function(...)gc.rectangle('line',...) end,
|
||||
fCirc=function(...)gc.circle('fill',...) end,
|
||||
dCirc=function(...)gc.circle('line',...) end,
|
||||
fElps=function(...)gc.ellipse('fill',...) end,
|
||||
dElps=function(...)gc.ellipse('line',...) end,
|
||||
fPoly=function(...)gc.polygon('fill',...) end,
|
||||
dPoly=function(...)gc.polygon('line',...) end,
|
||||
|
||||
dPie=function(...)gc.arc('line',...) end,
|
||||
dArc=function(...)gc.arc('line','open',...) end,
|
||||
dBow=function(...)gc.arc('line','closed',...) end,
|
||||
fPie=function(...)gc.arc('fill',...) end,
|
||||
fArc=function(...)gc.arc('fill','open',...) end,
|
||||
fBow=function(...)gc.arc('fill','closed',...) end,
|
||||
|
||||
fRPol=function(...)GC.regPolygon('fill',...) end,
|
||||
dRPol=function(...)GC.regPolygon('line',...) end,
|
||||
fRRPol=function(...)GC.regRoundPolygon('fill',...) end,
|
||||
dRRPol=function(...)GC.regRoundPolygon('line',...) end,
|
||||
}
|
||||
local sizeLimit=gc.getSystemLimits().texturesize
|
||||
function GC.DO(L)
|
||||
gc.push()
|
||||
local success,canvas
|
||||
repeat
|
||||
success,canvas=pcall(gc.newCanvas,math.min(L[1],sizeLimit),math.min(L[2],sizeLimit))
|
||||
if not success then
|
||||
sizeLimit=math.floor(sizeLimit*.8)
|
||||
end
|
||||
until success
|
||||
gc.setCanvas(canvas)
|
||||
gc.origin()
|
||||
gc.clear(1,1,1,0)
|
||||
gc.setColor(1,1,1)
|
||||
gc.setLineWidth(1)
|
||||
for i=3,#L do
|
||||
local cmd=L[i][1]
|
||||
if type(cmd)=='boolean' and cmd then
|
||||
table.remove(L[i],1)
|
||||
cmd=L[i][1]
|
||||
end
|
||||
if type(cmd)=='string' then
|
||||
local func=cmds[cmd] or gc[cmd]
|
||||
if type(func)=='string' then
|
||||
func=gc[func]
|
||||
end
|
||||
if func then
|
||||
func(unpack(L[i],2))
|
||||
else
|
||||
error("No gc command: "..cmd)
|
||||
end
|
||||
end
|
||||
end
|
||||
gc.setCanvas()
|
||||
gc.pop()
|
||||
return canvas
|
||||
end
|
||||
end
|
||||
return GC
|
||||
191
Zframework/http.lua
Normal file
191
Zframework/http.lua
Normal file
@@ -0,0 +1,191 @@
|
||||
local sendCHN=love.thread.getChannel('inputChannel')
|
||||
local recvCHN=love.thread.getChannel('outputChannel')
|
||||
|
||||
local threads={}
|
||||
local threadCount=0
|
||||
local threadCode=[[
|
||||
local id=...
|
||||
|
||||
local http=require'socket.http'
|
||||
local ltn12=require'ltn12'
|
||||
|
||||
local sendCHN=love.thread.getChannel('inputChannel')
|
||||
local recvCHN=love.thread.getChannel('outputChannel')
|
||||
|
||||
while true do
|
||||
local arg=sendCHN:demand()
|
||||
|
||||
if arg._destroy then
|
||||
recvCHN:push{
|
||||
destroy=true,
|
||||
id=id,
|
||||
}
|
||||
break
|
||||
end
|
||||
|
||||
-- print("\n------SEND------") for k,v in next,arg do print(k,v) end
|
||||
local data={}
|
||||
local _,code,detail=http.request{
|
||||
method=arg.method,
|
||||
url=arg.url,
|
||||
headers=arg.headers,
|
||||
source=ltn12.source.string(arg.body),
|
||||
|
||||
sink=ltn12.sink.table(data),
|
||||
}
|
||||
|
||||
local result={
|
||||
pool=arg.pool,
|
||||
poolPtr=arg.poolPtr,
|
||||
code=code,
|
||||
body=table.concat(data),
|
||||
detail=detail,
|
||||
}
|
||||
-- print("\n------RECV------") for k,v in next,result do print(k,v) end
|
||||
recvCHN:push(result)
|
||||
end
|
||||
]]
|
||||
|
||||
local msgPool=setmetatable({},{
|
||||
__index=function(self,k)
|
||||
self[k]={}
|
||||
return self[k]
|
||||
end
|
||||
})
|
||||
|
||||
local HTTP={
|
||||
_msgCount=0,
|
||||
_trigTime=0,
|
||||
_trigInterval=.26,
|
||||
_host=false,
|
||||
}
|
||||
|
||||
local function addThread(num)
|
||||
for i=1,26 do
|
||||
if num<=0 then break end
|
||||
if not threads[i] then
|
||||
threads[i]=love.thread.newThread(threadCode)
|
||||
threads[i]:start(i)
|
||||
threadCount=threadCount+1
|
||||
num=num-1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HTTP.request(arg)
|
||||
arg.method=arg.method or arg.body and 'POST' or 'GET'
|
||||
if arg.url then
|
||||
assert(type(arg.url)=='string',"Field 'url' need string, get "..type(arg.url))
|
||||
if arg.url:sub(1,7)~='http://' then arg.url='http://'..arg.url end
|
||||
else
|
||||
arg.url=HTTP._host or error("Need url=<string> or set default host with HTTP.setHost")
|
||||
end
|
||||
if arg.path then
|
||||
assert(type(arg.path)=='string',"Field 'path' need string, get "..type(arg.path))
|
||||
arg.url=arg.url..arg.path
|
||||
end
|
||||
assert(arg.headers==nil or type(arg.headers)=='table',"Field 'headers' need table, get "..type(arg.headers))
|
||||
|
||||
if arg.body~=nil then
|
||||
assert(type(arg.body)=='table',"Field 'body' need table, get "..type(arg.body))
|
||||
arg.body=JSON.encode(arg.body)
|
||||
if not arg.headers then arg.headers={} end
|
||||
TABLE.cover({
|
||||
['Content-Type']="application/json",
|
||||
['Content-Length']=#arg.body,
|
||||
},arg.headers)
|
||||
end
|
||||
|
||||
if arg.pool==nil then arg.pool='_default' end
|
||||
arg.poolPtr=tostring(msgPool[arg.pool])
|
||||
|
||||
sendCHN:push(arg)
|
||||
end
|
||||
|
||||
function HTTP.reset()
|
||||
for i=1,#threads do
|
||||
threads[i]:release()
|
||||
threads[i]=false
|
||||
end
|
||||
TABLE.clear(msgPool)
|
||||
sendCHN:clear()
|
||||
recvCHN:clear()
|
||||
addThread(threadCount)
|
||||
end
|
||||
function HTTP.setThreadCount(n)
|
||||
assert(type(n)=='number' and n>=1 and n<=26 and n%1==0,"function HTTP.setThreadCount(n): n must be integer from 1 to 26")
|
||||
if n>threadCount then
|
||||
addThread(n-threadCount)
|
||||
else
|
||||
for _=n+1,threadCount do
|
||||
sendCHN:push{_destroy=true}
|
||||
end
|
||||
end
|
||||
end
|
||||
function HTTP.getThreadCount()
|
||||
return threadCount
|
||||
end
|
||||
function HTTP.setInterval(interval)
|
||||
if interval<=0 then interval=1e99 end
|
||||
assert(type(interval)=='number',"Interval must be number")
|
||||
HTTP._trigInterval=interval
|
||||
end
|
||||
function HTTP.clearPool(pool)
|
||||
if pool==nil then pool='_default' end
|
||||
assert(type(pool)=='string',"Pool must be nil or string")
|
||||
HTTP._msgCount=HTTP._msgCount-#msgPool[pool]
|
||||
msgPool[pool]={}
|
||||
end
|
||||
function HTTP.deletePool(pool)
|
||||
assert(type(pool)=='string',"Pool must be nil or string")
|
||||
assert(pool~='_default',"Cannot delete _default pool. What are you doing?")
|
||||
HTTP._msgCount=HTTP._msgCount-#msgPool[pool]
|
||||
msgPool[pool]=nil
|
||||
end
|
||||
function HTTP.pollMsg(pool)
|
||||
if not (type(pool)=='nil' or type(pool)=='string') then error("Pool must be nil or string") end
|
||||
HTTP.update()
|
||||
local p=msgPool[pool or '_default']
|
||||
if #p>0 then
|
||||
HTTP._msgCount=HTTP._msgCount-1
|
||||
return table.remove(p)
|
||||
end
|
||||
end
|
||||
function HTTP.setHost(host)
|
||||
assert(type(host)=='string',"Host must be string")
|
||||
if host:sub(1,7)~='http://' then host='http://'..host end
|
||||
HTTP._host=host
|
||||
end
|
||||
|
||||
function HTTP.update(dt)
|
||||
if dt then
|
||||
HTTP._trigTime=HTTP._trigTime+dt
|
||||
if HTTP._trigTime>HTTP._trigInterval then
|
||||
HTTP._trigTime=HTTP._trigTime%HTTP._trigInterval
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
while recvCHN:getCount()>0 do
|
||||
local m=recvCHN:pop()
|
||||
if m.destroy then
|
||||
threads[m.id]:release()
|
||||
threads[m.id]=false
|
||||
elseif tostring(msgPool[m.pool])==m.poolPtr then -- If pool were cleared, discard this datapack
|
||||
table.insert(msgPool[m.pool],{
|
||||
code=m.code,
|
||||
body=m.body,
|
||||
detail=m.detail,
|
||||
})
|
||||
HTTP._msgCount=HTTP._msgCount+1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(HTTP,{__call=function(self,arg)
|
||||
return self.request(arg)
|
||||
end,__metatable=true})
|
||||
|
||||
HTTP.reset()
|
||||
|
||||
return HTTP
|
||||
25
Zframework/image.lua
Normal file
25
Zframework/image.lua
Normal file
@@ -0,0 +1,25 @@
|
||||
local IMG={}
|
||||
function IMG.init(list)
|
||||
IMG.init=nil
|
||||
|
||||
setmetatable(IMG,{__index=function(self,name)
|
||||
if type(list[name])=='table' then
|
||||
self[name]={}
|
||||
for k,v in next,list[name] do
|
||||
self[name][k]=love.graphics.newImage(v)
|
||||
end
|
||||
elseif type(list[name])=='string' then
|
||||
self[name]=love.graphics.newImage(list[name])
|
||||
else
|
||||
LOG("No IMG: "..name)
|
||||
self[name]=PAPER
|
||||
end
|
||||
return self[name]
|
||||
end})
|
||||
|
||||
function IMG.loadAll()
|
||||
for k in next,list do local _=IMG[k] end
|
||||
IMG.loadAll=nil
|
||||
end
|
||||
end
|
||||
return IMG
|
||||
932
Zframework/init.lua
Normal file
932
Zframework/init.lua
Normal file
@@ -0,0 +1,932 @@
|
||||
NONE={}function NULL() end PAPER=love.graphics.newCanvas(1,1)
|
||||
EDITING=""
|
||||
LOADED=false
|
||||
SYSTEM=love.system.getOS()
|
||||
if SYSTEM=='OS X' then SYSTEM='macOS' end
|
||||
|
||||
-- Bit module
|
||||
local success
|
||||
success,bit=pcall(require,"bit")
|
||||
if not success then
|
||||
bit=require"Zframework.bitop".bit
|
||||
end
|
||||
|
||||
-- Pure lua modules (basic)
|
||||
MATH= require'Zframework.mathExtend'
|
||||
COLOR= require'Zframework.color'
|
||||
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)
|
||||
local a,b=pcall(encode,val)
|
||||
if a then
|
||||
return b
|
||||
elseif MES then
|
||||
MES.traceback()
|
||||
end
|
||||
end
|
||||
JSON.decode=function(str)
|
||||
local a,b=pcall(decode,str)
|
||||
if a then
|
||||
return b
|
||||
elseif MES then
|
||||
MES.traceback()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Pure lua modules (complex)
|
||||
LOG= require'Zframework.log'
|
||||
REQUIRE= require'Zframework.require'
|
||||
TASK= require'Zframework.task'
|
||||
LANG= require'Zframework.languages'
|
||||
HASH= require'Zframework.sha2'
|
||||
do
|
||||
local bxor=bit.bxor
|
||||
local char=string.char
|
||||
local function sxor(s1, s2)
|
||||
local b3=""
|
||||
for i=1,#s1 do
|
||||
b3=b3..char(bxor(s1:byte(i),s2:byte(i)))
|
||||
end
|
||||
return b3
|
||||
end
|
||||
function HASH.pbkdf2(hashFunc, pw, salt, n)
|
||||
local u=HASH.hex2bin(HASH.hmac(hashFunc, pw, salt.."\0\0\0\1"))
|
||||
local t=u
|
||||
|
||||
for _=2,n do
|
||||
u=HASH.hex2bin(HASH.hmac(hashFunc, pw, u))
|
||||
t=sxor(t, u)
|
||||
end
|
||||
|
||||
return HASH.bin2hex(t):upper()
|
||||
end
|
||||
end
|
||||
|
||||
-- Love-based modules (basic)
|
||||
HTTP= require'Zframework.http'
|
||||
WS= require'Zframework.websocket'
|
||||
FILE= require'Zframework.file'
|
||||
WHEELMOV= require'Zframework.wheelScroll'
|
||||
SCR= require'Zframework.screen'
|
||||
SCN= require'Zframework.scene'
|
||||
|
||||
-- Love-based modules (complex)
|
||||
GC= require'Zframework.gcExtend'
|
||||
FONT= require'Zframework.font'
|
||||
TEXT= require'Zframework.text'
|
||||
SYSFX= require'Zframework.sysFX'
|
||||
WAIT= require'Zframework.wait'
|
||||
MES= require'Zframework.message'
|
||||
BG= require'Zframework.background'
|
||||
WIDGET= require'Zframework.widget'
|
||||
VIB= require'Zframework.vibrate'
|
||||
SFX= require'Zframework.sfx'
|
||||
IMG= require'Zframework.image'
|
||||
BGM= require'Zframework.bgm'
|
||||
VOC= require'Zframework.voice'
|
||||
|
||||
local ms,kb=love.mouse,love.keyboard
|
||||
local KBisDown=kb.isDown
|
||||
|
||||
local gc=love.graphics
|
||||
local gc_push,gc_pop,gc_clear,gc_discard=gc.push,gc.pop,gc.clear,gc.discard
|
||||
local gc_replaceTransform,gc_present=gc.replaceTransform,gc.present
|
||||
local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth
|
||||
local gc_draw,gc_line,gc_circle,gc_print=gc.draw,gc.line,gc.circle,gc.print
|
||||
|
||||
local BG,WIDGET,SCR,SCN,WAIT=BG,WIDGET,SCR,SCN,WAIT
|
||||
local xOy=SCR.xOy
|
||||
local ITP=xOy.inverseTransformPoint
|
||||
|
||||
local max,min=math.max,math.min
|
||||
|
||||
local debugMode
|
||||
local mx,my,mouseShow,cursorSpd=640,360,false,0
|
||||
local jsState={}-- map, joystickID->axisStates: {axisName->axisVal}
|
||||
local errData={}-- list, each error create {mes={errMes strings},scene=sceneNameStr}
|
||||
|
||||
local function drawCursor(_,x,y)
|
||||
gc_setColor(1,1,1)
|
||||
gc_setLineWidth(2)
|
||||
gc_circle(ms.isDown(1) and 'fill' or 'line',x,y,6)
|
||||
end
|
||||
local showPowerInfo=true
|
||||
local showClickFX=true
|
||||
local discardCanvas=false
|
||||
local frameMul=100
|
||||
local sleepInterval=1/60
|
||||
local onQuit=NULL
|
||||
local onBeforeQuit=false
|
||||
local versionText=""
|
||||
|
||||
local batteryImg=GC.DO{31,20,
|
||||
{'fRect',1,0,26,2},
|
||||
{'fRect',1,18,26,2},
|
||||
{'fRect',0,1,2,18},
|
||||
{'fRect',26,1,2,18},
|
||||
{'fRect',29,3,2,14},
|
||||
}
|
||||
local infoCanvas=gc.newCanvas(108,27)
|
||||
local function updatePowerInfo()
|
||||
local state,pow=love.system.getPowerInfo()
|
||||
gc.setCanvas(infoCanvas)
|
||||
gc_push('transform')
|
||||
gc.origin()
|
||||
gc_clear(0,0,0,.25)
|
||||
if state~='unknown' then
|
||||
gc_setLineWidth(4)
|
||||
if state=='nobattery' then
|
||||
gc_setColor(1,1,1)
|
||||
gc_setLineWidth(2)
|
||||
gc_line(74,5,100,22)
|
||||
elseif pow then
|
||||
if state=='charging' then gc_setColor(0,1,0)
|
||||
elseif pow>50 then gc_setColor(1,1,1)
|
||||
elseif pow>26 then gc_setColor(1,1,0)
|
||||
elseif pow==26 then gc_setColor(.5,0,1)
|
||||
else gc_setColor(1,0,0)
|
||||
end
|
||||
gc.rectangle('fill',76,6,pow*.22,14)
|
||||
if pow<100 then
|
||||
FONT.set(15)
|
||||
gc.setColor(COLOR.D)
|
||||
gc_print(pow,77,1)
|
||||
gc_print(pow,77,3)
|
||||
gc_print(pow,79,1)
|
||||
gc_print(pow,79,3)
|
||||
gc_setColor(COLOR.Z)
|
||||
gc_print(pow,78,2)
|
||||
end
|
||||
end
|
||||
gc_draw(batteryImg,73,3)
|
||||
end
|
||||
FONT.set(25)
|
||||
gc_print(os.date("%H:%M"),3,-5)
|
||||
gc_pop()
|
||||
gc.setCanvas()
|
||||
end
|
||||
-------------------------------------------------------------
|
||||
local lastX,lastY=0,0-- Last click pos
|
||||
local function _updateMousePos(x,y,dx,dy)
|
||||
if SCN.swapping or WAIT.state then return end
|
||||
dx,dy=dx/SCR.k,dy/SCR.k
|
||||
if SCN.mouseMove then SCN.mouseMove(x,y,dx,dy) end
|
||||
if ms.isDown(1) then
|
||||
WIDGET.drag(x,y,dx,dy)
|
||||
else
|
||||
WIDGET.cursorMove(x,y)
|
||||
end
|
||||
end
|
||||
local function mouse_update(dt)
|
||||
if not KBisDown('lctrl','rctrl') and KBisDown('up','down','left','right') then
|
||||
local dx,dy=0,0
|
||||
if KBisDown('up') then dy=dy-cursorSpd end
|
||||
if KBisDown('down') then dy=dy+cursorSpd end
|
||||
if KBisDown('left') then dx=dx-cursorSpd end
|
||||
if KBisDown('right') then dx=dx+cursorSpd end
|
||||
mx=max(min(mx+dx,1280),0)
|
||||
my=max(min(my+dy,720),0)
|
||||
if my==0 or my==720 then
|
||||
WIDGET.sel=false
|
||||
WIDGET.drag(0,0,0,-dy)
|
||||
end
|
||||
_updateMousePos(mx,my,dx,dy)
|
||||
cursorSpd=min(cursorSpd+dt*26,12.6)
|
||||
else
|
||||
cursorSpd=6
|
||||
end
|
||||
end
|
||||
local function gp_update(js,dt)
|
||||
local sx,sy=js._jsObj:getGamepadAxis('leftx'),js._jsObj:getGamepadAxis('lefty')
|
||||
if math.abs(sx)>.1 or math.abs(sy)>.1 then
|
||||
local dx,dy=0,0
|
||||
if sy<-.1 then dy=dy+2*sy*cursorSpd end
|
||||
if sy>.1 then dy=dy+2*sy*cursorSpd end
|
||||
if sx<-.1 then dx=dx+2*sx*cursorSpd end
|
||||
if sx>.1 then dx=dx+2*sx*cursorSpd end
|
||||
mx=max(min(mx+dx,1280),0)
|
||||
my=max(min(my+dy,720),0)
|
||||
if my==0 or my==720 then
|
||||
WIDGET.sel=false
|
||||
WIDGET.drag(0,0,0,-dy)
|
||||
end
|
||||
_updateMousePos(mx,my,dx,dy)
|
||||
cursorSpd=min(cursorSpd+dt*26,12.6)
|
||||
else
|
||||
cursorSpd=6
|
||||
end
|
||||
end
|
||||
function love.mousepressed(x,y,k,touch)
|
||||
if touch or WAIT.state then return end
|
||||
mouseShow=true
|
||||
mx,my=ITP(xOy,x,y)
|
||||
if debugMode==1 then
|
||||
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
|
||||
mx,my,
|
||||
mx-lastX,my-lastY,
|
||||
math.floor(mx/10)*10,math.floor(my/10)*10,
|
||||
math.floor((mx-lastX)/10)*10,math.floor((my-lastY)/10)*10
|
||||
))
|
||||
end
|
||||
if SCN.swapping then return end
|
||||
if SCN.mouseDown then SCN.mouseDown(mx,my,k) end
|
||||
WIDGET.press(mx,my,k)
|
||||
lastX,lastY=mx,my
|
||||
if showClickFX then SYSFX.newTap(3,mx,my) end
|
||||
end
|
||||
function love.mousemoved(x,y,dx,dy,touch)
|
||||
if touch then return end
|
||||
mouseShow=true
|
||||
mx,my=ITP(xOy,x,y)
|
||||
_updateMousePos(mx,my,dx,dy)
|
||||
end
|
||||
function love.mousereleased(x,y,k,touch)
|
||||
if touch or WAIT.state or SCN.swapping then return end
|
||||
mx,my=ITP(xOy,x,y)
|
||||
if SCN.mouseUp then SCN.mouseUp(mx,my,k) end
|
||||
if WIDGET.sel then
|
||||
WIDGET.release(mx,my,k)
|
||||
else
|
||||
if lastX and SCN.mouseClick and (mx-lastX)^2+(my-lastY)^2<62 then
|
||||
SCN.mouseClick(mx,my,k)
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.wheelmoved(x,y)
|
||||
if math.abs(x)>=100 then x=x/100 end
|
||||
if math.abs(y)>=100 then y=y/100 end
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
if SCN.wheelMoved then
|
||||
SCN.wheelMoved(x,y)
|
||||
else
|
||||
WIDGET.unFocus()
|
||||
WIDGET.drag(0,0,0,100*y)
|
||||
end
|
||||
end
|
||||
|
||||
function love.touchpressed(id,x,y)
|
||||
mouseShow=false
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
if not SCN.mainTouchID then
|
||||
SCN.mainTouchID=id
|
||||
WIDGET.unFocus(true)
|
||||
love.touchmoved(id,x,y,0,0)
|
||||
end
|
||||
x,y=ITP(xOy,x,y)
|
||||
lastX,lastY=x,y
|
||||
if SCN.touchDown then SCN.touchDown(x,y,id) end
|
||||
if kb.hasTextInput() then kb.setTextInput(false) end
|
||||
WIDGET.cursorMove(x,y)
|
||||
WIDGET.press(x,y,1)
|
||||
end
|
||||
function love.touchmoved(id,x,y,dx,dy)
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
x,y=ITP(xOy,x,y)
|
||||
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k,id) end
|
||||
WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k)
|
||||
end
|
||||
function love.touchreleased(id,x,y)
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
x,y=ITP(xOy,x,y)
|
||||
if id==SCN.mainTouchID then
|
||||
WIDGET.release(x,y,1)
|
||||
WIDGET.cursorMove(x,y)
|
||||
WIDGET.unFocus()
|
||||
SCN.mainTouchID=false
|
||||
end
|
||||
if SCN.touchUp then SCN.touchUp(x,y,id) end
|
||||
if (x-lastX)^2+(y-lastY)^2<62 then
|
||||
if SCN.touchClick then SCN.touchClick(x,y) end
|
||||
if showClickFX then SYSFX.newTap(3,x,y) end
|
||||
end
|
||||
end
|
||||
-- function love.mousepressed(x,y,k) love.touchpressed(1,x,y) end
|
||||
-- function love.mousemoved(x,y,dx,dy,touch) love.touchmoved(1,x,y,dx,dy) end
|
||||
-- function love.mousereleased(x,y,k) love.touchreleased(1,x,y) end
|
||||
|
||||
local globalKey={
|
||||
f8=function()
|
||||
debugMode=1
|
||||
MES.new('info',"DEBUG ON",.2)
|
||||
end
|
||||
}
|
||||
local fnKey={NULL,NULL,NULL,NULL,NULL,NULL,NULL}
|
||||
local function debugKeyPressed(key)
|
||||
if key=='f1' then fnKey[1]()
|
||||
elseif key=='f2' then fnKey[2]()
|
||||
elseif key=='f3' then fnKey[3]()
|
||||
elseif key=='f4' then fnKey[4]()
|
||||
elseif key=='f5' then fnKey[5]()
|
||||
elseif key=='f6' then fnKey[6]()
|
||||
elseif key=='f7' then fnKey[7]()
|
||||
elseif key=='f8' then debugMode=nil MES.new('info',"DEBUG OFF",.2)
|
||||
elseif key=='f9' then debugMode=1 MES.new('info',"DEBUG 1")
|
||||
elseif key=='f10' then debugMode=2 MES.new('info',"DEBUG 2")
|
||||
elseif key=='f11' then debugMode=3 MES.new('info',"DEBUG 3")
|
||||
elseif key=='f12' then debugMode=4 MES.new('info',"DEBUG 4")
|
||||
elseif debugMode==2 then
|
||||
local W=WIDGET.sel
|
||||
if W then
|
||||
if key=='left' then W.x=W.x-10
|
||||
elseif key=='right' then W.x=W.x+10
|
||||
elseif key=='up' then W.y=W.y-10
|
||||
elseif key=='down' then W.y=W.y+10
|
||||
elseif key==',' then W.w=W.w-10
|
||||
elseif key=='.' then W.w=W.w+10
|
||||
elseif key=='/' then W.h=W.h-10
|
||||
elseif key=='\'' then W.h=W.h+10
|
||||
elseif key=='[' then W.font=W.font-5
|
||||
elseif key==']' then W.font=W.font+5
|
||||
else return
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
return true
|
||||
end
|
||||
function love.keypressed(key,_,isRep)
|
||||
mouseShow=false
|
||||
if debugMode and debugKeyPressed(key) then
|
||||
-- Do nothing
|
||||
elseif globalKey[key] then
|
||||
globalKey[key]()
|
||||
else
|
||||
if SCN.swapping then return end
|
||||
if WAIT.state then
|
||||
if key=='escape' and WAIT.arg.escapable then WAIT.interrupt() end
|
||||
return
|
||||
end
|
||||
if EDITING=="" and (not SCN.keyDown or SCN.keyDown(key,isRep)) then
|
||||
local W=WIDGET.sel
|
||||
if key=='escape' and not isRep then
|
||||
SCN.back()
|
||||
elseif key=='up' or key=='down' or key=='left' or key=='right' then
|
||||
mouseShow=true
|
||||
if KBisDown('lctrl','rctrl') then
|
||||
if W and W.arrowKey then W:arrowKey(key) end
|
||||
end
|
||||
elseif key=='space' or key=='return' then
|
||||
mouseShow=true
|
||||
if not isRep then
|
||||
if showClickFX then SYSFX.newTap(3,mx,my) end
|
||||
love.mousepressed(mx,my,1)
|
||||
love.mousereleased(mx,my,1)
|
||||
end
|
||||
else
|
||||
if W and W.keypress then
|
||||
W:keypress(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.keyreleased(i)
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
if SCN.keyUp then SCN.keyUp(i) end
|
||||
end
|
||||
|
||||
function love.textedited(texts)
|
||||
EDITING=texts
|
||||
end
|
||||
function love.textinput(texts)
|
||||
WIDGET.textinput(texts)
|
||||
end
|
||||
|
||||
-- analog sticks: -1, 0, 1 for neg, neutral, pos
|
||||
-- triggers: 0 for released, 1 for pressed
|
||||
local jsAxisEventName={
|
||||
leftx={'leftstick_left','leftstick_right'},
|
||||
lefty={'leftstick_up','leftstick_down'},
|
||||
rightx={'rightstick_left','rightstick_right'},
|
||||
righty={'rightstick_up','rightstick_down'},
|
||||
triggerleft='triggerleft',
|
||||
triggerright='triggerright'
|
||||
}
|
||||
local gamePadKeys={'a','b','x','y','back','guide','start','leftstick','rightstick','leftshoulder','rightshoulder','dpup','dpdown','dpleft','dpright'}
|
||||
local dPadToKey={
|
||||
dpup='up',
|
||||
dpdown='down',
|
||||
dpleft='left',
|
||||
dpright='right',
|
||||
start='return',
|
||||
back='escape',
|
||||
}
|
||||
function love.joystickadded(JS)
|
||||
table.insert(jsState,{
|
||||
_id=JS:getID(),
|
||||
_jsObj=JS,
|
||||
leftx=0,lefty=0,
|
||||
rightx=0,righty=0,
|
||||
triggerleft=0,triggerright=0
|
||||
})
|
||||
MES.new('info',"Joystick added")
|
||||
end
|
||||
function love.joystickremoved(JS)
|
||||
for i=1,#jsState do
|
||||
if jsState[i]._jsObj==JS then
|
||||
for j=1,#gamePadKeys do
|
||||
if JS:isGamepadDown(gamePadKeys[j]) then
|
||||
love.gamepadreleased(JS,gamePadKeys[j])
|
||||
end
|
||||
end
|
||||
love.gamepadaxis(JS,'leftx',0)
|
||||
love.gamepadaxis(JS,'lefty',0)
|
||||
love.gamepadaxis(JS,'rightx',0)
|
||||
love.gamepadaxis(JS,'righty',0)
|
||||
love.gamepadaxis(JS,'triggerleft',-1)
|
||||
love.gamepadaxis(JS,'triggerright',-1)
|
||||
MES.new('info',"Joystick removed")
|
||||
table.remove(jsState,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.gamepadaxis(JS,axis,val)
|
||||
if jsState[1] and JS==jsState[1]._jsObj then
|
||||
local js=jsState[1]
|
||||
if axis=='leftx' or axis=='lefty' or axis=='rightx' or axis=='righty' then
|
||||
local newVal=-- range: [0,1]
|
||||
val>.4 and 1 or
|
||||
val<-.4 and -1 or
|
||||
0
|
||||
if newVal~=js[axis] then
|
||||
if js[axis]==-1 then
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis][1])
|
||||
elseif js[axis]~=0 then
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis][2])
|
||||
end
|
||||
if newVal==-1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis][1])
|
||||
elseif newVal==1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis][2])
|
||||
end
|
||||
js[axis]=newVal
|
||||
end
|
||||
elseif axis=='triggerleft' or axis=='triggerright' then
|
||||
local newVal=val>.3 and 1 or 0-- range: [0,1]
|
||||
if newVal~=js[axis] then
|
||||
if newVal==1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis])
|
||||
else
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis])
|
||||
end
|
||||
js[axis]=newVal
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.gamepadpressed(_,key)
|
||||
mouseShow=false
|
||||
if not SCN.swapping then
|
||||
local cursorCtrl
|
||||
if SCN.gamepadDown then
|
||||
cursorCtrl=SCN.gamepadDown(key)
|
||||
elseif SCN.keyDown then
|
||||
cursorCtrl=SCN.keyDown(dPadToKey[key] or key)
|
||||
else
|
||||
cursorCtrl=true
|
||||
end
|
||||
if cursorCtrl then
|
||||
key=dPadToKey[key] or key
|
||||
mouseShow=true
|
||||
local W=WIDGET.sel
|
||||
if key=='back' then
|
||||
SCN.back()
|
||||
elseif key=='up' or key=='down' or key=='left' or key=='right' then
|
||||
mouseShow=true
|
||||
if W and W.arrowKey then W:arrowKey(key) end
|
||||
elseif key=='return' then
|
||||
mouseShow=true
|
||||
if showClickFX then SYSFX.newTap(3,mx,my) end
|
||||
love.mousepressed(mx,my,1)
|
||||
love.mousereleased(mx,my,1)
|
||||
else
|
||||
if W and W.keypress then
|
||||
W:keypress(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.gamepadreleased(_,i)
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
if SCN.gamepadUp then SCN.gamepadUp(i) end
|
||||
end
|
||||
|
||||
function love.filedropped(file)
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
if SCN.fileDropped then SCN.fileDropped(file) end
|
||||
end
|
||||
function love.directorydropped(dir)
|
||||
if WAIT.state or SCN.swapping then return end
|
||||
if SCN.directoryDropped then SCN.directoryDropped(dir) end
|
||||
end
|
||||
local autoGCcount=0
|
||||
function love.lowmemory()
|
||||
collectgarbage()
|
||||
if autoGCcount<3 then
|
||||
autoGCcount=autoGCcount+1
|
||||
MES.new('check',"[auto GC] low MEM 设备内存过低")
|
||||
end
|
||||
end
|
||||
|
||||
local onResize=NULL
|
||||
function love.resize(w,h)
|
||||
if SCR.w==w and SCR.h==h then return end
|
||||
SCR.resize(w,h)
|
||||
if BG.resize then BG.resize(w,h) end
|
||||
if SCN.resize then SCN.resize(w,h) end
|
||||
WIDGET.resize(w,h)
|
||||
FONT.reset()
|
||||
onResize(w,h)
|
||||
end
|
||||
|
||||
local onFocus=NULL
|
||||
function love.focus(f) onFocus(f) end
|
||||
|
||||
local yield=coroutine.yield
|
||||
local function secondLoopThread()
|
||||
local mainLoop=love.run()
|
||||
repeat yield() until mainLoop()
|
||||
end
|
||||
function love.errorhandler(msg)
|
||||
|
||||
if type(msg)~='string' then
|
||||
msg="Unknown error"
|
||||
elseif msg:find("Invalid UTF-8") and text then
|
||||
msg=text.tryAnotherBuild
|
||||
end
|
||||
|
||||
-- Generate error message
|
||||
local err={"Error:"..msg}
|
||||
local c=2
|
||||
for l in debug.traceback("",2):gmatch("(.-)\n") do
|
||||
if c>2 then
|
||||
if not l:find("boot") then
|
||||
err[c]=l:gsub("^\t*","")
|
||||
c=c+1
|
||||
end
|
||||
else
|
||||
err[2]="Traceback"
|
||||
c=3
|
||||
end
|
||||
end
|
||||
print(table.concat(err,"\n",1,c-2))
|
||||
|
||||
-- Reset something
|
||||
love.audio.stop()
|
||||
gc.reset()
|
||||
|
||||
local sceneStack=SCN and table.concat(SCN.stack,"/") or "NULL"
|
||||
if LOADED and #errData<3 then
|
||||
BG.set('none')
|
||||
table.insert(errData,{mes=err,scene=sceneStack})
|
||||
|
||||
-- Write messages to log file
|
||||
love.filesystem.append('conf/error.log',
|
||||
os.date("%Y/%m/%d %A %H:%M:%S\n")..
|
||||
#errData.." crash(es) "..SYSTEM.."-"..VERSION.string.." scene: "..sceneStack.."\n"..
|
||||
table.concat(err,"\n",1,c-2).."\n\n"
|
||||
)
|
||||
|
||||
-- Get screencapture
|
||||
gc.captureScreenshot(function(_) errData[#errData].shot=gc.newImage(_) end)
|
||||
gc.present()
|
||||
|
||||
-- Create a new mainLoop thread to keep game alive
|
||||
local status,resume=coroutine.status,coroutine.resume
|
||||
local loopThread=coroutine.create(secondLoopThread)
|
||||
local res,threadErr
|
||||
repeat
|
||||
res,threadErr=resume(loopThread)
|
||||
until status(loopThread)=='dead'
|
||||
if not res then
|
||||
love.errorhandler(threadErr)
|
||||
return
|
||||
end
|
||||
else
|
||||
ms.setVisible(true)
|
||||
|
||||
local errorMsg
|
||||
errorMsg=LOADED and
|
||||
"Too many errors or fatal error occured.\nPlease restart the game." or
|
||||
"An error has occurred during loading.\nError info has been created, and you can send it to the author."
|
||||
while true do
|
||||
love.event.pump()
|
||||
for E,a,b in love.event.poll() do
|
||||
if E=='quit' or a=='escape' then
|
||||
return true
|
||||
elseif E=='resize' then
|
||||
SCR.resize(a,b)
|
||||
end
|
||||
end
|
||||
gc_clear(.3,.5,.9)
|
||||
gc_push('transform')
|
||||
gc_replaceTransform(SCR.xOy)
|
||||
FONT.set(100)gc_print(":(",100,0,0,1.2)
|
||||
FONT.set(40)gc.printf(errorMsg,100,160,SCR.w0-100)
|
||||
FONT.set(20)
|
||||
gc_print(SYSTEM.."-"..VERSION.string.." scene:"..sceneStack,100,660)
|
||||
gc.printf(err[1],100,360,1260-100)
|
||||
gc_print("TRACEBACK",100,450)
|
||||
for i=4,#err-2 do
|
||||
gc_print(err[i],100,400+20*i)
|
||||
end
|
||||
gc_pop()
|
||||
gc_present()
|
||||
love.timer.sleep(.26)
|
||||
end
|
||||
end
|
||||
end
|
||||
love.threaderror=nil
|
||||
|
||||
love.draw,love.update=nil-- remove default draw/update
|
||||
|
||||
local debugColor={
|
||||
COLOR.Z,
|
||||
COLOR.lM,
|
||||
COLOR.lG,
|
||||
COLOR.lB,
|
||||
}
|
||||
|
||||
local debugInfos={
|
||||
{"Cache",gcinfo},
|
||||
}
|
||||
function love.run()
|
||||
local love=love
|
||||
|
||||
local TEXT_update,TEXT_draw=TEXT.update,TEXT.draw
|
||||
local MES_update,MES_draw=MES.update,MES.draw
|
||||
local HTTP_update,WS_update=HTTP.update,WS.update
|
||||
local TASK_update=TASK.update
|
||||
local SYSFX_update,SYSFX_draw=SYSFX.update,SYSFX.draw
|
||||
local WIDGET_update,WIDGET_draw=WIDGET.update,WIDGET.draw
|
||||
local STEP,SLEEP=love.timer.step,love.timer.sleep
|
||||
local FPS,MINI=love.timer.getFPS,love.window.isMinimized
|
||||
local PUMP,POLL=love.event.pump,love.event.poll
|
||||
|
||||
local timer=love.timer.getTime
|
||||
|
||||
local frameTimeList={}
|
||||
local lastFrame=timer()
|
||||
local lastFreshPow=lastFrame
|
||||
local FCT=0-- Framedraw counter, from 0~99
|
||||
|
||||
love.resize(gc.getWidth(),gc.getHeight())
|
||||
|
||||
-- Scene Launch
|
||||
while #SCN.stack>0 do SCN.pop() end
|
||||
if #errData>0 then
|
||||
SCN.cur='error'
|
||||
SCN.init('error')
|
||||
else
|
||||
SCN.init('load')
|
||||
end
|
||||
|
||||
return function()
|
||||
local _
|
||||
|
||||
local time=timer()
|
||||
local dt=time-lastFrame
|
||||
lastFrame=time
|
||||
|
||||
-- EVENT
|
||||
PUMP()
|
||||
for N,a,b,c,d,e in POLL() do
|
||||
if love[N] then
|
||||
love[N](a,b,c,d,e)
|
||||
elseif N=='quit' then
|
||||
if onBeforeQuit then
|
||||
onBeforeQuit()
|
||||
onBeforeQuit=false
|
||||
else
|
||||
onQuit()
|
||||
return a or true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- UPDATE
|
||||
STEP()
|
||||
if mouseShow then mouse_update(dt) end
|
||||
if next(jsState) then gp_update(jsState[1],dt) end
|
||||
VOC.update()
|
||||
BG.update(dt)
|
||||
TEXT_update(dt)
|
||||
WAIT.update(dt)
|
||||
MES_update(dt)
|
||||
HTTP_update(dt)
|
||||
WS_update(dt)
|
||||
TASK_update(dt)
|
||||
SYSFX_update(dt)
|
||||
if SCN.update then SCN.update(dt) end
|
||||
if SCN.swapping then SCN.swapUpdate(dt) end
|
||||
WIDGET_update(dt)
|
||||
|
||||
-- DRAW
|
||||
if not MINI() then
|
||||
FCT=FCT+frameMul
|
||||
if FCT>=100 then
|
||||
FCT=FCT-100
|
||||
|
||||
gc_replaceTransform(SCR.origin)
|
||||
gc_setColor(1,1,1)
|
||||
BG.draw()
|
||||
gc_replaceTransform(SCR.xOy)
|
||||
if SCN.draw then SCN.draw() end
|
||||
WIDGET_draw()
|
||||
SYSFX_draw()
|
||||
TEXT_draw()
|
||||
|
||||
-- Draw cursor
|
||||
if mouseShow then drawCursor(time,mx,my) end
|
||||
gc_replaceTransform(SCR.xOy_ul)
|
||||
if showPowerInfo then
|
||||
gc.translate(0,27)
|
||||
end
|
||||
MES_draw()
|
||||
gc_replaceTransform(SCR.origin)
|
||||
-- Draw power info.
|
||||
if showPowerInfo then
|
||||
gc_setColor(1,1,1)
|
||||
gc_draw(infoCanvas,SCR.safeX,0,0,SCR.k)
|
||||
end
|
||||
|
||||
-- Draw scene swapping animation
|
||||
if SCN.swapping then
|
||||
gc_setColor(1,1,1)
|
||||
_=SCN.state
|
||||
_.draw(_.time)
|
||||
end
|
||||
gc_replaceTransform(SCR.xOy_d)
|
||||
-- Draw Version string
|
||||
gc_setColor(.9,.9,.9,.42)
|
||||
FONT.set(20)
|
||||
GC.mStr(versionText,0,-30)
|
||||
gc_replaceTransform(SCR.xOy_dl)
|
||||
local safeX=SCR.safeX/SCR.k
|
||||
|
||||
-- Draw FPS
|
||||
FONT.set(15)
|
||||
gc_setColor(1,1,1)
|
||||
gc_print(FPS(),safeX+5,-20)
|
||||
|
||||
-- Debug info.
|
||||
if debugMode then
|
||||
-- Debug infos at left-down
|
||||
gc_setColor(debugColor[debugMode])
|
||||
|
||||
-- Text infos
|
||||
for i=1,#debugInfos do
|
||||
gc_print(debugInfos[i][1],safeX+5,-20-20*i)
|
||||
gc_print(debugInfos[i][2](),safeX+62.6,-20-20*i)
|
||||
end
|
||||
|
||||
-- Update & draw frame time
|
||||
table.insert(frameTimeList,1,dt)table.remove(frameTimeList,126)
|
||||
gc_setColor(1,1,1,.3)
|
||||
for i=1,#frameTimeList do
|
||||
gc.rectangle('fill',150+2*i,-20,2,-frameTimeList[i]*4000)
|
||||
end
|
||||
|
||||
-- Cursor pos disp
|
||||
gc_replaceTransform(SCR.origin)
|
||||
local x,y=SCR.xOy:transformPoint(mx,my)
|
||||
gc_setLineWidth(1)
|
||||
gc_line(x,0,x,SCR.h)
|
||||
gc_line(0,y,SCR.w,y)
|
||||
local t=math.floor(mx+.5)..","..math.floor(my+.5)
|
||||
gc.setColor(COLOR.D)
|
||||
gc_print(t,x+1,y)
|
||||
gc_print(t,x+1,y-1)
|
||||
gc_print(t,x+2,y-1)
|
||||
gc_setColor(COLOR.Z)
|
||||
gc_print(t,x+2,y)
|
||||
|
||||
gc_replaceTransform(SCR.xOy_dr)
|
||||
-- Websocket status
|
||||
local status=WS.status('game')
|
||||
if status=='dead' then
|
||||
gc_setColor(COLOR.R)
|
||||
elseif status=='connecting' then
|
||||
gc_setColor(1,1,1,.5+.3*math.sin(time*6.26))
|
||||
elseif status=='running' then
|
||||
gc_setColor(COLOR.lG)
|
||||
end
|
||||
gc.rectangle('fill',-16,-16,12,12)
|
||||
local t1,t2,t3=WS.getTimers('game')
|
||||
if t1>0 then gc_setColor(.9,.9,.9,t1)gc.rectangle('fill',-60,-2,-16,-16) end
|
||||
if t2>0 then gc_setColor(.3,1,.3,t2)gc.rectangle('fill',-42,-2,-16,-16) end
|
||||
if t3>0 then gc_setColor(1,.2,.2,t3)gc.rectangle('fill',-24,-2,-16,-16) end
|
||||
end
|
||||
gc_replaceTransform(SCR.origin)
|
||||
WAIT.draw()
|
||||
gc_present()
|
||||
|
||||
-- SPEED UPUPUP!
|
||||
if discardCanvas then gc_discard() end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fresh power info.
|
||||
if time-lastFreshPow>2.6 then
|
||||
if showPowerInfo then
|
||||
updatePowerInfo()
|
||||
lastFreshPow=time
|
||||
end
|
||||
if gc.getWidth()~=SCR.w or gc.getHeight()~=SCR.h then
|
||||
love.resize(gc.getWidth(),gc.getHeight())
|
||||
end
|
||||
end
|
||||
|
||||
-- Slow debugmode
|
||||
if debugMode then
|
||||
if debugMode==3 then
|
||||
SLEEP(.1)
|
||||
elseif debugMode==4 then
|
||||
SLEEP(.5)
|
||||
end
|
||||
end
|
||||
|
||||
_=timer()-lastFrame
|
||||
if _<sleepInterval*.9626 then SLEEP(sleepInterval*.9626-_) end
|
||||
while timer()-lastFrame<sleepInterval do end
|
||||
end
|
||||
end
|
||||
|
||||
local Z={}
|
||||
|
||||
function Z.getJsState() return jsState end
|
||||
function Z.getErr(i)
|
||||
if i=='#' then
|
||||
return errData[#errData]
|
||||
elseif i then
|
||||
return errData[i]
|
||||
else
|
||||
return errData
|
||||
end
|
||||
end
|
||||
|
||||
function Z.setPowerInfo(bool) showPowerInfo=bool end
|
||||
function Z.setCleanCanvas(bool) discardCanvas=bool end
|
||||
function Z.setFrameMul(n) frameMul=n end
|
||||
function Z.setMaxFPS(fps) sleepInterval=1/fps end
|
||||
function Z.setClickFX(bool) showClickFX=bool end
|
||||
|
||||
--[Warning] Color and line width is uncertain value, set it in the function.
|
||||
function Z.setCursor(func) drawCursor=func end
|
||||
|
||||
function Z.setVersionText(str) versionText=str end
|
||||
|
||||
function Z.setDebugInfo(list)
|
||||
assert(type(list)=='table',"Z.setDebugInfo(list): list must be table")
|
||||
for i=1,#list do
|
||||
assert(type(list[i][1])=='string',"Z.setDebugInfo(list): list[i][1] must be string")
|
||||
assert(type(list[i][2])=='function',"Z.setDebugInfo(list): list[i][2] must be function")
|
||||
end
|
||||
debugInfos=list
|
||||
end
|
||||
|
||||
-- Change F1~F7 events of debugmode (F8 mode)
|
||||
function Z.setOnFnKeys(list)
|
||||
assert(type(list)=='table',"Z.setOnFnKeys(list): list must be table")
|
||||
for i=1,7 do fnKey[i]=assert(type(list[i])=='function' and list[i]) end
|
||||
end
|
||||
|
||||
function Z.setOnGlobalKey(key,func)
|
||||
assert(type(key)=='string',"Z.setOnFnKeys(key,func): key must be string")
|
||||
if not func then
|
||||
globalKey[key]=nil
|
||||
else
|
||||
assert(type(func)=='function',"Z.setOnFnKeys(key,func): func must be function")
|
||||
globalKey[key]=func
|
||||
end
|
||||
end
|
||||
|
||||
function Z.setOnFocus(func)
|
||||
onFocus=assert(type(func)=='function' and func,"Z.setOnFocus(func): func must be function")
|
||||
end
|
||||
|
||||
function Z.setOnResize(func)
|
||||
onResize=assert(type(func)=='function' and func,"Z.setOnResize(func): func must be function")
|
||||
end
|
||||
|
||||
function Z.setOnQuit(func)
|
||||
onQuit=assert(type(func)=='function' and func,"Z.setOnQuit(func): func must be function")
|
||||
end
|
||||
|
||||
function Z.setOnBeforeQuit(func)
|
||||
onBeforeQuit=assert(type(func)=='function' and func,"Z.setOnBeforeQuit(func): func must be function")
|
||||
end
|
||||
|
||||
return Z
|
||||
340
Zframework/json.lua
Normal file
340
Zframework/json.lua
Normal file
@@ -0,0 +1,340 @@
|
||||
-- json.lua
|
||||
|
||||
-- Copyright (c) 2020 rxi
|
||||
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in
|
||||
-- the Software without restriction, including without limitation the rights to
|
||||
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
-- of the Software, and to permit persons to whom the Software is furnished to do
|
||||
-- so, subject to the following conditions:
|
||||
|
||||
-- The above copyright notice and this permission notice shall be included in all
|
||||
-- copies or substantial portions of the Software.
|
||||
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
-- SOFTWARE.
|
||||
|
||||
-- Editted by MrZ
|
||||
|
||||
local ins,char=table.insert,string.char
|
||||
local json = {}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Encode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local _encode
|
||||
|
||||
local escape_char_map = {
|
||||
["\\"] = "\\",
|
||||
["\""] = "\"",
|
||||
["\b"] = "b",
|
||||
["\f"] = "f",
|
||||
["\n"] = "n",
|
||||
["\r"] = "r",
|
||||
["\t"] = "t"
|
||||
}
|
||||
|
||||
local escape_char_map_inv = {["/"] = "/"}
|
||||
for k, v in pairs(escape_char_map) do escape_char_map_inv[v] = k end
|
||||
|
||||
local function escape_char(c)
|
||||
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
|
||||
end
|
||||
|
||||
local function encode_nil() return "null" end
|
||||
|
||||
local function encode_table(val, stack)
|
||||
local res = {}
|
||||
stack = stack or {}
|
||||
|
||||
-- Circular reference?
|
||||
if stack[val] then error("circular reference") end
|
||||
|
||||
stack[val] = true
|
||||
|
||||
if rawget(val, 1) ~= nil or next(val) == nil then
|
||||
-- Treat as array -- check keys are valid and it is not sparse
|
||||
local n = 0
|
||||
for k in pairs(val) do
|
||||
if type(k) ~= 'number' then
|
||||
error("invalid table: mixed or invalid key types")
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if n ~= #val then error("invalid table: sparse array") end
|
||||
-- Encode
|
||||
for _, v in ipairs(val) do ins(res, _encode(v, stack)) end
|
||||
stack[val] = nil
|
||||
return "[" .. table.concat(res, ",") .. "]"
|
||||
|
||||
else
|
||||
-- Treat as an object
|
||||
for k, v in pairs(val) do
|
||||
if type(k) ~= 'string' then
|
||||
error("invalid table: mixed or invalid key types")
|
||||
end
|
||||
ins(res, _encode(k, stack) .. ":" .. _encode(v, stack))
|
||||
end
|
||||
stack[val] = nil
|
||||
return "{" .. table.concat(res, ",") .. "}"
|
||||
end
|
||||
end
|
||||
|
||||
local function encode_string(val)
|
||||
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
|
||||
end
|
||||
|
||||
local function encode_number(val)
|
||||
-- Check for NaN, -inf and inf
|
||||
if val ~= val or val <= -math.huge or val >= math.huge then
|
||||
error("unexpected number value '" .. tostring(val) .. "'")
|
||||
end
|
||||
return string.format("%.14g", val)
|
||||
end
|
||||
|
||||
local type_func_map = {
|
||||
['nil'] = encode_nil,
|
||||
['table'] = encode_table,
|
||||
['string'] = encode_string,
|
||||
['number'] = encode_number,
|
||||
['boolean'] = tostring
|
||||
}
|
||||
|
||||
_encode = function(val, stack)
|
||||
local t = type(val)
|
||||
local f = type_func_map[t]
|
||||
if f then return f(val, stack) end
|
||||
error("unexpected type '" .. t .. "'")
|
||||
end
|
||||
|
||||
json.encode=_encode
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Decode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local parse
|
||||
|
||||
local function create_set(...)
|
||||
local res = {}
|
||||
for i = 1, select("#", ...) do res[select(i, ...)] = true end
|
||||
return res
|
||||
end
|
||||
|
||||
local space_chars = create_set(" ", "\t", "\r", "\n")
|
||||
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
|
||||
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
|
||||
local literals = create_set("true", "false", "null")
|
||||
|
||||
local literal_map = {["true"] = true, ["false"] = false, ["null"] = nil}
|
||||
|
||||
local function next_char(str, idx, set, negate)
|
||||
for i = idx, #str do if set[str:sub(i, i)] ~= negate then return i end end
|
||||
return #str + 1
|
||||
end
|
||||
|
||||
local function decode_error(str, idx, msg)
|
||||
local line_count = 1
|
||||
local col_count = 1
|
||||
for i = 1, idx - 1 do
|
||||
col_count = col_count + 1
|
||||
if str:sub(i, i) == "\n" then
|
||||
line_count = line_count + 1
|
||||
col_count = 1
|
||||
end
|
||||
end
|
||||
error(string.format("%s at line %d col %d", msg, line_count, col_count))
|
||||
end
|
||||
|
||||
local function codepoint_to_utf8(n)
|
||||
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
|
||||
local f = bit.rshift
|
||||
if n <= 0x7f then
|
||||
return char(n)
|
||||
elseif n <= 0x7ff then
|
||||
return char(f(n, 6) + 192, n % 64 + 128)
|
||||
elseif n <= 0xffff then
|
||||
return char(f(n, 12) + 224, f(n % 4096, 6) + 128, n % 64 + 128)
|
||||
elseif n <= 0x10ffff then
|
||||
return char(f(n, 18) + 240, f(n % 262144, 12) + 128, f(n % 4096, 6) + 128, n % 64 + 128)
|
||||
end
|
||||
error(string.format("invalid unicode codepoint '%x'", n))
|
||||
end
|
||||
|
||||
local function parse_unicode_escape(s)
|
||||
local n1 = tonumber(s:sub(1, 4), 16)
|
||||
local n2 = tonumber(s:sub(7, 10), 16)
|
||||
-- Surrogate pair?
|
||||
if n2 then
|
||||
return
|
||||
codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
|
||||
else
|
||||
return codepoint_to_utf8(n1)
|
||||
end
|
||||
end
|
||||
|
||||
local function parse_string(str, i)
|
||||
local res = ""
|
||||
local j = i + 1
|
||||
local k = j
|
||||
|
||||
while j <= #str do
|
||||
local x = str:byte(j)
|
||||
|
||||
if x < 32 then
|
||||
decode_error(str, j, "control character in string")
|
||||
|
||||
elseif x == 92 then -- `\`: Escape
|
||||
res = res .. str:sub(k, j - 1)
|
||||
j = j + 1
|
||||
local c = str:sub(j, j)
|
||||
if c == "u" then
|
||||
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) or
|
||||
str:match("^%x%x%x%x", j + 1) or
|
||||
decode_error(str, j - 1,
|
||||
"invalid unicode escape in string")
|
||||
res = res .. parse_unicode_escape(hex)
|
||||
j = j + #hex
|
||||
else
|
||||
if not escape_chars[c] then
|
||||
decode_error(str, j - 1,
|
||||
"invalid escape char '" .. c .. "' in string")
|
||||
end
|
||||
res = res .. escape_char_map_inv[c]
|
||||
end
|
||||
k = j + 1
|
||||
|
||||
elseif x == 34 then -- `"`: End of string
|
||||
res = res .. str:sub(k, j - 1)
|
||||
return res, j + 1
|
||||
end
|
||||
|
||||
j = j + 1
|
||||
end
|
||||
|
||||
decode_error(str, i, "expected closing quote for string")
|
||||
end
|
||||
|
||||
local function parse_number(str, i)
|
||||
local x = next_char(str, i, delim_chars)
|
||||
local s = str:sub(i, x - 1)
|
||||
local n = tonumber(s)
|
||||
if not n then decode_error(str, i, "invalid number '" .. s .. "'") end
|
||||
return n, x
|
||||
end
|
||||
|
||||
local function parse_literal(str, i)
|
||||
local x = next_char(str, i, delim_chars)
|
||||
local word = str:sub(i, x - 1)
|
||||
if not literals[word] then
|
||||
decode_error(str, i, "invalid literal '" .. word .. "'")
|
||||
end
|
||||
return literal_map[word], x
|
||||
end
|
||||
|
||||
local function parse_array(str, i)
|
||||
local res = {}
|
||||
local n = 1
|
||||
i = i + 1
|
||||
while 1 do
|
||||
local x
|
||||
i = next_char(str, i, space_chars, true)
|
||||
-- Empty / end of array?
|
||||
if str:sub(i, i) == "]" then
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
-- Read token
|
||||
x, i = parse(str, i)
|
||||
res[n] = x
|
||||
n = n + 1
|
||||
-- Next token
|
||||
i = next_char(str, i, space_chars, true)
|
||||
local chr = str:sub(i, i)
|
||||
i = i + 1
|
||||
if chr == "]" then break end
|
||||
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
|
||||
end
|
||||
return res, i
|
||||
end
|
||||
|
||||
local function parse_object(str, i)
|
||||
local res = {}
|
||||
i = i + 1
|
||||
while 1 do
|
||||
local key, val
|
||||
i = next_char(str, i, space_chars, true)
|
||||
-- Empty / end of object?
|
||||
if str:sub(i, i) == "}" then
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
-- Read key
|
||||
if str:sub(i, i) ~= '"' then
|
||||
decode_error(str, i, "expected string for key")
|
||||
end
|
||||
key, i = parse(str, i)
|
||||
-- Read ':' delimiter
|
||||
i = next_char(str, i, space_chars, true)
|
||||
if str:sub(i, i) ~= ":" then
|
||||
decode_error(str, i, "expected ':' after key")
|
||||
end
|
||||
i = next_char(str, i + 1, space_chars, true)
|
||||
-- Read value
|
||||
val, i = parse(str, i)
|
||||
-- Set
|
||||
res[key] = val
|
||||
-- Next token
|
||||
i = next_char(str, i, space_chars, true)
|
||||
local chr = str:sub(i, i)
|
||||
i = i + 1
|
||||
if chr == "}" then break end
|
||||
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
|
||||
end
|
||||
return res, i
|
||||
end
|
||||
|
||||
local char_func_map = {
|
||||
['"'] = parse_string,
|
||||
["0"] = parse_number,
|
||||
["1"] = parse_number,
|
||||
["2"] = parse_number,
|
||||
["3"] = parse_number,
|
||||
["4"] = parse_number,
|
||||
["5"] = parse_number,
|
||||
["6"] = parse_number,
|
||||
["7"] = parse_number,
|
||||
["8"] = parse_number,
|
||||
["9"] = parse_number,
|
||||
["-"] = parse_number,
|
||||
["t"] = parse_literal,
|
||||
["f"] = parse_literal,
|
||||
["n"] = parse_literal,
|
||||
["["] = parse_array,
|
||||
["{"] = parse_object
|
||||
}
|
||||
|
||||
function parse(str, idx)
|
||||
local chr = str:sub(idx, idx)
|
||||
local f = char_func_map[chr]
|
||||
if f then return f(str, idx) end
|
||||
decode_error(str, idx, "unexpected character '" .. chr .. "'")
|
||||
end
|
||||
|
||||
function json.decode(str)
|
||||
if type(str) ~= 'string' then
|
||||
error("expected argument of type string, got " .. type(str))
|
||||
end
|
||||
local res, idx = parse(str, next_char(str, 1, space_chars, true))
|
||||
idx = next_char(str, idx, space_chars, true)
|
||||
if idx <= #str then decode_error(str, idx, "trailing garbage") end
|
||||
return res
|
||||
end
|
||||
return json
|
||||
57
Zframework/languages.lua
Normal file
57
Zframework/languages.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
local LANG={}
|
||||
-- ONLY FIRST CALL MAKE SENSE
|
||||
-- Create LANG.get() and LANG.addScene()
|
||||
function LANG.init(defaultLang,langList,publicText,pretreatFunc)
|
||||
local function _langFallback(T0,T)
|
||||
for k,v in next,T0 do
|
||||
if type(v)=='table' and not v.refuseCopy then-- refuseCopy: just copy pointer, not contents
|
||||
if not T[k] then T[k]={} end
|
||||
if type(T[k])=='table' then
|
||||
_langFallback(v,T[k])
|
||||
end
|
||||
elseif not T[k] then
|
||||
T[k]=v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Set public text
|
||||
if publicText then
|
||||
for _,L in next,langList do
|
||||
for key,list in next,publicText do L[key]=list end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to default language
|
||||
for name,L in next,langList do
|
||||
if name~=defaultLang then
|
||||
_langFallback(langList[L.fallback or defaultLang],L)
|
||||
end
|
||||
end
|
||||
|
||||
-- Custom pretreatment for each language
|
||||
if pretreatFunc then
|
||||
for _,L in next,langList do
|
||||
pretreatFunc(L)
|
||||
end
|
||||
end
|
||||
|
||||
function LANG.get(l)
|
||||
if not langList[l] then
|
||||
LOG("Wrong language: "..tostring(l))
|
||||
l=defaultLang
|
||||
end
|
||||
return langList[l]
|
||||
end
|
||||
|
||||
function LANG.addScene(name)
|
||||
for _,L in next,langList do
|
||||
if L.WidgetText and not L.WidgetText[name] then
|
||||
L.WidgetText[name]={}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LANG.init() end
|
||||
end
|
||||
return LANG
|
||||
20
Zframework/log.lua
Normal file
20
Zframework/log.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
local ins=table.insert
|
||||
|
||||
local logs={os.date("Techmino logs %Y/%m/%d %A")}
|
||||
|
||||
local function log(message)
|
||||
ins(logs,os.date("[%H:%M:%S] ")..message)
|
||||
end
|
||||
|
||||
local LOG=setmetatable({logs=logs},{
|
||||
__call=function(_,message)
|
||||
print(message)
|
||||
log(message)
|
||||
end
|
||||
})
|
||||
|
||||
function LOG.read()
|
||||
return table.concat(logs,"\n")
|
||||
end
|
||||
|
||||
return LOG
|
||||
26
Zframework/lowcaser.txt
Normal file
26
Zframework/lowcaser.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
A=a,B=b,C=c,D=d,E=e,F=f,G=g,H=h,I=i,J=j,K=k,L=l,M=m,N=n,O=o,P=p,Q=q,R=r,S=s,T=t,U=u,V=v,W=w,X=x,Y=y,Z=z
|
||||
Μ=µ,ẞ=ß,À=à,Á=á,Â=â,Ã=ã,Ä=ä,Å=å,Æ=æ,Ç=ç,È=è,É=é,Ê=ê,Ë=ë,Ì=ì,Í=í,Î=î,Ï=ï,Ð=ð,Ñ=ñ,Ò=ò,Ó=ó,Ô=ô,Õ=õ,Ö=ö,Ø=ø,Ù=ù,Ú=ú,Û=û,Ü=ü,Ý=ý,Þ=þ,Ÿ=ÿ,Ā=ā,Ă=ă,Ą=ą,Ć=ć,Ĉ=ĉ,Ċ=ċ,Č=č,Ď=ď,Đ=đ,Ē=ē,Ĕ=ĕ,Ė=ė,Ę=ę,Ě=ě,Ĝ=ĝ,Ğ=ğ,Ġ=ġ,Ģ=ģ,Ĥ=ĥ,Ħ=ħ,Ĩ=ĩ,Ī=ī,Ĭ=ĭ,Į=į,IJ=ij,Ĵ=ĵ,Ķ=ķ,Ĺ=ĺ,Ļ=ļ,Ľ=ľ,Ŀ=ŀ,Ł=ł,Ń=ń,Ņ=ņ,Ň=ň,Ŋ=ŋ,Ō=ō,Ŏ=ŏ,Ő=ő,Œ=œ,Ŕ=ŕ,Ŗ=ŗ,Ř=ř,Ś=ś,Ŝ=ŝ,Ş=ş,Š=š,Ţ=ţ,Ť=ť,Ŧ=ŧ,Ũ=ũ,Ū=ū,Ŭ=ŭ,Ů=ů,Ű=ű,Ų=ų,Ŵ=ŵ,Ŷ=ŷ,Ź=ź,Ż=ż,Ž=ž
|
||||
Ƀ=ƀ,Ƃ=ƃ,Ƅ=ƅ,Ƈ=ƈ,Ƌ=ƌ,Ƒ=ƒ,Ƕ=ƕ,Ƙ=ƙ,Ƚ=ƚ,Ƞ=ƞ,Ơ=ơ,Ƣ=ƣ,Ƥ=ƥ,Ƨ=ƨ,Ƭ=ƭ,Ư=ư,Ƴ=ƴ,Ƶ=ƶ,Ƹ=ƹ,Ƽ=ƽ,Ƿ=ƿ,DŽ=dž,LJ=lj,NJ=nj,Ǎ=ǎ,Ǐ=ǐ,Ǒ=ǒ,Ǔ=ǔ,Ǖ=ǖ,Ǘ=ǘ,Ǚ=ǚ,Ǜ=ǜ,Ǝ=ǝ,Ǟ=ǟ,Ǡ=ǡ,Ǣ=ǣ,Ǥ=ǥ,Ǧ=ǧ,Ǩ=ǩ,Ǫ=ǫ,Ǭ=ǭ,Ǯ=ǯ,DZ=dz,Ǵ=ǵ,Ǹ=ǹ,Ǻ=ǻ,Ǽ=ǽ,Ǿ=ǿ,Ȁ=ȁ,Ȃ=ȃ,Ȅ=ȅ,Ȇ=ȇ,Ȉ=ȉ,Ȋ=ȋ,Ȍ=ȍ,Ȏ=ȏ,Ȑ=ȑ,Ȓ=ȓ,Ȕ=ȕ,Ȗ=ȗ,Ș=ș,Ț=ț,Ȝ=ȝ,Ȟ=ȟ,Ȣ=ȣ,Ȥ=ȥ,Ȧ=ȧ,Ȩ=ȩ,Ȫ=ȫ,Ȭ=ȭ,Ȯ=ȯ,Ȱ=ȱ,Ȳ=ȳ,Ȼ=ȼ,Ȿ=ȿ,Ɀ=ɀ,Ɂ=ɂ,Ɇ=ɇ,Ɉ=ɉ,Ɋ=ɋ,Ɍ=ɍ,Ɏ=ɏ
|
||||
Ɐ=ɐ,Ɑ=ɑ,Ɒ=ɒ,Ɓ=ɓ,Ɔ=ɔ,Ɖ=ɖ,Ɗ=ɗ,Ə=ə,Ɛ=ɛ,Ɜ=ɜ,Ɠ=ɠ,Ɡ=ɡ,Ɣ=ɣ,Ɥ=ɥ,Ɦ=ɦ,Ɨ=ɨ,Ɩ=ɩ,Ɪ=ɪ,Ɫ=ɫ,Ɬ=ɬ,Ɯ=ɯ,Ɱ=ɱ,Ɲ=ɲ,Ɵ=ɵ,Ɽ=ɽ,Ʀ=ʀ,Ʂ=ʂ,Ʃ=ʃ,Ʇ=ʇ,Ʈ=ʈ,Ʉ=ʉ,Ʊ=ʊ,Ʋ=ʋ,Ʌ=ʌ,Ʒ=ʒ,Ʝ=ʝ,Ʞ=ʞ
|
||||
Ͱ=ͱ,Ͳ=ͳ,Ͷ=ͷ,Ͻ=ͻ,Ͼ=ͼ,Ͽ=ͽ,Ά=ά,Έ=έ,Ή=ή,Ί=ί,Α=α,Β=β,Γ=γ,Δ=δ,Ε=ε,Ζ=ζ,Η=η,Θ=θ,Κ=κ,Λ=λ,Ν=ν,Ξ=ξ,Ο=ο,Π=π,Ρ=ρ,Σ=σ,Τ=τ,Υ=υ,Φ=φ,Χ=χ,Ψ=ψ,Ω=ω,Ϊ=ϊ,Ϋ=ϋ,Ό=ό,Ύ=ύ,Ώ=ώ,Ϗ=ϗ,Ϙ=ϙ,Ϛ=ϛ,Ϝ=ϝ,Ϟ=ϟ,Ϡ=ϡ,Ϣ=ϣ,Ϥ=ϥ,Ϧ=ϧ,Ϩ=ϩ,Ϫ=ϫ,Ϭ=ϭ,Ϯ=ϯ,Ϲ=ϲ,Ϳ=ϳ,Ϸ=ϸ,Ϻ=ϻ
|
||||
А=а,Б=б,В=в,Г=г,Д=д,Е=е,Ж=ж,З=з,И=и,Й=й,К=к,Л=л,М=м,Н=н,О=о,П=п,Р=р,С=с,Т=т,У=у,Ф=ф,Х=х,Ц=ц,Ч=ч,Ш=ш,Щ=щ,Ъ=ъ,Ы=ы,Ь=ь,Э=э,Ю=ю,Я=я,Ѐ=ѐ,Ё=ё,Ђ=ђ,Ѓ=ѓ,Є=є,Ѕ=ѕ,І=і,Ї=ї,Ј=ј,Љ=љ,Њ=њ,Ћ=ћ,Ќ=ќ,Ѝ=ѝ,Ў=ў,Џ=џ,Ѡ=ѡ,Ѣ=ѣ,Ѥ=ѥ,Ѧ=ѧ,Ѩ=ѩ,Ѫ=ѫ,Ѭ=ѭ,Ѯ=ѯ,Ѱ=ѱ,Ѳ=ѳ,Ѵ=ѵ,Ѷ=ѷ,Ѹ=ѹ,Ѻ=ѻ,Ѽ=ѽ,Ѿ=ѿ,Ҁ=ҁ,Ҋ=ҋ,Ҍ=ҍ,Ҏ=ҏ,Ґ=ґ,Ғ=ғ,Ҕ=ҕ,Җ=җ,Ҙ=ҙ,Қ=қ,Ҝ=ҝ,Ҟ=ҟ,Ҡ=ҡ,Ң=ң,Ҥ=ҥ,Ҧ=ҧ,Ҩ=ҩ,Ҫ=ҫ,Ҭ=ҭ,Ү=ү,Ұ=ұ,Ҳ=ҳ,Ҵ=ҵ,Ҷ=ҷ,Ҹ=ҹ,Һ=һ,Ҽ=ҽ,Ҿ=ҿ,Ӂ=ӂ,Ӄ=ӄ,Ӆ=ӆ,Ӈ=ӈ,Ӊ=ӊ,Ӌ=ӌ,Ӎ=ӎ,Ӏ=ӏ,Ӑ=ӑ,Ӓ=ӓ,Ӕ=ӕ,Ӗ=ӗ,Ә=ә,Ӛ=ӛ,Ӝ=ӝ,Ӟ=ӟ,Ӡ=ӡ,Ӣ=ӣ,Ӥ=ӥ,Ӧ=ӧ,Ө=ө,Ӫ=ӫ,Ӭ=ӭ,Ӯ=ӯ,Ӱ=ӱ,Ӳ=ӳ,Ӵ=ӵ,Ӷ=ӷ,Ӹ=ӹ,Ӻ=ӻ,Ӽ=ӽ,Ӿ=ӿ,Ԁ=ԁ,Ԃ=ԃ,Ԅ=ԅ,Ԇ=ԇ,Ԉ=ԉ,Ԋ=ԋ,Ԍ=ԍ,Ԏ=ԏ,Ԑ=ԑ,Ԓ=ԓ,Ԕ=ԕ,Ԗ=ԗ,Ԙ=ԙ,Ԛ=ԛ,Ԝ=ԝ,Ԟ=ԟ,Ԡ=ԡ,Ԣ=ԣ,Ԥ=ԥ,Ԧ=ԧ,Ԩ=ԩ,Ԫ=ԫ,Ԭ=ԭ,Ԯ=ԯ
|
||||
Ա=ա,Բ=բ,Գ=գ,Դ=դ,Ե=ե,Զ=զ,Է=է,Ը=ը,Թ=թ,Ժ=ժ,Ի=ի,Լ=լ,Խ=խ,Ծ=ծ,Կ=կ,Հ=հ,Ձ=ձ,Ղ=ղ,Ճ=ճ,Մ=մ,Յ=յ,Ն=ն,Շ=շ,Ո=ո,Չ=չ,Պ=պ,Ջ=ջ,Ռ=ռ,Ս=ս,Վ=վ,Տ=տ,Ր=ր,Ց=ց,Ւ=ւ,Փ=փ,Ք=ք,Օ=օ,Ֆ=ֆ
|
||||
Ა=ა,Ბ=ბ,Გ=გ,Დ=დ,Ე=ე,Ვ=ვ,Ზ=ზ,Თ=თ,Ი=ი,Კ=კ,Ლ=ლ,Მ=მ,Ნ=ნ,Ო=ო,Პ=პ,Ჟ=ჟ,Რ=რ,Ს=ს,Ტ=ტ,Უ=უ,Ფ=ფ,Ქ=ქ,Ღ=ღ,Ყ=ყ,Შ=შ,Ჩ=ჩ,Ც=ც,Ძ=ძ,Წ=წ,Ჭ=ჭ,Ხ=ხ,Ჯ=ჯ,Ჰ=ჰ,Ჱ=ჱ,Ჲ=ჲ,Ჳ=ჳ,Ჴ=ჴ,Ჵ=ჵ,Ჶ=ჶ,Ჷ=ჷ,Ჸ=ჸ,Ჹ=ჹ,Ჺ=ჺ,Ჽ=ჽ,Ჾ=ჾ,Ჿ=ჿ
|
||||
Ᏸ=ᏸ,Ᏹ=ᏹ,Ᏺ=ᏺ,Ᏻ=ᏻ,Ᏼ=ᏼ,Ᏽ=ᏽ
|
||||
Ꙋ=ᲈ,Ᵹ=ᵹ,Ᵽ=ᵽ,Ᶎ=ᶎ,Ḁ=ḁ,Ḃ=ḃ,Ḅ=ḅ,Ḇ=ḇ,Ḉ=ḉ,Ḋ=ḋ,Ḍ=ḍ,Ḏ=ḏ,Ḑ=ḑ,Ḓ=ḓ,Ḕ=ḕ,Ḗ=ḗ,Ḙ=ḙ,Ḛ=ḛ,Ḝ=ḝ,Ḟ=ḟ,Ḡ=ḡ,Ḣ=ḣ,Ḥ=ḥ,Ḧ=ḧ,Ḩ=ḩ,Ḫ=ḫ,Ḭ=ḭ,Ḯ=ḯ,Ḱ=ḱ,Ḳ=ḳ,Ḵ=ḵ,Ḷ=ḷ,Ḹ=ḹ,Ḻ=ḻ,Ḽ=ḽ,Ḿ=ḿ,Ṁ=ṁ,Ṃ=ṃ,Ṅ=ṅ,Ṇ=ṇ,Ṉ=ṉ,Ṋ=ṋ,Ṍ=ṍ,Ṏ=ṏ,Ṑ=ṑ,Ṓ=ṓ,Ṕ=ṕ,Ṗ=ṗ,Ṙ=ṙ,Ṛ=ṛ,Ṝ=ṝ,Ṟ=ṟ,Ṡ=ṡ,Ṣ=ṣ,Ṥ=ṥ,Ṧ=ṧ,Ṩ=ṩ,Ṫ=ṫ,Ṭ=ṭ,Ṯ=ṯ,Ṱ=ṱ,Ṳ=ṳ,Ṵ=ṵ,Ṷ=ṷ,Ṹ=ṹ,Ṻ=ṻ,Ṽ=ṽ,Ṿ=ṿ,Ẁ=ẁ,Ẃ=ẃ,Ẅ=ẅ,Ẇ=ẇ,Ẉ=ẉ,Ẋ=ẋ,Ẍ=ẍ,Ẏ=ẏ,Ẑ=ẑ,Ẓ=ẓ,Ẕ=ẕ,Ạ=ạ,Ả=ả,Ấ=ấ,Ầ=ầ,Ẩ=ẩ,Ẫ=ẫ,Ậ=ậ,Ắ=ắ,Ằ=ằ,Ẳ=ẳ,Ẵ=ẵ,Ặ=ặ,Ẹ=ẹ,Ẻ=ẻ,Ẽ=ẽ,Ế=ế,Ề=ề,Ể=ể,Ễ=ễ,Ệ=ệ,Ỉ=ỉ,Ị=ị,Ọ=ọ,Ỏ=ỏ,Ố=ố,Ồ=ồ,Ổ=ổ,Ỗ=ỗ,Ộ=ộ,Ớ=ớ,Ờ=ờ,Ở=ở,Ỡ=ỡ,Ợ=ợ,Ụ=ụ,Ủ=ủ,Ứ=ứ,Ừ=ừ,Ử=ử,Ữ=ữ,Ự=ự,Ỳ=ỳ,Ỵ=ỵ,Ỷ=ỷ,Ỹ=ỹ,Ỻ=ỻ,Ỽ=ỽ,Ỿ=ỿ,Ἀ=ἀ,Ἁ=ἁ,Ἂ=ἂ,Ἃ=ἃ,Ἄ=ἄ,Ἅ=ἅ,Ἆ=ἆ,Ἇ=ἇ,Ἐ=ἐ,Ἑ=ἑ,Ἒ=ἒ,Ἓ=ἓ,Ἔ=ἔ,Ἕ=ἕ,Ἠ=ἠ,Ἡ=ἡ,Ἢ=ἢ,Ἣ=ἣ,Ἤ=ἤ,Ἥ=ἥ,Ἦ=ἦ,Ἧ=ἧ,Ἰ=ἰ,Ἱ=ἱ,Ἲ=ἲ,Ἳ=ἳ,Ἴ=ἴ,Ἵ=ἵ,Ἶ=ἶ,Ἷ=ἷ,Ὀ=ὀ,Ὁ=ὁ,Ὂ=ὂ,Ὃ=ὃ,Ὄ=ὄ,Ὅ=ὅ,Ὑ=ὑ,Ὓ=ὓ,Ὕ=ὕ,Ὗ=ὗ,Ὠ=ὠ,Ὡ=ὡ,Ὢ=ὢ,Ὣ=ὣ,Ὤ=ὤ,Ὥ=ὥ,Ὦ=ὦ,Ὧ=ὧ,Ὰ=ὰ,Ά=ά,Ὲ=ὲ,Έ=έ,Ὴ=ὴ,Ή=ή,Ὶ=ὶ,Ί=ί,Ὸ=ὸ,Ό=ό,Ὺ=ὺ,Ύ=ύ,Ὼ=ὼ,Ώ=ώ,Ᾰ=ᾰ,Ᾱ=ᾱ,Ῐ=ῐ,Ῑ=ῑ,Ῠ=ῠ,Ῡ=ῡ,Ῥ=ῥ,Ⅎ=ⅎ
|
||||
Ⅰ=ⅰ,Ⅱ=ⅱ,Ⅲ=ⅲ,Ⅳ=ⅳ,Ⅴ=ⅴ,Ⅵ=ⅵ,Ⅶ=ⅶ,Ⅷ=ⅷ,Ⅸ=ⅸ,Ⅹ=ⅹ,Ⅺ=ⅺ,Ⅻ=ⅻ,Ⅼ=ⅼ,Ⅽ=ⅽ,Ⅾ=ⅾ,Ⅿ=ⅿ,Ↄ=ↄ
|
||||
Ⓐ=ⓐ,Ⓑ=ⓑ,Ⓒ=ⓒ,Ⓓ=ⓓ,Ⓔ=ⓔ,Ⓕ=ⓕ,Ⓖ=ⓖ,Ⓗ=ⓗ,Ⓘ=ⓘ,Ⓙ=ⓙ,Ⓚ=ⓚ,Ⓛ=ⓛ,Ⓜ=ⓜ,Ⓝ=ⓝ,Ⓞ=ⓞ,Ⓟ=ⓟ,Ⓠ=ⓠ,Ⓡ=ⓡ,Ⓢ=ⓢ,Ⓣ=ⓣ,Ⓤ=ⓤ,Ⓥ=ⓥ,Ⓦ=ⓦ,Ⓧ=ⓧ,Ⓨ=ⓨ,Ⓩ=ⓩ
|
||||
Ⰰ=ⰰ,Ⰱ=ⰱ,Ⰲ=ⰲ,Ⰳ=ⰳ,Ⰴ=ⰴ,Ⰵ=ⰵ,Ⰶ=ⰶ,Ⰷ=ⰷ,Ⰸ=ⰸ,Ⰹ=ⰹ,Ⰺ=ⰺ,Ⰻ=ⰻ,Ⰼ=ⰼ,Ⰽ=ⰽ,Ⰾ=ⰾ,Ⰿ=ⰿ,Ⱀ=ⱀ,Ⱁ=ⱁ,Ⱂ=ⱂ,Ⱃ=ⱃ,Ⱄ=ⱄ,Ⱅ=ⱅ,Ⱆ=ⱆ,Ⱇ=ⱇ,Ⱈ=ⱈ,Ⱉ=ⱉ,Ⱊ=ⱊ,Ⱋ=ⱋ,Ⱌ=ⱌ,Ⱍ=ⱍ,Ⱎ=ⱎ,Ⱏ=ⱏ,Ⱐ=ⱐ,Ⱑ=ⱑ,Ⱒ=ⱒ,Ⱓ=ⱓ,Ⱔ=ⱔ,Ⱕ=ⱕ,Ⱖ=ⱖ,Ⱗ=ⱗ,Ⱘ=ⱘ,Ⱙ=ⱙ,Ⱚ=ⱚ,Ⱛ=ⱛ,Ⱜ=ⱜ,Ⱝ=ⱝ,Ⱞ=ⱞ,Ⱟ=ⱟ
|
||||
Ⱡ=ⱡ,Ⱥ=ⱥ,Ⱦ=ⱦ,Ⱨ=ⱨ,Ⱪ=ⱪ,Ⱬ=ⱬ,Ⱳ=ⱳ,Ⱶ=ⱶ
|
||||
Ⲁ=ⲁ,Ⲃ=ⲃ,Ⲅ=ⲅ,Ⲇ=ⲇ,Ⲉ=ⲉ,Ⲋ=ⲋ,Ⲍ=ⲍ,Ⲏ=ⲏ,Ⲑ=ⲑ,Ⲓ=ⲓ,Ⲕ=ⲕ,Ⲗ=ⲗ,Ⲙ=ⲙ,Ⲛ=ⲛ,Ⲝ=ⲝ,Ⲟ=ⲟ,Ⲡ=ⲡ,Ⲣ=ⲣ,Ⲥ=ⲥ,Ⲧ=ⲧ,Ⲩ=ⲩ,Ⲫ=ⲫ,Ⲭ=ⲭ,Ⲯ=ⲯ,Ⲱ=ⲱ,Ⲳ=ⲳ,Ⲵ=ⲵ,Ⲷ=ⲷ,Ⲹ=ⲹ,Ⲻ=ⲻ,Ⲽ=ⲽ,Ⲿ=ⲿ,Ⳁ=ⳁ,Ⳃ=ⳃ,Ⳅ=ⳅ,Ⳇ=ⳇ,Ⳉ=ⳉ,Ⳋ=ⳋ,Ⳍ=ⳍ,Ⳏ=ⳏ,Ⳑ=ⳑ,Ⳓ=ⳓ,Ⳕ=ⳕ,Ⳗ=ⳗ,Ⳙ=ⳙ,Ⳛ=ⳛ,Ⳝ=ⳝ,Ⳟ=ⳟ,Ⳡ=ⳡ,Ⳣ=ⳣ,Ⳬ=ⳬ,Ⳮ=ⳮ,Ⳳ=ⳳ
|
||||
Ⴀ=ⴀ,Ⴁ=ⴁ,Ⴂ=ⴂ,Ⴃ=ⴃ,Ⴄ=ⴄ,Ⴅ=ⴅ,Ⴆ=ⴆ,Ⴇ=ⴇ,Ⴈ=ⴈ,Ⴉ=ⴉ,Ⴊ=ⴊ,Ⴋ=ⴋ,Ⴌ=ⴌ,Ⴍ=ⴍ,Ⴎ=ⴎ,Ⴏ=ⴏ,Ⴐ=ⴐ,Ⴑ=ⴑ,Ⴒ=ⴒ,Ⴓ=ⴓ,Ⴔ=ⴔ,Ⴕ=ⴕ,Ⴖ=ⴖ,Ⴗ=ⴗ,Ⴘ=ⴘ,Ⴙ=ⴙ,Ⴚ=ⴚ,Ⴛ=ⴛ,Ⴜ=ⴜ,Ⴝ=ⴝ,Ⴞ=ⴞ,Ⴟ=ⴟ,Ⴠ=ⴠ,Ⴡ=ⴡ,Ⴢ=ⴢ,Ⴣ=ⴣ,Ⴤ=ⴤ,Ⴥ=ⴥ,Ⴧ=ⴧ
|
||||
Ⴭ=ⴭ,Ꙁ=ꙁ,Ꙃ=ꙃ,Ꙅ=ꙅ,Ꙇ=ꙇ,Ꙉ=ꙉ,Ꙍ=ꙍ,Ꙏ=ꙏ,Ꙑ=ꙑ,Ꙓ=ꙓ,Ꙕ=ꙕ,Ꙗ=ꙗ,Ꙙ=ꙙ,Ꙛ=ꙛ,Ꙝ=ꙝ,Ꙟ=ꙟ,Ꙡ=ꙡ,Ꙣ=ꙣ,Ꙥ=ꙥ,Ꙧ=ꙧ,Ꙩ=ꙩ,Ꙫ=ꙫ,Ꙭ=ꙭ,Ꚁ=ꚁ,Ꚃ=ꚃ,Ꚅ=ꚅ,Ꚇ=ꚇ,Ꚉ=ꚉ,Ꚋ=ꚋ,Ꚍ=ꚍ,Ꚏ=ꚏ,Ꚑ=ꚑ,Ꚓ=ꚓ,Ꚕ=ꚕ,Ꚗ=ꚗ,Ꚙ=ꚙ,Ꚛ=ꚛ,Ꜣ=ꜣ,Ꜥ=ꜥ,Ꜧ=ꜧ,Ꜩ=ꜩ,Ꜫ=ꜫ,Ꜭ=ꜭ,Ꜯ=ꜯ,Ꜳ=ꜳ,Ꜵ=ꜵ,Ꜷ=ꜷ,Ꜹ=ꜹ,Ꜻ=ꜻ,Ꜽ=ꜽ,Ꜿ=ꜿ,Ꝁ=ꝁ,Ꝃ=ꝃ,Ꝅ=ꝅ,Ꝇ=ꝇ,Ꝉ=ꝉ,Ꝋ=ꝋ,Ꝍ=ꝍ,Ꝏ=ꝏ,Ꝑ=ꝑ,Ꝓ=ꝓ,Ꝕ=ꝕ,Ꝗ=ꝗ,Ꝙ=ꝙ,Ꝛ=ꝛ,Ꝝ=ꝝ,Ꝟ=ꝟ,Ꝡ=ꝡ,Ꝣ=ꝣ,Ꝥ=ꝥ,Ꝧ=ꝧ,Ꝩ=ꝩ,Ꝫ=ꝫ,Ꝭ=ꝭ,Ꝯ=ꝯ,Ꝺ=ꝺ,Ꝼ=ꝼ,Ꝿ=ꝿ,Ꞁ=ꞁ,Ꞃ=ꞃ,Ꞅ=ꞅ,Ꞇ=ꞇ,Ꞌ=ꞌ,Ꞑ=ꞑ,Ꞓ=ꞓ,Ꞔ=ꞔ,Ꞗ=ꞗ,Ꞙ=ꞙ,Ꞛ=ꞛ,Ꞝ=ꞝ,Ꞟ=ꞟ,Ꞡ=ꞡ,Ꞣ=ꞣ,Ꞥ=ꞥ,Ꞧ=ꞧ,Ꞩ=ꞩ,Ꞵ=ꞵ,Ꞷ=ꞷ,Ꞹ=ꞹ,Ꞻ=ꞻ,Ꞽ=ꞽ,Ꞿ=ꞿ,Ꟁ=ꟁ,Ꟃ=ꟃ,Ꟈ=ꟈ,Ꟊ=ꟊ,Ꟑ=ꟑ,Ꟗ=ꟗ,Ꟙ=ꟙ,Ꟶ=ꟶ,Ꭓ=ꭓ
|
||||
Ꭰ=ꭰ,Ꭱ=ꭱ,Ꭲ=ꭲ,Ꭳ=ꭳ,Ꭴ=ꭴ,Ꭵ=ꭵ,Ꭶ=ꭶ,Ꭷ=ꭷ,Ꭸ=ꭸ,Ꭹ=ꭹ,Ꭺ=ꭺ,Ꭻ=ꭻ,Ꭼ=ꭼ,Ꭽ=ꭽ,Ꭾ=ꭾ,Ꭿ=ꭿ,Ꮀ=ꮀ,Ꮁ=ꮁ,Ꮂ=ꮂ,Ꮃ=ꮃ,Ꮄ=ꮄ,Ꮅ=ꮅ,Ꮆ=ꮆ,Ꮇ=ꮇ,Ꮈ=ꮈ,Ꮉ=ꮉ,Ꮊ=ꮊ,Ꮋ=ꮋ,Ꮌ=ꮌ,Ꮍ=ꮍ,Ꮎ=ꮎ,Ꮏ=ꮏ,Ꮐ=ꮐ,Ꮑ=ꮑ,Ꮒ=ꮒ,Ꮓ=ꮓ,Ꮔ=ꮔ,Ꮕ=ꮕ,Ꮖ=ꮖ,Ꮗ=ꮗ,Ꮘ=ꮘ,Ꮙ=ꮙ,Ꮚ=ꮚ,Ꮛ=ꮛ,Ꮜ=ꮜ,Ꮝ=ꮝ,Ꮞ=ꮞ,Ꮟ=ꮟ,Ꮠ=ꮠ,Ꮡ=ꮡ,Ꮢ=ꮢ,Ꮣ=ꮣ,Ꮤ=ꮤ,Ꮥ=ꮥ,Ꮦ=ꮦ,Ꮧ=ꮧ,Ꮨ=ꮨ,Ꮩ=ꮩ,Ꮪ=ꮪ,Ꮫ=ꮫ,Ꮬ=ꮬ,Ꮭ=ꮭ,Ꮮ=ꮮ,Ꮯ=ꮯ,Ꮰ=ꮰ,Ꮱ=ꮱ,Ꮲ=ꮲ,Ꮳ=ꮳ,Ꮴ=ꮴ,Ꮵ=ꮵ,Ꮶ=ꮶ,Ꮷ=ꮷ,Ꮸ=ꮸ,Ꮹ=ꮹ,Ꮺ=ꮺ,Ꮻ=ꮻ,Ꮼ=ꮼ,Ꮽ=ꮽ,Ꮾ=ꮾ,Ꮿ=ꮿ
|
||||
A=a,B=b,C=c,D=d,E=e,F=f,G=g,H=h,I=i,J=j,K=k,L=l,M=m,N=n,O=o,P=p,Q=q,R=r,S=s,T=t,U=u,V=v,W=w,X=x,Y=y,Z=z
|
||||
𐐀=𐐨,𐐁=𐐩,𐐂=𐐪,𐐃=𐐫,𐐄=𐐬,𐐅=𐐭,𐐆=𐐮,𐐇=𐐯,𐐈=𐐰,𐐉=𐐱,𐐊=𐐲,𐐋=𐐳,𐐌=𐐴,𐐍=𐐵,𐐎=𐐶,𐐏=𐐷,𐐐=𐐸,𐐑=𐐹,𐐒=𐐺,𐐓=𐐻,𐐔=𐐼,𐐕=𐐽,𐐖=𐐾,𐐗=𐐿,𐐘=𐑀,𐐙=𐑁,𐐚=𐑂,𐐛=𐑃,𐐜=𐑄,𐐝=𐑅,𐐞=𐑆,𐐟=𐑇,𐐠=𐑈,𐐡=𐑉,𐐢=𐑊,𐐣=𐑋,𐐤=𐑌,𐐥=𐑍,𐐦=𐑎,𐐧=𐑏
|
||||
𐒰=𐓘,𐒱=𐓙,𐒲=𐓚,𐒳=𐓛,𐒴=𐓜,𐒵=𐓝,𐒶=𐓞,𐒷=𐓟,𐒸=𐓠,𐒹=𐓡,𐒺=𐓢,𐒻=𐓣,𐒼=𐓤,𐒽=𐓥,𐒾=𐓦,𐒿=𐓧,𐓀=𐓨,𐓁=𐓩,𐓂=𐓪,𐓃=𐓫,𐓄=𐓬,𐓅=𐓭,𐓆=𐓮,𐓇=𐓯,𐓈=𐓰,𐓉=𐓱,𐓊=𐓲,𐓋=𐓳,𐓌=𐓴,𐓍=𐓵,𐓎=𐓶,𐓏=𐓷,𐓐=𐓸,𐓑=𐓹,𐓒=𐓺,𐓓=𐓻
|
||||
𐲀=𐳀,𐲁=𐳁,𐲂=𐳂,𐲃=𐳃,𐲄=𐳄,𐲅=𐳅,𐲆=𐳆,𐲇=𐳇,𐲈=𐳈,𐲉=𐳉,𐲊=𐳊,𐲋=𐳋,𐲌=𐳌,𐲍=𐳍,𐲎=𐳎,𐲏=𐳏,𐲐=𐳐,𐲑=𐳑,𐲒=𐳒,𐲓=𐳓,𐲔=𐳔,𐲕=𐳕,𐲖=𐳖,𐲗=𐳗,𐲘=𐳘,𐲙=𐳙,𐲚=𐳚,𐲛=𐳛,𐲜=𐳜,𐲝=𐳝,𐲞=𐳞,𐲟=𐳟,𐲠=𐳠,𐲡=𐳡,𐲢=𐳢,𐲣=𐳣,𐲤=𐳤,𐲥=𐳥,𐲦=𐳦,𐲧=𐳧,𐲨=𐳨,𐲩=𐳩,𐲪=𐳪,𐲫=𐳫,𐲬=𐳬,𐲭=𐳭,𐲮=𐳮,𐲯=𐳯,𐲰=𐳰,𐲱=𐳱,𐲲=𐳲
|
||||
𑢠=𑣀,𑢡=𑣁,𑢢=𑣂,𑢣=𑣃,𑢤=𑣄,𑢥=𑣅,𑢦=𑣆,𑢧=𑣇,𑢨=𑣈,𑢩=𑣉,𑢪=𑣊,𑢫=𑣋,𑢬=𑣌,𑢭=𑣍,𑢮=𑣎,𑢯=𑣏,𑢰=𑣐,𑢱=𑣑,𑢲=𑣒,𑢳=𑣓,𑢴=𑣔,𑢵=𑣕,𑢶=𑣖,𑢷=𑣗,𑢸=𑣘,𑢹=𑣙,𑢺=𑣚,𑢻=𑣛,𑢼=𑣜,𑢽=𑣝,𑢾=𑣞,𑢿=𑣟
|
||||
𖹀=𖹠,𖹁=𖹡,𖹂=𖹢,𖹃=𖹣,𖹄=𖹤,𖹅=𖹥,𖹆=𖹦,𖹇=𖹧,𖹈=𖹨,𖹉=𖹩,𖹊=𖹪,𖹋=𖹫,𖹌=𖹬,𖹍=𖹭,𖹎=𖹮,𖹏=𖹯,𖹐=𖹰,𖹑=𖹱,𖹒=𖹲,𖹓=𖹳,𖹔=𖹴,𖹕=𖹵,𖹖=𖹶,𖹗=𖹷,𖹘=𖹸,𖹙=𖹹,𖹚=𖹺,𖹛=𖹻,𖹜=𖹼,𖹝=𖹽,𖹞=𖹾,𖹟=𖹿
|
||||
𞤀=𞤢,𞤁=𞤣,𞤂=𞤤,𞤃=𞤥,𞤄=𞤦,𞤅=𞤧,𞤆=𞤨,𞤇=𞤩,𞤈=𞤪,𞤉=𞤫,𞤊=𞤬,𞤋=𞤭,𞤌=𞤮,𞤍=𞤯,𞤎=𞤰,𞤏=𞤱,𞤐=𞤲,𞤑=𞤳,𞤒=𞤴,𞤓=𞤵,𞤔=𞤶,𞤕=𞤷,𞤖=𞤸,𞤗=𞤹,𞤘=𞤺,𞤙=𞤻,𞤚=𞤼,𞤛=𞤽,𞤜=𞤾,𞤝=𞤿,𞤞=𞥀,𞤟=𞥁,𞤠=𞥂,𞤡=𞥃
|
||||
İ=i̇,ʼN=ʼn,J̌=ǰ,Ϊ́=ΐ,Ϋ́=ΰ,ԵՒ=և,H̱=ẖ,T̈=ẗ,W̊=ẘ,Y̊=ẙ,Aʾ=ẚ,Υ̓=ὐ,Υ̓̀=ὒ,Υ̓́=ὔ,Υ̓͂=ὖ,ἈΙ=ᾀ,ἉΙ=ᾁ,ἊΙ=ᾂ,ἋΙ=ᾃ,ἌΙ=ᾄ,ἍΙ=ᾅ,ἎΙ=ᾆ,ἏΙ=ᾇ,ἨΙ=ᾐ,ἩΙ=ᾑ,ἪΙ=ᾒ,ἫΙ=ᾓ,ἬΙ=ᾔ,ἭΙ=ᾕ,ἮΙ=ᾖ,ἯΙ=ᾗ,ὨΙ=ᾠ,ὩΙ=ᾡ,ὪΙ=ᾢ,ὫΙ=ᾣ,ὬΙ=ᾤ,ὭΙ=ᾥ,ὮΙ=ᾦ,ὯΙ=ᾧ,ᾺΙ=ᾲ,ΑΙ=ᾳ,ΆΙ=ᾴ,Α͂=ᾶ,Α͂Ι=ᾷ,ῊΙ=ῂ,ΗΙ=ῃ,ΉΙ=ῄ,Η͂=ῆ,Η͂Ι=ῇ,Ϊ̀=ῒ,Ι͂=ῖ,Ϊ͂=ῗ,Ϋ̀=ῢ,Ρ̓=ῤ,Υ͂=ῦ,Ϋ͂=ῧ,ῺΙ=ῲ,ΩΙ=ῳ,ΏΙ=ῴ,Ω͂=ῶ,Ω͂Ι=ῷ,ՄՆ=ﬓ,ՄԵ=ﬔ,ՄԻ=ﬕ,ՎՆ=ﬖ,ՄԽ=ﬗ
|
||||
88
Zframework/mathExtend.lua
Normal file
88
Zframework/mathExtend.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
local MATH={} for k,v in next,math do MATH[k]=v end
|
||||
|
||||
local floor,ceil=math.floor,math.ceil
|
||||
local rnd=math.random
|
||||
local exp=math.exp
|
||||
|
||||
MATH.tau=2*math.pi
|
||||
MATH.phi=(1+math.sqrt(5))/2
|
||||
MATH.inf=1/0
|
||||
MATH.nan=0/0
|
||||
|
||||
function MATH.isnan(n)
|
||||
return n~=n
|
||||
end
|
||||
|
||||
function MATH.sign(a)
|
||||
return a>0 and 1 or a<0 and -1 or 0
|
||||
end
|
||||
|
||||
function MATH.roll(chance)
|
||||
return rnd()<(chance or .5)
|
||||
end
|
||||
|
||||
function MATH.coin(a,b)
|
||||
if rnd()<.5 then
|
||||
return a
|
||||
else
|
||||
return b
|
||||
end
|
||||
end
|
||||
|
||||
function MATH.clamp(v,low,high)
|
||||
if v<=low then
|
||||
return low
|
||||
elseif v>=high then
|
||||
return high
|
||||
else
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
function MATH.mix(s,e,t)
|
||||
return s+(e-s)*t
|
||||
end
|
||||
|
||||
do-- function MATH.listMix(list,t)
|
||||
local clamp,mix=MATH.clamp,MATH.mix
|
||||
function MATH.listMix(list,t)
|
||||
local t2=(#list-1)*clamp(t,0,1)+1
|
||||
return mix(list[floor(t2)],list[ceil(t2)],t2%1)
|
||||
end
|
||||
end
|
||||
|
||||
function MATH.expApproach(a,b,k)
|
||||
return b+(a-b)*exp(-k)
|
||||
end
|
||||
|
||||
function MATH.distance(x1,y1,x2,y2)
|
||||
return ((x1-x2)^2+(y1-y2)^2)^.5
|
||||
end
|
||||
|
||||
-- By Pedro Gimeno,donated to the public domain
|
||||
function MATH.pointInPolygon(x,y,poly,evenOddRule)
|
||||
local x1,y1,x2,y2
|
||||
local len=#poly
|
||||
x2,y2=poly[len-1],poly[len]
|
||||
local wn=0
|
||||
for idx=1,len,2 do
|
||||
x1,y1=x2,y2
|
||||
x2,y2=poly[idx],poly[idx+1]
|
||||
if y1>y then
|
||||
if y2<=y and (x1-x)*(y2-y)<(x2-x)*(y1-y) then
|
||||
wn=wn+1
|
||||
end
|
||||
else
|
||||
if y2>y and (x1-x)*(y2-y)>(x2-x)*(y1-y) then
|
||||
wn=wn-1
|
||||
end
|
||||
end
|
||||
end
|
||||
if evenOddRule then
|
||||
return wn%2~=0
|
||||
else-- non-zero winding rule
|
||||
return wn~=0
|
||||
end
|
||||
end
|
||||
|
||||
return MATH
|
||||
153
Zframework/message.lua
Normal file
153
Zframework/message.lua
Normal file
@@ -0,0 +1,153 @@
|
||||
local ins,rem=table.insert,table.remove
|
||||
local max=math.max
|
||||
|
||||
local mesList={}
|
||||
local mesIcon={
|
||||
check=GC.DO{40,40,
|
||||
{'setLW',10},
|
||||
{'setCL',0,0,0},
|
||||
{'line',4,19,15,30,36,9},
|
||||
{'setLW',6},
|
||||
{'setCL',.7,1,.6},
|
||||
{'line',5,20,15,30,35,10},
|
||||
},
|
||||
info=GC.DO{40,40,
|
||||
{'setCL',.2,.25,.85},
|
||||
{'fCirc',20,20,15},
|
||||
{'setCL',1,1,1},
|
||||
{'setLW',2},
|
||||
{'dCirc',20,20,15},
|
||||
{'fRect',18,11,4,4},
|
||||
{'fRect',18,17,4,12},
|
||||
},
|
||||
broadcast=GC.DO{40,40,
|
||||
{'setCL',1,1,1},
|
||||
{'fRect',2,4,36,26,3},
|
||||
{'fPoly',2,27,2,37,14,25},
|
||||
{'setCL',.5,.5,.5},
|
||||
{'fRect',6,11,4,4,1},{'fRect',14,11,19,4,1},
|
||||
{'fRect',6,19,4,4,1},{'fRect',14,19,19,4,1},
|
||||
},
|
||||
warn=GC.DO{40,40,
|
||||
{'setCL',.95,.83,.4},
|
||||
{'fPoly',20.5,1,0,38,40,38},
|
||||
{'setCL',0,0,0},
|
||||
{'dPoly',20.5,1,0,38,40,38},
|
||||
{'fRect',17,10,7,18,2},
|
||||
{'fRect',17,29,7,7,2},
|
||||
{'setCL',1,1,1},
|
||||
{'fRect',18,11,5,16,2},
|
||||
{'fRect',18,30,5,5,2},
|
||||
},
|
||||
error=GC.DO{40,40,
|
||||
{'setCL',.95,.3,.3},
|
||||
{'fCirc',20,20,19},
|
||||
{'setCL',0,0,0},
|
||||
{'dCirc',20,20,19},
|
||||
{'setLW',6},
|
||||
{'line',10.2,10.2,29.8,29.8},
|
||||
{'line',10.2,29.8,29.8,10.2},
|
||||
{'setLW',4},
|
||||
{'setCL',1,1,1},
|
||||
{'line',11,11,29,29},
|
||||
{'line',11,29,29,11},
|
||||
},
|
||||
music=GC.DO{40,40,
|
||||
{'setLW',2},
|
||||
{'dRect',1,3,38,34,3},
|
||||
{'setLW',4},
|
||||
{'line',21,26,21,10,28,10},
|
||||
{'fElps',17,26,6,5},
|
||||
},
|
||||
}
|
||||
|
||||
local MES={}
|
||||
local backColors={
|
||||
check={.3,.6,.3,.7},
|
||||
broadcast={.3,.3,.6,.8},
|
||||
warn={.4,.4,.2,.9},
|
||||
error={.4,.2,.2,.9},
|
||||
music={.2,.4,.4,.9},
|
||||
other={.5,.5,.5,.7},
|
||||
}
|
||||
function MES.new(icon,str,time)
|
||||
local color=backColors.other
|
||||
if type(icon)=='string' then
|
||||
color=TABLE.shift(backColors[icon] or color)
|
||||
icon=mesIcon[icon]
|
||||
end
|
||||
local text=GC.newText(FONT.get(30),str)
|
||||
local w=math.max(text:getWidth()+(icon and 45 or 5),200)+15
|
||||
local h=math.max(text:getHeight(),46)+2
|
||||
local k=h>400 and 1/math.min(h/400,2.6) or 1
|
||||
|
||||
ins(mesList,1,{
|
||||
startTime=.26,
|
||||
endTime=.26,
|
||||
time=time or 3,
|
||||
|
||||
color=color,
|
||||
text=text,icon=icon,
|
||||
w=w,h=h,k=k,
|
||||
y=-h,
|
||||
})
|
||||
end
|
||||
|
||||
function MES.update(dt)
|
||||
for i=#mesList,1,-1 do
|
||||
local m=mesList[i]
|
||||
if m.startTime>0 then
|
||||
m.startTime=max(m.startTime-dt,0)
|
||||
elseif m.time>0 then
|
||||
m.time=max(m.time-dt,0)
|
||||
elseif m.endTime>0 then
|
||||
m.endTime=m.endTime-dt
|
||||
else
|
||||
rem(mesList,i)
|
||||
end
|
||||
if i>1 then
|
||||
local _m=mesList[i-1]
|
||||
m.y=MATH.expApproach(m.y,_m.y+_m.h*_m.k+3,dt*26)
|
||||
else
|
||||
m.y=MATH.expApproach(m.y,3,dt*26)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MES.draw()
|
||||
if #mesList>0 then
|
||||
GC.setLineWidth(2)
|
||||
for i=1,#mesList do
|
||||
local m=mesList[i]
|
||||
local a=3.846*(m.endTime-m.startTime)
|
||||
GC.push('transform')
|
||||
GC.translate(3+SCR.safeX,m.y)
|
||||
GC.scale(m.k)
|
||||
|
||||
GC.setColor(m.color[1],m.color[2],m.color[3],m.color[4]*a)
|
||||
GC.rectangle('fill',0,0,m.w,m.h,8)
|
||||
GC.setColor(.62,.62,.62,a*.626)
|
||||
GC.rectangle('line',1,1,m.w-2,m.h-2,4)
|
||||
GC.setColor(1,1,1,a)
|
||||
if m.icon then
|
||||
GC.draw(m.icon,4,4,nil,40/m.icon:getWidth(),40/m.icon:getHeight())
|
||||
end
|
||||
GC.simpY(m.text,m.icon and 50 or 10,m.h/2)
|
||||
GC.pop()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MES.traceback()
|
||||
local mes=
|
||||
debug.traceback('',1)
|
||||
:gsub(': in function',', in')
|
||||
:gsub(':',' ')
|
||||
:gsub('\t','')
|
||||
MES.new('error',mes:sub(
|
||||
mes:find("\n",2)+1,
|
||||
mes:find("\n%[C%], in 'xpcall'")
|
||||
),5)
|
||||
end
|
||||
|
||||
return MES
|
||||
157
Zframework/profile.lua
Normal file
157
Zframework/profile.lua
Normal file
@@ -0,0 +1,157 @@
|
||||
local clock=os.clock
|
||||
|
||||
local profile={}
|
||||
|
||||
local _labeled={} -- function labels
|
||||
local _defined={} -- function definitions
|
||||
local _tcalled={} -- time of last call
|
||||
local _telapsed={}-- total execution time
|
||||
local _ncalls={} -- number of calls
|
||||
local _internal={}-- list of internal profiler functions
|
||||
|
||||
local getInfo=debug.getinfo
|
||||
function profile.hooker(event,line,info)
|
||||
info=info or getInfo(2,'fnS')
|
||||
local f=info.func
|
||||
if _internal[f] then return end-- ignore the profiler itself
|
||||
if info.name then _labeled[f]=info.name end-- get the function name if available
|
||||
-- find the line definition
|
||||
if not _defined[f] then
|
||||
_defined[f]=info.short_src..":"..info.linedefined
|
||||
_ncalls[f]=0
|
||||
_telapsed[f]=0
|
||||
end
|
||||
if _tcalled[f] then
|
||||
local dt=clock()-_tcalled[f]
|
||||
_telapsed[f]=_telapsed[f]+dt
|
||||
_tcalled[f]=nil
|
||||
end
|
||||
if event=='tail call' then
|
||||
local prev=getInfo(3,'fnS')
|
||||
profile.hooker('return',line,prev)
|
||||
profile.hooker('call',line,info)
|
||||
elseif event=='call' then
|
||||
_tcalled[f]=clock()
|
||||
else
|
||||
_ncalls[f]=_ncalls[f]+1
|
||||
end
|
||||
end
|
||||
|
||||
--- Starts collecting data.
|
||||
function profile.start()
|
||||
if jit then
|
||||
jit.off()
|
||||
jit.flush()
|
||||
end
|
||||
debug.sethook(profile.hooker,'cr')
|
||||
end
|
||||
|
||||
--- Stops collecting data.
|
||||
function profile.stop()
|
||||
debug.sethook()
|
||||
for f in next,_tcalled do
|
||||
local dt=clock()-_tcalled[f]
|
||||
_telapsed[f]=_telapsed[f]+dt
|
||||
_tcalled[f]=nil
|
||||
end
|
||||
-- merge closures
|
||||
local lookup={}
|
||||
for f,d in next,_defined do
|
||||
local id=(_labeled[f] or "?")..d
|
||||
local f2=lookup[id]
|
||||
if f2 then
|
||||
_ncalls[f2]=_ncalls[f2]+(_ncalls[f] or 0)
|
||||
_telapsed[f2]=_telapsed[f2]+(_telapsed[f] or 0)
|
||||
_defined[f],_labeled[f]=nil,nil
|
||||
_ncalls[f],_telapsed[f]=nil,nil
|
||||
else
|
||||
lookup[id]=f
|
||||
end
|
||||
end
|
||||
collectgarbage()
|
||||
end
|
||||
|
||||
--- Resets all collected data.
|
||||
function profile.reset()
|
||||
for f in next,_ncalls do
|
||||
_ncalls[f]=0
|
||||
_telapsed[f]=0
|
||||
_tcalled[f]=nil
|
||||
end
|
||||
collectgarbage()
|
||||
end
|
||||
|
||||
local function _comp(a,b)
|
||||
local dt=_telapsed[b]-_telapsed[a]
|
||||
return dt==0 and _ncalls[b]<_ncalls[a] or dt<0
|
||||
end
|
||||
|
||||
--- Iterates all functions that have been called since the profile was started.
|
||||
function profile.query(limit)
|
||||
local t={}
|
||||
for f,n in next,_ncalls do
|
||||
if n>0 then
|
||||
t[#t+1]=f
|
||||
end
|
||||
end
|
||||
table.sort(t,_comp)
|
||||
|
||||
if limit then while #t>limit do table.remove(t) end end
|
||||
|
||||
for i,f in ipairs(t) do
|
||||
local dt=0
|
||||
if _tcalled[f] then
|
||||
dt=clock()-_tcalled[f]
|
||||
end
|
||||
t[i]={i,_labeled[f] or "?",math.floor((_telapsed[f]+dt)*1e6)/1e6,_ncalls[f],_defined[f]}
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local cols={3,20,8,6,32}
|
||||
function profile.report(n)
|
||||
local out={}
|
||||
local report=profile.query(n)
|
||||
for i,row in ipairs(report) do
|
||||
for j=1,5 do
|
||||
local s=tostring(row[j])
|
||||
local l1,l2=#s,cols[j]
|
||||
if l1<l2 then
|
||||
s=s..(" "):rep(l2-l1)
|
||||
elseif l1>l2 then
|
||||
s=s:sub(l1-l2+1,l1)
|
||||
end
|
||||
row[j]=s
|
||||
end
|
||||
out[i]=table.concat(row," | ")
|
||||
end
|
||||
|
||||
local row=" +-----+----------------------+----------+--------+----------------------------------+ \n"
|
||||
local col=" | # | Function | Time | Calls | Code | \n"
|
||||
local sz=row..col..row
|
||||
if #out>0 then
|
||||
sz=sz.." | "..table.concat(out," | \n | ").." | \n"
|
||||
end
|
||||
return "\n"..sz..row
|
||||
end
|
||||
|
||||
local switch=false
|
||||
function profile.switch()
|
||||
switch=not switch
|
||||
if not switch then
|
||||
profile.stop()
|
||||
love.system.setClipboardText(profile.report())
|
||||
profile.reset()
|
||||
return false
|
||||
else
|
||||
profile.start()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- store all internal profiler functions
|
||||
for _,v in next,profile do
|
||||
_internal[v]=type(v)=='function'
|
||||
end
|
||||
|
||||
return profile
|
||||
47
Zframework/require.lua
Normal file
47
Zframework/require.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
package.cpath=package.cpath..';'..love.filesystem.getSaveDirectory()..'/lib/?.so;'..'?.dylib'
|
||||
local loaded={}
|
||||
local errorCount={}
|
||||
return function(libName)
|
||||
local require=require
|
||||
local arch='unknown'
|
||||
local success,res
|
||||
if SYSTEM=='Web' then
|
||||
return
|
||||
end
|
||||
if SYSTEM=='macOS' then
|
||||
require=package.loadlib(libName..'.dylib','luaopen_'..libName)
|
||||
success,res=pcall(require)
|
||||
else
|
||||
if SYSTEM=='Android' and not loaded[libName] then
|
||||
local platform=(function()
|
||||
local p=io.popen('uname -m')
|
||||
arch=p:read('*a'):lower()
|
||||
p:close()
|
||||
if arch:find('v8') and not arch:find('v8l') or arch:find('64') then
|
||||
return 'arm64-v8a'
|
||||
else
|
||||
return 'armeabi-v7a'
|
||||
end
|
||||
end)()
|
||||
local data=love.filesystem.read('data','libAndroid/'..platform..'/'..libName..'.so')
|
||||
if data then
|
||||
love.filesystem.write('lib/'..libName..'.so',data)
|
||||
end
|
||||
loaded[libName]=true
|
||||
end
|
||||
success,res=pcall(require,libName)
|
||||
end
|
||||
if success and res then
|
||||
return res
|
||||
else
|
||||
if not next(errorCount) then
|
||||
MES.new('info',"Architecture: "..arch)
|
||||
end
|
||||
errorCount[libName]=(errorCount[libName] or 0)+1
|
||||
if errorCount[libName]==1 then
|
||||
MES.new('error',"Cannot load "..libName..": "..tostring(res):gsub('[\128-\255]+','??'))
|
||||
else
|
||||
MES.new('error',("Cannot load %s (x%d)"):format(libName,errorCount[libName]))
|
||||
end
|
||||
end
|
||||
end
|
||||
223
Zframework/scene.lua
Normal file
223
Zframework/scene.lua
Normal file
@@ -0,0 +1,223 @@
|
||||
local scenes={}
|
||||
|
||||
local SCN={
|
||||
mainTouchID=nil, -- First touching ID(userdata)
|
||||
swapping=false, -- If Swapping
|
||||
state={
|
||||
tar=false, -- Swapping target
|
||||
style=false, -- Swapping style
|
||||
changeTime=false,-- Loading point
|
||||
time=false, -- Full swap time
|
||||
draw=false, -- Swap draw func
|
||||
},
|
||||
stack={},-- Scene stack
|
||||
prev=false,
|
||||
cur=false,
|
||||
args={},-- Arguments from previous scene
|
||||
|
||||
scenes=scenes,
|
||||
|
||||
-- Events
|
||||
update=false,
|
||||
draw=false,
|
||||
mouseClick=false,
|
||||
touchClick=false,
|
||||
mouseDown=false,
|
||||
mouseMove=false,
|
||||
mouseUp=false,
|
||||
wheelMoved=false,
|
||||
touchDown=false,
|
||||
touchUp=false,
|
||||
touchMove=false,
|
||||
keyDown=false,
|
||||
keyUp=false,
|
||||
gamepadDown=false,
|
||||
gamepadUp=false,
|
||||
fileDropped=false,
|
||||
directoryDropped=false,
|
||||
resize=false,
|
||||
}-- Scene datas, returned
|
||||
|
||||
function SCN.add(name,scene)
|
||||
scenes[name]=scene
|
||||
if scene.widgetList then
|
||||
setmetatable(scene.widgetList,WIDGET.indexMeta)
|
||||
end
|
||||
end
|
||||
|
||||
function SCN.swapUpdate(dt)
|
||||
local S=SCN.state
|
||||
S.time=S.time-dt
|
||||
if S.time<S.changeTime and S.time+dt>=S.changeTime then
|
||||
-- Scene swapped this frame
|
||||
SCN.stack[#SCN.stack]=S.tar
|
||||
SCN.cur=S.tar
|
||||
SCN.init(S.tar)
|
||||
SCN.mainTouchID=nil
|
||||
end
|
||||
if S.time<0 then
|
||||
SCN.swapping=false
|
||||
end
|
||||
end
|
||||
function SCN.init(s)
|
||||
love.keyboard.setTextInput(false)
|
||||
|
||||
local S=scenes[s]
|
||||
|
||||
WIDGET.setScrollHeight(S.widgetScrollHeight)
|
||||
WIDGET.setWidgetList(S.widgetList)
|
||||
SCN.enter=S.enter
|
||||
SCN.leave=S.leave
|
||||
SCN.mouseDown=S.mouseDown
|
||||
SCN.mouseMove=S.mouseMove
|
||||
SCN.mouseUp=S.mouseUp
|
||||
SCN.mouseClick=S.mouseClick
|
||||
SCN.wheelMoved=S.wheelMoved
|
||||
SCN.touchDown=S.touchDown
|
||||
SCN.touchUp=S.touchUp
|
||||
SCN.touchMove=S.touchMove
|
||||
SCN.touchClick=S.touchClick
|
||||
SCN.keyDown=S.keyDown
|
||||
SCN.keyUp=S.keyUp
|
||||
SCN.gamepadDown=S.gamepadDown
|
||||
SCN.gamepadUp=S.gamepadUp
|
||||
SCN.fileDropped=S.fileDropped
|
||||
SCN.directoryDropped=S.directoryDropped
|
||||
SCN.resize=S.resize
|
||||
SCN.update=S.update
|
||||
SCN.draw=S.draw
|
||||
if S.enter then
|
||||
S.enter()
|
||||
end
|
||||
end
|
||||
function SCN.push(tar)
|
||||
table.insert(SCN.stack,tar or SCN.stack[#SCN.stack])
|
||||
end
|
||||
function SCN.pop()
|
||||
table.remove(SCN.stack)
|
||||
end
|
||||
|
||||
local swap={
|
||||
none={
|
||||
duration=0,changeTime=0,
|
||||
draw=function() end
|
||||
},
|
||||
flash={
|
||||
duration=.16,changeTime=.08,
|
||||
draw=function() GC.clear(1,1,1) end
|
||||
},
|
||||
fade={
|
||||
duration=.5,changeTime=.25,
|
||||
draw=function(t)
|
||||
t=t>.25 and 2-t*4 or t*4
|
||||
GC.setColor(0,0,0,t)
|
||||
GC.rectangle('fill',0,0,SCR.w,SCR.h)
|
||||
end
|
||||
},
|
||||
fade_togame={
|
||||
duration=2,changeTime=.5,
|
||||
draw=function(t)
|
||||
t=t>.5 and (2-t)/1.5 or t*.5
|
||||
GC.setColor(0,0,0,t)
|
||||
GC.rectangle('fill',0,0,SCR.w,SCR.h)
|
||||
end
|
||||
},
|
||||
slowFade={
|
||||
duration=3,changeTime=1.5,
|
||||
draw=function(t)
|
||||
t=t>1.5 and (3-t)/1.5 or t/1.5
|
||||
GC.setColor(0,0,0,t)
|
||||
GC.rectangle('fill',0,0,SCR.w,SCR.h)
|
||||
end
|
||||
},
|
||||
swipeL={
|
||||
duration=.5,changeTime=.25,
|
||||
draw=function(t)
|
||||
t=t*2
|
||||
GC.setColor(.1,.1,.1,1-math.abs(t-.5))
|
||||
t=t*t*(3-2*t)*2-1
|
||||
GC.rectangle('fill',t*SCR.w,0,SCR.w,SCR.h)
|
||||
end
|
||||
},
|
||||
swipeR={
|
||||
duration=.5,changeTime=.25,
|
||||
draw=function(t)
|
||||
t=t*2
|
||||
GC.setColor(.1,.1,.1,1-math.abs(t-.5))
|
||||
t=t*t*(2*t-3)*2+1
|
||||
GC.rectangle('fill',t*SCR.w,0,SCR.w,SCR.h)
|
||||
end
|
||||
},
|
||||
swipeD={
|
||||
duration=.5,changeTime=.25,
|
||||
draw=function(t)
|
||||
t=t*2
|
||||
GC.setColor(.1,.1,.1,1-math.abs(t-.5))
|
||||
t=t*t*(2*t-3)*2+1
|
||||
GC.rectangle('fill',0,t*SCR.h,SCR.w,SCR.h)
|
||||
end
|
||||
},
|
||||
}-- Scene swapping animations
|
||||
function SCN.swapTo(tar,style,...)-- Parallel scene swapping, cannot back
|
||||
if scenes[tar] then
|
||||
if not SCN.swapping then
|
||||
SCN.prev=SCN.stack[#SCN.stack]
|
||||
|
||||
style=style or 'fade'
|
||||
SCN.swapping=true
|
||||
SCN.args={...}
|
||||
local S=SCN.state
|
||||
S.tar,S.style=tar,style
|
||||
S.time=swap[style].duration
|
||||
S.changeTime=swap[style].changeTime
|
||||
S.draw=swap[style].draw
|
||||
end
|
||||
else
|
||||
MES.new('warn',"No Scene: "..tostring(tar))
|
||||
end
|
||||
end
|
||||
function SCN.go(tar,style,...)-- Normal scene swapping, can back
|
||||
if scenes[tar] then
|
||||
if not SCN.swapping then
|
||||
SCN.push(SCN.stack[#SCN.stack] or '_')
|
||||
SCN.swapTo(tar,style,...)
|
||||
end
|
||||
else
|
||||
MES.new('warn',"No Scene: "..tar)
|
||||
end
|
||||
end
|
||||
function SCN.back(style,...)
|
||||
if SCN.swapping then return end
|
||||
|
||||
-- Leave scene
|
||||
if SCN.leave then
|
||||
SCN.leave()
|
||||
end
|
||||
|
||||
-- Poll&Back to previous Scene
|
||||
if #SCN.stack>1 then
|
||||
SCN.pop()
|
||||
SCN.swapTo(SCN.stack[#SCN.stack],style,...)
|
||||
else
|
||||
SCN.swapTo('quit','slowFade')
|
||||
end
|
||||
end
|
||||
function SCN.backTo(tar,style,...)
|
||||
if SCN.swapping then return end
|
||||
|
||||
-- Leave scene
|
||||
if SCN.leave then
|
||||
SCN.leave()
|
||||
end
|
||||
|
||||
-- Poll&Back to previous Scene
|
||||
while SCN.stack[#SCN.stack]~=tar and #SCN.stack>1 do
|
||||
SCN.pop()
|
||||
end
|
||||
SCN.swapTo(SCN.stack[#SCN.stack],style,...)
|
||||
end
|
||||
function SCN.printStack()
|
||||
for i=0,#SCN.stack+1 do print(SCN.stack[i] or "-------") end
|
||||
end
|
||||
|
||||
return SCN
|
||||
73
Zframework/screen.lua
Normal file
73
Zframework/screen.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
local SCR={
|
||||
w0=1280,h0=720, -- Default Screen Size
|
||||
x=0,y=0, -- Up-left Coord on screen
|
||||
cx=0,cy=0, -- Center Coord on screen (Center X/Y)
|
||||
ex=0,ey=0, -- Down-right Coord on screen (End X/Y)
|
||||
w=0,h=0, -- Fullscreen w/h for graphic functions
|
||||
W=0,H=0, -- Fullscreen w/h for shader
|
||||
safeX=0,safeY=0,-- Safe area
|
||||
safeW=0,safeH=0,-- Safe area
|
||||
rad=0, -- Radius
|
||||
k=1, -- Scale size
|
||||
dpi=1, -- DPI from gc.getDPIScale()
|
||||
|
||||
-- Screen transformation objects
|
||||
origin=love.math.newTransform(),
|
||||
xOy=love.math.newTransform(),
|
||||
xOy_m=love.math.newTransform(),
|
||||
xOy_ul=love.math.newTransform(),
|
||||
xOy_u=love.math.newTransform(),
|
||||
xOy_ur=love.math.newTransform(),
|
||||
xOy_l=love.math.newTransform(),
|
||||
xOy_r=love.math.newTransform(),
|
||||
xOy_dl=love.math.newTransform(),
|
||||
xOy_d=love.math.newTransform(),
|
||||
xOy_dr=love.math.newTransform(),
|
||||
}
|
||||
function SCR.setSize(w,h)
|
||||
SCR.w0,SCR.h0=w,h
|
||||
end
|
||||
function SCR.resize(w,h)
|
||||
SCR.w,SCR.h,SCR.dpi=w,h,love.graphics.getDPIScale()
|
||||
SCR.W,SCR.H=SCR.w*SCR.dpi,SCR.h*SCR.dpi
|
||||
SCR.r=h/w
|
||||
SCR.rad=(w^2+h^2)^.5
|
||||
|
||||
SCR.x,SCR.y=0,0
|
||||
if SCR.r>=SCR.h0/SCR.w0 then
|
||||
SCR.k=w/SCR.w0
|
||||
SCR.y=(h-SCR.h0*SCR.k)/2
|
||||
else
|
||||
SCR.k=h/SCR.h0
|
||||
SCR.x=(w-SCR.w0*SCR.k)/2
|
||||
end
|
||||
SCR.cx,SCR.cy=SCR.w/2,SCR.h/2
|
||||
SCR.ex,SCR.ey=SCR.w-SCR.x,SCR.h-SCR.y
|
||||
SCR.safeX,SCR.safeY,SCR.safeW,SCR.safeH=love.window.getSafeArea()
|
||||
|
||||
SCR.origin:setTransformation(0,0)
|
||||
SCR.xOy:setTransformation(SCR.x,SCR.y,0,SCR.k)
|
||||
SCR.xOy_m:setTransformation(w/2,h/2,0,SCR.k)
|
||||
SCR.xOy_ul:setTransformation(0,0,0,SCR.k)
|
||||
SCR.xOy_u:setTransformation(w/2,0,0,SCR.k)
|
||||
SCR.xOy_ur:setTransformation(w,0,0,SCR.k)
|
||||
SCR.xOy_l:setTransformation(0,h/2,0,SCR.k)
|
||||
SCR.xOy_r:setTransformation(w,h/2,0,SCR.k)
|
||||
SCR.xOy_dl:setTransformation(0,h,0,SCR.k)
|
||||
SCR.xOy_d:setTransformation(w/2,h,0,SCR.k)
|
||||
SCR.xOy_dr:setTransformation(w,h,0,SCR.k)
|
||||
end
|
||||
function SCR.info()
|
||||
return {
|
||||
("w0,h0 : %d, %d"):format(SCR.w0,SCR.h0),
|
||||
("x,y : %d, %d"):format(SCR.x,SCR.y),
|
||||
("cx,cy : %d, %d"):format(SCR.cx,SCR.cy),
|
||||
("ex,ey : %d, %d"):format(SCR.ex,SCR.ey),
|
||||
("w,h : %d, %d"):format(SCR.w,SCR.h),
|
||||
("W,H : %d, %d"):format(SCR.W,SCR.H),
|
||||
("safeX,safeY : %d, %d"):format(SCR.safeX,SCR.safeY),
|
||||
("safeW,safeH : %d, %d"):format(SCR.safeW,SCR.safeH),
|
||||
("k,dpi,rad : %.2f, %d, %.2f"):format(SCR.k,SCR.dpi,SCR.rad),
|
||||
}
|
||||
end
|
||||
return SCR
|
||||
169
Zframework/sfx.lua
Normal file
169
Zframework/sfx.lua
Normal file
@@ -0,0 +1,169 @@
|
||||
local type,rem=type,table.remove
|
||||
local floor,rnd=math.floor,math.random
|
||||
|
||||
local sfxList={}
|
||||
local packSetting={}
|
||||
local Sources={}
|
||||
local volume=1
|
||||
local stereo=1
|
||||
|
||||
local noteVal={
|
||||
C=1,c=1,
|
||||
D=3,d=3,
|
||||
E=5,e=5,
|
||||
F=6,f=6,
|
||||
G=8,g=8,
|
||||
A=10,a=10,
|
||||
B=12,b=12,
|
||||
}
|
||||
local noteName={'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'}
|
||||
local function _getTuneHeight(tune)
|
||||
local octave=tonumber(tune:sub(-1,-1))
|
||||
if octave then
|
||||
local tuneHeight=noteVal[tune:sub(1,1)]
|
||||
if tuneHeight then
|
||||
tuneHeight=tuneHeight+(octave-1)*12
|
||||
local s=tune:sub(2,2)
|
||||
if s=='s' or s=='#' then
|
||||
tuneHeight=tuneHeight+1
|
||||
elseif s=='f' or s=='b' then
|
||||
tuneHeight=tuneHeight-1
|
||||
end
|
||||
return tuneHeight
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local SFX={}
|
||||
|
||||
function SFX.init(list)
|
||||
assert(type(list)=='table',"Initialize SFX lib with a list of filenames!")
|
||||
for i=1,#list do table.insert(sfxList,list[i]) end
|
||||
end
|
||||
function SFX.load(path)
|
||||
local c=0
|
||||
local missing=0
|
||||
for i=1,#sfxList do
|
||||
local fullPath=path..sfxList[i]..'.ogg'
|
||||
if love.filesystem.getInfo(fullPath) then
|
||||
if Sources[sfxList[i]] then
|
||||
for j=1,#Sources[sfxList[i]] do
|
||||
Sources[sfxList[i]][j]:release()
|
||||
end
|
||||
end
|
||||
Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')}
|
||||
c=c+1
|
||||
else
|
||||
LOG("No SFX: "..sfxList[i]..'.ogg',.1)
|
||||
missing=missing+1
|
||||
end
|
||||
end
|
||||
LOG(c.."/"..#sfxList.." SFX files loaded")
|
||||
LOG(missing.." SFX files missing")
|
||||
if missing>0 then
|
||||
MES.new('info',missing.." SFX files missing")
|
||||
end
|
||||
collectgarbage()
|
||||
end
|
||||
function SFX.loadSample(pack)
|
||||
assert(type(pack)=='table',"Usage: SFX.loadsample([table])")
|
||||
assert(pack.name,"No field: name")
|
||||
assert(pack.path,"No field: path")
|
||||
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
|
||||
|
||||
function SFX.getCount()
|
||||
return #sfxList
|
||||
end
|
||||
function SFX.setVol(v)
|
||||
assert(type(v)=='number' and v>=0 and v<=1,'Wrong volume')
|
||||
volume=v
|
||||
end
|
||||
function SFX.setStereo(v)
|
||||
assert(type(v)=='number' and v>=0 and v<=1,'Wrong stereo')
|
||||
stereo=v
|
||||
end
|
||||
|
||||
function SFX.getNoteName(note)
|
||||
if note<1 then
|
||||
return '---'
|
||||
else
|
||||
note=note-1
|
||||
local octave=floor(note/12)+1
|
||||
return noteName[note%12+1]..octave
|
||||
end
|
||||
end
|
||||
function SFX.playSample(pack,...)-- vol-1, sampSet1, vol-2, sampSet2
|
||||
if ... then
|
||||
local arg={...}
|
||||
local vol
|
||||
for i=1,#arg do
|
||||
local a=arg[i]
|
||||
if type(a)=='number' and a<=1 then
|
||||
vol=a
|
||||
else
|
||||
local base=packSetting[pack].base
|
||||
local top=packSetting[pack].top
|
||||
local tune=type(a)=='string' and _getTuneHeight(a) or a-- Absolute tune in number
|
||||
local playTune=tune+rnd(-2,2)
|
||||
if playTune<=base then-- Too low notes
|
||||
playTune=base+1
|
||||
elseif playTune>top then-- Too high notes
|
||||
playTune=top
|
||||
end
|
||||
SFX.play(pack..playTune-base,vol,nil,tune-playTune)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local function _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
|
||||
local n=1
|
||||
while S[n]:isPlaying() do
|
||||
n=n+1
|
||||
if not S[n] then
|
||||
S[n]=S[1]:clone()
|
||||
S[n]:seek(0)
|
||||
break
|
||||
end
|
||||
end
|
||||
S=S[n]-- AU_SRC
|
||||
if S:getChannelCount()==1 then
|
||||
if pos then
|
||||
pos=MATH.clamp(pos,-1,1)*stereo
|
||||
S:setPosition(pos,1-pos^2,0)
|
||||
else
|
||||
S:setPosition(0,0,0)
|
||||
end
|
||||
end
|
||||
S:setVolume(vol^1.626)
|
||||
S:setPitch(pitch and 1.0594630943592953^pitch or 1)
|
||||
S:play()
|
||||
end
|
||||
SFX.fplay=_play-- Play sounds without apply module's volume setting
|
||||
function SFX.play(name,vol,pos,pitch)
|
||||
_play(name,(vol or 1)*volume,pos,pitch)
|
||||
end
|
||||
function SFX.reset()
|
||||
for _,L in next,Sources do
|
||||
if type(L)=='table' then
|
||||
for i=#L,1,-1 do
|
||||
if not L[i]:isPlaying() then
|
||||
rem(L,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return SFX
|
||||
5675
Zframework/sha2.lua
Normal file
5675
Zframework/sha2.lua
Normal file
File diff suppressed because it is too large
Load Diff
428
Zframework/stringExtend.lua
Normal file
428
Zframework/stringExtend.lua
Normal file
@@ -0,0 +1,428 @@
|
||||
local data=love.data
|
||||
local STRING={}
|
||||
local assert,tostring,tonumber=assert,tostring,tonumber
|
||||
local floorint,format=math.floor,string.format
|
||||
local find,sub,gsub=string.find,string.sub,string.gsub
|
||||
local rep,upper=string.rep,string.upper
|
||||
local char,byte=string.char,string.byte
|
||||
|
||||
-- "Replace dollars", replace all $n with ...
|
||||
function STRING.repD(str,...)
|
||||
local l={...}
|
||||
for i=#l,1,-1 do
|
||||
str=gsub(str,'$'..i,l[i])
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
-- "Scan arg", scan if str has the arg (format of str is like "-json -q", arg is like "-q")
|
||||
function STRING.sArg(str,switch)
|
||||
if find(str.." ",switch.." ") then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
do-- function STRING.shiftChar(c)
|
||||
local shiftMap={
|
||||
['1']='!',['2']='@',['3']='#',['4']='$',['5']='%',
|
||||
['6']='^',['7']='&',['8']='*',['9']='(',['0']=')',
|
||||
['`']='~',['-']='_',['=']='+',
|
||||
['[']='{',[']']='}',['\\']='|',
|
||||
[';']=':',['\'']='"',
|
||||
[',']='<',['.']='>',['/']='?',
|
||||
}
|
||||
function STRING.shiftChar(c)
|
||||
return shiftMap[c] or upper(c)
|
||||
end
|
||||
end
|
||||
|
||||
-- [LOW PERFORMANCE!]
|
||||
local upperData,lowerData,diaData
|
||||
function STRING.upperUTF8(str)
|
||||
for _,pair in next,upperData do
|
||||
str=str:gsub(pair[1],pair[2])
|
||||
end
|
||||
return str
|
||||
end
|
||||
function STRING.lowerUTF8(str)
|
||||
for _,pair in next,lowerData do
|
||||
str=str:gsub(pair[1],pair[2])
|
||||
end
|
||||
return str
|
||||
end
|
||||
function STRING.remDiacritics(str)
|
||||
for _,pair in next,diaData do
|
||||
str=str:gsub(pair[1],pair[2])
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
function STRING.trim(s)
|
||||
if not s:find("%S") then return "" end
|
||||
s=s:sub((s:find("%S"))):reverse()
|
||||
return s:sub((s:find("%S"))):reverse()
|
||||
end
|
||||
|
||||
function STRING.split(s,sep,regex)
|
||||
local L={}
|
||||
local p1,p2=1-- start,target
|
||||
if regex then
|
||||
while p1<=#s do
|
||||
p2=find(s,sep,p1) or #s+1
|
||||
L[#L+1]=sub(s,p1,p2-1)
|
||||
p1=p2+#sep
|
||||
end
|
||||
else
|
||||
while p1<=#s do
|
||||
p2=find(s,sep,p1,true) or #s+1
|
||||
L[#L+1]=sub(s,p1,p2-1)
|
||||
p1=p2+#sep
|
||||
end
|
||||
end
|
||||
return L
|
||||
end
|
||||
|
||||
function STRING.simpEmailCheck(e)
|
||||
e=STRING.split(e,"@")
|
||||
if #e~=2 then return false end
|
||||
if e[1]:sub(-1)=="." or e[2]:sub(-1)=="." then return false end
|
||||
local e1,e2=STRING.split(e[1],"."),STRING.split(e[2],".")
|
||||
if #e1*#e2==0 then return false end
|
||||
for _,v in next,e1 do if #v==0 then return false end end
|
||||
for _,v in next,e2 do if #v==0 then return false end end
|
||||
return true
|
||||
end
|
||||
|
||||
local MINUTE=60
|
||||
local HOUR=3600
|
||||
local DAY=86400
|
||||
local YEAR=31536000 -- 365 days
|
||||
local function convertSecondsToUnits(t) -- convert seconds to {seconds, minutes, hours, days, years}
|
||||
local years=floorint(t/YEAR)
|
||||
local remainder=t%YEAR
|
||||
|
||||
local days=floorint(remainder/DAY)
|
||||
remainder=remainder%DAY
|
||||
|
||||
local hours=floorint(remainder/HOUR)
|
||||
remainder=remainder%HOUR
|
||||
|
||||
local minutes=floorint(remainder/MINUTE)
|
||||
local seconds=remainder%MINUTE
|
||||
return seconds,minutes,hours,days,years
|
||||
end
|
||||
|
||||
-- MM:SS
|
||||
function STRING.time_simp(t)
|
||||
return format("%02d:%02d",floorint(t/MINUTE),floorint(t%MINUTE))
|
||||
end
|
||||
|
||||
local timeLetters={' y',' d',' h',' m',' s',' ms'}
|
||||
-- Display 2 largest units of time.
|
||||
function STRING.time_short(t)
|
||||
-- Early returns to prevent nil values
|
||||
if t<0 then return '-'..STRING.time_short(-t) end -- negative time
|
||||
if t<1 then return math.floor(t*1000)..timeLetters[6] end -- 123 ms
|
||||
if t<MINUTE then return math.floor(t)..timeLetters[5]..' '..math.floor((t%1)*1000)..timeLetters[6] end -- 12s 345ms
|
||||
|
||||
local timeUnits=TABLE.reverse({convertSecondsToUnits(t)})
|
||||
|
||||
-- floor seconds
|
||||
timeUnits[#timeUnits]=floorint(timeUnits[#timeUnits])
|
||||
|
||||
local outputStr=''
|
||||
for i=1,#timeUnits do
|
||||
if timeUnits>0 then
|
||||
return timeUnits[i]..timeLetters[i]..' '..timeUnits[i+1]..timeLetters[i+1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function STRING.time(t)
|
||||
local s,m,h,d,y=convertSecondsToUnits(t)
|
||||
if t<MINUTE then
|
||||
return format("%.3f″",t) -- example: 12.345″
|
||||
elseif t<HOUR then
|
||||
return format("%d′%05.2f″",m,s) -- 1′23.45″
|
||||
elseif t<DAY then
|
||||
return format("%d:%.2d′%04.1f″",h,m,s) -- 12:34′56.7″
|
||||
elseif t<YEAR then
|
||||
return format("%dd %d:%.2d′%.2d″",d,h,m,s) -- 123d 12:34′56″
|
||||
else
|
||||
return format("%dy %dd %d:%.2d′",y,d,h,m) -- 1y 234d 12:34′
|
||||
end
|
||||
end
|
||||
|
||||
function STRING.time_ext(t)
|
||||
local s,m,h,d,y=convertSecondsToUnits(t)
|
||||
if t<MINUTE then
|
||||
return format("%.5f″",t) -- 12.34567″
|
||||
elseif t<HOUR then
|
||||
return format("%d′%06.3f″",m,s) -- 1′23.456″
|
||||
elseif t<DAY then
|
||||
return format("%d:%.2d′%05.2f″",h,m,s) -- 12:34′56.78″
|
||||
elseif t<YEAR then
|
||||
return format("%dd %d:%.2d′%04.1f″",d,h,m,s) -- 123d 12:34′56.7″
|
||||
else
|
||||
return format("%dy %dd %d:%.2d′%.2d″",y,d,h,m,s) -- 1y 234d 12:34′56″
|
||||
end
|
||||
end
|
||||
|
||||
function STRING.UTF8(n)-- Simple utf8 coding
|
||||
assert(type(n)=='number',"Wrong type ("..type(n)..")")
|
||||
assert(n>=0 and n<2^31,"Out of range ("..n..")")
|
||||
if n<2^7 then return char(n)
|
||||
elseif n<2^11 then return char(192+floorint(n/2^06),128+n%2^6)
|
||||
elseif n<2^16 then return char(224+floorint(n/2^12),128+floorint(n/2^06)%2^6,128+n%2^6)
|
||||
elseif n<2^21 then return char(240+floorint(n/2^18),128+floorint(n/2^12)%2^6,128+floorint(n/2^06)%2^6,128+n%2^6)
|
||||
elseif n<2^26 then return char(248+floorint(n/2^24),128+floorint(n/2^18)%2^6,128+floorint(n/2^12)%2^6,128+floorint(n/2^06)%2^6,128+n%2^6)
|
||||
elseif n<2^31 then return char(252+floorint(n/2^30),128+floorint(n/2^24)%2^6,128+floorint(n/2^18)%2^6,128+floorint(n/2^12)%2^6,128+floorint(n/2^06)%2^6,128+n%2^6)
|
||||
end
|
||||
end
|
||||
|
||||
do-- functions to shorted big numbers
|
||||
local lg=math.log10
|
||||
local units={"","K","M","B","T","Qa","Qt","Sx","Sp","Oc","No"}
|
||||
local preUnits={"","U","D","T","Qa","Qt","Sx","Sp","O","N"}
|
||||
local secUnits={"Dc","Vg","Tg","Qd","Qi","Se","St","Og","Nn","Ce"}-- Ce is next-level unit, but DcCe is not used so used here
|
||||
for _,preU in next,preUnits do for _,secU in next,secUnits do table.insert(units,preU..secU) end end
|
||||
function STRING.bigInt(t)
|
||||
if t<1000 then
|
||||
return tostring(t)
|
||||
elseif t~=1e999 then
|
||||
local e=floorint(lg(t)/3)
|
||||
return(t/10^(e*3))..units[e+1]
|
||||
else
|
||||
return "INF"
|
||||
end
|
||||
end
|
||||
|
||||
local MIN_SI=-30 -- current lowest order of magnitude for SI units (quecto-; 10^-30)
|
||||
local MAX_SI=30 -- current highest order of magnitude for SI units (quetta-; 10^30)
|
||||
local SI_SHORT={
|
||||
[-30]='q',[-27]='r',[-24]='y',[-21]='z',[-18]='a',[-15]='f',[-12]='p',
|
||||
[-9]='n',[-6]='μ',[-3]='m',[0]='',[3]='k',[6]='M',[9]='G',
|
||||
[12]='T',[15]='P',[18]='E',[21]='Z',[24]='Y',[27]='R',[30]='Q'
|
||||
}
|
||||
local SI_LONG={
|
||||
[-30]='quecto',[-27]='ronto',[-24]='yocto',[-21]='zepto',[-18]='atto',[-15]='femto',[-12]='pico',
|
||||
[-9]='nano',[-6]='micro',[-3]='milli',[0]='',[3]='kilo',[6]='mega',[9]='giga',
|
||||
[12]='tera',[15]='peta',[18]='exa',[21]='zetta',[24]='yotta',[27]='ronna',[30]='quetta'
|
||||
}
|
||||
--[[
|
||||
Converts a number into SI notation with letter prefixes.
|
||||
NOTE: Only power-of-thousand prefixes; no deci-/centi-.
|
||||
Arguments:
|
||||
- num: The number to be converted to SI notation.
|
||||
- unit: [optional] The unit to be concatenated at the end.
|
||||
Example: STRING.SI(10^-9,"m") --> "1 nm"
|
||||
]]
|
||||
function STRING.SI(num, unit)
|
||||
unit=unit or ''
|
||||
local order=MATH.clamp(3*math.floor(math.log10(num)/3),MIN_SI,MAX_SI)
|
||||
local prefix=SI_SHORT[order]
|
||||
local scaledNum=num/10^order
|
||||
local formattedNum=string.format('%.3f', scaledNum):gsub('%.?0+$','')
|
||||
return formattedNum.." "..prefix..unit
|
||||
end
|
||||
|
||||
--[[
|
||||
Converts a number into SI notation with word prefixes.
|
||||
NOTE: Only power-of-thousand prefixes; no deci-/centi-.
|
||||
Arguments:
|
||||
- num: The number to be converted to SI notation.
|
||||
- unit: [optional] The unit to be concatenated at the end.
|
||||
Example: STRING.SI(10^9,"hertz") --> "1 megahertz"
|
||||
]]
|
||||
function STRING.SILong(num, unit)
|
||||
unit=unit or ''
|
||||
local order=MATH.clamp(3*math.floor(math.log10(num)/3),MIN_SI,MAX_SI)
|
||||
local prefix=SI_LONG[order]
|
||||
local scaledNum=num/10^order
|
||||
local formattedNum=string.format('%.3f', scaledNum):gsub('%.?0+$','')
|
||||
return formattedNum.." "..prefix..unit
|
||||
end
|
||||
end
|
||||
|
||||
do-- function STRING.toBin, STRING.toOct, STRING.toHex(n,len)
|
||||
function STRING.toBin(n,len)
|
||||
local s=""
|
||||
while n>0 do
|
||||
s=(n%2)..s
|
||||
n=floorint(n/2)
|
||||
end
|
||||
if len then
|
||||
return rep("0",len-#s)..s
|
||||
else
|
||||
return s
|
||||
end
|
||||
end
|
||||
function STRING.toOct(n,len)
|
||||
local s=""
|
||||
while n>0 do
|
||||
s=(n%8)..s
|
||||
n=floorint(n/8)
|
||||
end
|
||||
if len then
|
||||
return rep("0",len-#s)..s
|
||||
else
|
||||
return s
|
||||
end
|
||||
end
|
||||
local b16={[0]='0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}
|
||||
function STRING.toHex(n,len)
|
||||
local s=""
|
||||
while n>0 do
|
||||
s=b16[n%16]..s
|
||||
n=floorint(n/16)
|
||||
end
|
||||
if len then
|
||||
return rep("0",len-#s)..s
|
||||
else
|
||||
return s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function STRING.hexColor(str)--[LOW PERFORMENCE]
|
||||
assert(type(str)=='string')
|
||||
if str:sub(1,1)=="#" then str=str:sub(2) end
|
||||
assert(#str<=8)
|
||||
local r=(tonumber(str:sub(1,2),16) or 0)/255
|
||||
local g=(tonumber(str:sub(3,4),16) or 0)/255
|
||||
local b=(tonumber(str:sub(5,6),16) or 0)/255
|
||||
local a=(tonumber(str:sub(7,8),16) or 255)/255
|
||||
return r,g,b,a
|
||||
end
|
||||
|
||||
do-- function STRING.urlEncode(s)
|
||||
local rshift=bit.rshift
|
||||
local b16={[0]='0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}
|
||||
function STRING.urlEncode(s)
|
||||
local out=""
|
||||
for i=1,#s do
|
||||
if s:sub(i,i):match("[a-zA-Z0-9]") then
|
||||
out=out..s:sub(i,i)
|
||||
else
|
||||
local b=s:byte(i)
|
||||
out=out.."%"..b16[rshift(b,4)]..b16[b%16]
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
end
|
||||
|
||||
function STRING.vcsEncrypt(text,key)
|
||||
local keyLen=#key
|
||||
local result=""
|
||||
local buffer=""
|
||||
for i=0,#text-1 do
|
||||
buffer=buffer..char((byte(text,i+1)-32+byte(key,i%keyLen+1))%95+32)
|
||||
if #buffer==26 then
|
||||
result=result..buffer
|
||||
buffer=""
|
||||
end
|
||||
end
|
||||
return result..buffer
|
||||
end
|
||||
function STRING.vcsDecrypt(text,key)
|
||||
local keyLen=#key
|
||||
local result=""
|
||||
local buffer=""
|
||||
for i=0,#text-1 do
|
||||
buffer=buffer..char((byte(text,i+1)-32-byte(key,i%keyLen+1))%95+32)
|
||||
if #buffer==26 then
|
||||
result=result..buffer
|
||||
buffer=""
|
||||
end
|
||||
end
|
||||
return result..buffer
|
||||
end
|
||||
function STRING.digezt(text)-- Not powerful hash, just protect the original text
|
||||
local out={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
||||
local seed=26
|
||||
for i=1,#text do
|
||||
local c=byte(text,i)
|
||||
seed=(seed+c)%26
|
||||
c=c+seed
|
||||
local pos=c*i%16
|
||||
local step=(c+i)%4+1
|
||||
local times=2+(c%6)
|
||||
for _=1,times do
|
||||
out[pos+1]=(out[pos+1]+c)%256
|
||||
pos=(pos+step)%16
|
||||
end
|
||||
end
|
||||
local result=""
|
||||
for i=1,16 do result=result..char(out[i]) end
|
||||
return result
|
||||
end
|
||||
|
||||
function STRING.readLine(str)
|
||||
local p=str:find("\n")
|
||||
if p then
|
||||
return str:sub(1,p-1),str:sub(p+1)
|
||||
else
|
||||
return str,""
|
||||
end
|
||||
end
|
||||
function STRING.readChars(str,n)
|
||||
return sub(str,1,n),sub(str,n+1)
|
||||
end
|
||||
|
||||
function STRING.packBin(s)
|
||||
return data.encode('string','base64',data.compress('string','zlib',s))
|
||||
end
|
||||
function STRING.unpackBin(str)
|
||||
local res
|
||||
res,str=pcall(data.decode,'string','base64',str)
|
||||
if not res then return end
|
||||
res,str=pcall(data.decompress,'string','zlib',str)
|
||||
if res then return str end
|
||||
end
|
||||
function STRING.packText(s)
|
||||
return data.encode('string','base64',data.compress('string','gzip',s))
|
||||
end
|
||||
function STRING.unpackText(str)
|
||||
local res
|
||||
res,str=pcall(data.decode,'string','base64',str)
|
||||
if not res then return end
|
||||
res,str=pcall(data.decompress,'string','gzip',str)
|
||||
if res then return str end
|
||||
end
|
||||
function STRING.packTable(t)
|
||||
return STRING.packText(JSON.encode(t))
|
||||
end
|
||||
function STRING.unpackTable(t)
|
||||
return JSON.decode(STRING.unpackText(t))
|
||||
end
|
||||
|
||||
do
|
||||
local function parseFile(fname)
|
||||
local d
|
||||
if love and love.filesystem and type(love.filesystem.read)=='function' then
|
||||
d=love.filesystem.read(fname)
|
||||
else
|
||||
local f=io.open(fname,'r')
|
||||
if f then
|
||||
d=f:read('a')
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
if not d then
|
||||
print("ERROR: Failed to read the data from "..fname)
|
||||
return {}
|
||||
end
|
||||
d=STRING.split(gsub(d,'\n',','),',')
|
||||
for i=1,#d do
|
||||
d[i]=STRING.split(d[i],'=')
|
||||
end
|
||||
return d
|
||||
end
|
||||
upperData=parseFile('Zframework/upcaser.txt')
|
||||
lowerData=parseFile('Zframework/lowcaser.txt')
|
||||
diaData=parseFile('Zframework/diacritics.txt')
|
||||
end
|
||||
|
||||
return STRING
|
||||
205
Zframework/sysFX.lua
Normal file
205
Zframework/sysFX.lua
Normal file
@@ -0,0 +1,205 @@
|
||||
local gc=love.graphics
|
||||
local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth
|
||||
local gc_draw,gc_line=gc.draw,gc.line
|
||||
local gc_rectangle,gc_circle=gc.rectangle,gc.circle
|
||||
|
||||
local max,min=math.max,math.min
|
||||
local rnd=math.random
|
||||
local ins,rem=table.insert,table.remove
|
||||
|
||||
local fx={}
|
||||
|
||||
local function _normUpdate(S,dt)
|
||||
S.t=S.t+dt*S.rate
|
||||
return S.t>1
|
||||
end
|
||||
|
||||
local FXupdate={}
|
||||
function FXupdate.badge(S,dt)
|
||||
S.t=S.t+dt
|
||||
if S.t<.2 then
|
||||
S.x,S.y=S.x1-14,S.y1-14
|
||||
elseif S.t<.8 then
|
||||
local t=((S.t-.2)*1.6667)
|
||||
t=(3-2*t)*t*t
|
||||
S.x,S.y=S.x1*(1-t)+S.x2*t-14,S.y1*(1-t)+S.y2*t-14
|
||||
else
|
||||
S.x,S.y=S.x2-14,S.y2-14
|
||||
end
|
||||
return S.t>=1
|
||||
end
|
||||
FXupdate.attack=_normUpdate
|
||||
FXupdate.tap=_normUpdate
|
||||
FXupdate.ripple=_normUpdate
|
||||
FXupdate.rectRipple=_normUpdate
|
||||
FXupdate.shade=_normUpdate
|
||||
function FXupdate.cell(S,dt)
|
||||
if S.vx then
|
||||
S.x=S.x+S.vx*S.rate
|
||||
S.y=S.y+S.vy*S.rate
|
||||
if S.ax then
|
||||
S.vx=S.vx+S.ax*S.rate
|
||||
S.vy=S.vy+S.ay*S.rate
|
||||
end
|
||||
end
|
||||
S.t=S.t+dt*S.rate
|
||||
return S.t>1
|
||||
end
|
||||
FXupdate.line=_normUpdate
|
||||
|
||||
local FXdraw={}
|
||||
function FXdraw.badge(S)
|
||||
gc_setColor(1,1,1,S.t<.2 and S.t*.6 or S.t<.8 and 1 or (1-S.t)*.6)
|
||||
gc_draw(IMG.badgeIcon,S.x,S.y)
|
||||
end
|
||||
function FXdraw.attack(S)
|
||||
gc_setColor(S.r*2,S.g*2,S.b*2,S.a*min(4-S.t*4,1))
|
||||
|
||||
gc_setLineWidth(S.wid)
|
||||
local t1,t2=max(5*S.t-4,0),min(S.t*4,1)
|
||||
gc_line(
|
||||
S.x1*(1-t1)+S.x2*t1,
|
||||
S.y1*(1-t1)+S.y2*t1,
|
||||
S.x1*(1-t2)+S.x2*t2,
|
||||
S.y1*(1-t2)+S.y2*t2
|
||||
)
|
||||
|
||||
gc_setLineWidth(S.wid*.6)
|
||||
t1,t2=max(4*S.t-3,0),min(S.t*5,1)
|
||||
gc_line(
|
||||
S.x1*(1-t1)+S.x2*t1,
|
||||
S.y1*(1-t1)+S.y2*t1,
|
||||
S.x1*(1-t2)+S.x2*t2,
|
||||
S.y1*(1-t2)+S.y2*t2
|
||||
)
|
||||
end
|
||||
function FXdraw.tap(S)
|
||||
local t=S.t
|
||||
gc_setColor(1,1,1,(1-t)*.4)
|
||||
gc_circle('fill',S.x,S.y,30*(1-t)^.5)
|
||||
end
|
||||
function FXdraw.ripple(S)
|
||||
local t=S.t
|
||||
gc_setLineWidth(2)
|
||||
gc_setColor(1,1,1,1-t)
|
||||
gc_circle('line',S.x,S.y,t*(2-t)*S.r)
|
||||
end
|
||||
function FXdraw.rectRipple(S)
|
||||
gc_setLineWidth(6)
|
||||
gc_setColor(1,1,1,1-S.t)
|
||||
local r=(10*S.t)^1.2
|
||||
gc_rectangle('line',S.x-r,S.y-r,S.w+2*r,S.h+2*r)
|
||||
end
|
||||
function FXdraw.shade(S)
|
||||
gc_setColor(S.r,S.g,S.b,1-S.t)
|
||||
gc_rectangle('fill',S.x,S.y,S.w,S.h,2)
|
||||
end
|
||||
function FXdraw.cell(S)
|
||||
gc_setColor(1,1,1,1-S.t)
|
||||
gc_draw(S.image,S.x,S.y,nil,S.size,nil,S.cx,S.cy)
|
||||
end
|
||||
function FXdraw.line(S)
|
||||
gc_setColor(1,1,1,S.a*(1-S.t))
|
||||
gc_line(S.x1,S.y1,S.x2,S.y2)
|
||||
end
|
||||
|
||||
local SYSFX={}
|
||||
function SYSFX.update(dt)
|
||||
for i=#fx,1,-1 do
|
||||
if fx[i]:update(dt) then
|
||||
rem(fx,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
function SYSFX.draw()
|
||||
for i=1,#fx do
|
||||
fx[i]:draw()
|
||||
end
|
||||
end
|
||||
|
||||
function SYSFX.newBadge(x1,y1,x2,y2)
|
||||
ins(fx,{
|
||||
update=FXupdate.badge,
|
||||
draw=FXdraw.badge,
|
||||
t=0,
|
||||
x=x1,y=y1,
|
||||
x1=x1,y1=y1,
|
||||
x2=x2,y2=y2,
|
||||
})
|
||||
end
|
||||
function SYSFX.newAttack(rate,x1,y1,x2,y2,wid,r,g,b,a)
|
||||
ins(fx,{
|
||||
update=FXupdate.attack,
|
||||
draw=FXdraw.attack,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x1=x1,y1=y1,-- Start pos
|
||||
x2=x2,y2=y2,-- End pos
|
||||
wid=wid,-- Line width
|
||||
r=r,g=g,b=b,a=a,
|
||||
})
|
||||
end
|
||||
function SYSFX.newTap(rate,x,y)
|
||||
local T=
|
||||
{
|
||||
update=FXupdate.tap,
|
||||
draw=FXdraw.tap,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x=x,y=y,
|
||||
}
|
||||
ins(fx,T)
|
||||
end
|
||||
function SYSFX.newRipple(rate,x,y,r)
|
||||
ins(fx,{
|
||||
update=FXupdate.ripple,
|
||||
draw=FXdraw.ripple,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x=x,y=y,r=r,
|
||||
})
|
||||
end
|
||||
function SYSFX.newRectRipple(rate,x,y,w,h)
|
||||
ins(fx,{
|
||||
update=FXupdate.rectRipple,
|
||||
draw=FXdraw.rectRipple,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x=x,y=y,w=w,h=h,
|
||||
})
|
||||
end
|
||||
function SYSFX.newShade(rate,x,y,w,h,r,g,b)
|
||||
ins(fx,{
|
||||
update=FXupdate.shade,
|
||||
draw=FXdraw.shade,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x=x,y=y,w=w,h=h,
|
||||
r=r or 1,g=g or 1,b=b or 1,
|
||||
})
|
||||
end
|
||||
function SYSFX.newCell(rate,image,size,x,y,vx,vy,ax,ay)
|
||||
ins(fx,{
|
||||
update=FXupdate.cell,
|
||||
draw=FXdraw.cell,
|
||||
t=0,
|
||||
rate=rate*(.9+rnd()*.2),
|
||||
image=image,size=size,
|
||||
cx=image:getWidth()*.5,cy=image:getHeight()*.5,
|
||||
x=x,y=y,
|
||||
vx=vx,vy=vy,
|
||||
ax=ax,ay=ay,
|
||||
})
|
||||
end
|
||||
function SYSFX.newLine(rate,x1,y1,x2,y2,r,g,b,a)
|
||||
ins(fx,{
|
||||
update=FXupdate.line,
|
||||
draw=FXdraw.line,
|
||||
t=0,
|
||||
rate=rate,
|
||||
x1=x1 or 0,y1=y1 or 0,
|
||||
x2=x2 or x1 or 1280,y2=y2 or y1 or 720,
|
||||
r=r or 1,g=g or 1,b=b or 1,a=a or 1,
|
||||
})
|
||||
end
|
||||
return SYSFX
|
||||
463
Zframework/tableExtend.lua
Normal file
463
Zframework/tableExtend.lua
Normal file
@@ -0,0 +1,463 @@
|
||||
local rnd=math.random
|
||||
local min,max=math.min,math.max
|
||||
local find=string.find
|
||||
local ins,rem=table.insert,table.remove
|
||||
local next,type=next,type
|
||||
local TABLE={}
|
||||
|
||||
-----------------------[Making Tables]------------------------
|
||||
-- Get a new filled table
|
||||
function TABLE.new(val,count)
|
||||
local L={}
|
||||
for i=1,count do
|
||||
L[i]=val
|
||||
end
|
||||
return L
|
||||
end
|
||||
|
||||
-- Get a copy of [1~#] elements
|
||||
function TABLE.shift(org,depth)
|
||||
if not depth then depth=1e99 end
|
||||
local L={}
|
||||
for i=1,#org do
|
||||
if type(org[i])=='table' and depth>0 then
|
||||
L[i]=TABLE.shift(org[i],depth-1)
|
||||
else
|
||||
L[i]=org[i]
|
||||
end
|
||||
end
|
||||
return L
|
||||
end
|
||||
|
||||
-- Get a full copy of a table, depth=how many layers will be recreate, default to inf
|
||||
function TABLE.copy(org,depth)
|
||||
if not depth then depth=1e99 end
|
||||
local L={}
|
||||
for k,v in next,org do
|
||||
if type(v)=='table' and depth>0 then
|
||||
L[k]=TABLE.copy(v,depth-1)
|
||||
else
|
||||
L[k]=v
|
||||
end
|
||||
end
|
||||
return L
|
||||
end
|
||||
|
||||
-- Connect [1~#] elements of new to the end of org
|
||||
function TABLE.connect(org,new)
|
||||
local l0=#org
|
||||
for i=1,#new do
|
||||
org[l0+i]=new[i]
|
||||
end
|
||||
return org
|
||||
end
|
||||
|
||||
-- Get a table of two lists connected
|
||||
function TABLE.combine(L1,L2)
|
||||
local l={}
|
||||
local l0=#L1
|
||||
for i=1,l0 do l[i]=L1[i] end
|
||||
for i=1,#L2 do l[l0+i]=L2[i] end
|
||||
return l
|
||||
end
|
||||
|
||||
----------------------[Modifying Tables]----------------------
|
||||
|
||||
-- For all things in new, push to old
|
||||
function TABLE.cover(new,old)
|
||||
for k,v in next,new do
|
||||
old[k]=v
|
||||
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 org, delete them if it's in sub
|
||||
function TABLE.subtract(org,sub)
|
||||
for _,v in next,sub do
|
||||
while true do
|
||||
local p=TABLE.search(org,v)
|
||||
if p then
|
||||
rem(org,p)
|
||||
else
|
||||
break
|
||||
end
|
||||
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
|
||||
if type(v)==type(old[k]) then
|
||||
if type(v)=='table' then
|
||||
TABLE.update(v,old[k])
|
||||
else
|
||||
old[k]=v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- For all things in new if no val in old, push to old
|
||||
function TABLE.complete(new,old)
|
||||
for k,v in next,new do
|
||||
if type(v)=='table' then
|
||||
if old[k]==nil then old[k]={} end
|
||||
TABLE.complete(v,old[k])
|
||||
elseif old[k]==nil then
|
||||
old[k]=v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------[Removing Table Values]--------------------
|
||||
|
||||
-- Pop & return random [1~#] of table
|
||||
function TABLE.popRandom(t)
|
||||
local l=#t
|
||||
if l>0 then
|
||||
local r=rnd(l)
|
||||
r,t[r]=t[r],t[l]
|
||||
t[l]=nil
|
||||
return r
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove [1~#] of table
|
||||
function TABLE.cut(G)
|
||||
for i=1,#G do
|
||||
G[i]=nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Clear table
|
||||
function TABLE.clear(G)
|
||||
for k in next,G do
|
||||
G[k]=nil
|
||||
end
|
||||
end
|
||||
|
||||
--------------------[Handling duplicates]---------------------
|
||||
|
||||
-- Remove duplicated value of [1~#]
|
||||
function TABLE.trimDuplicate(org)
|
||||
local cache={}
|
||||
for i=1,#org,-1 do
|
||||
if cache[org[i]] then
|
||||
rem(org,i)
|
||||
else
|
||||
cache[org[i]]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Discard duplicated value
|
||||
function TABLE.remDuplicate(org)
|
||||
local cache={}
|
||||
for k,v in next,org do
|
||||
if cache[v] then
|
||||
org[k]=nil
|
||||
else
|
||||
cache[v]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Run length encoder. Input must be a list containing non-nil value(s).
|
||||
Example:
|
||||
- Input: {1, 1, 2, 2, 2, 1}
|
||||
- Output: {{1, 2}, {2, 3}, {1, 1}}
|
||||
- This means: "Two 1's in a row", "Three 2's in a row", "One 1 in a row"
|
||||
]]
|
||||
function TABLE.RLE(org)
|
||||
local output={}
|
||||
local cur=nil
|
||||
local count=0
|
||||
|
||||
for i=1,#org do
|
||||
local item=org[i]
|
||||
|
||||
if item==cur then
|
||||
count=count+1
|
||||
else
|
||||
if cur then
|
||||
ins(output,{cur,count})
|
||||
end
|
||||
cur=item
|
||||
count=1
|
||||
end
|
||||
end
|
||||
|
||||
if cur then
|
||||
ins(output,{cur,count})
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
----------------------[Reversing Tables]----------------------
|
||||
|
||||
-- Reverse [1~#]
|
||||
function TABLE.reverse(org)
|
||||
local l=#org
|
||||
for i=1,math.floor(l/2) do
|
||||
org[i],org[l+1-i]=org[l+1-i],org[i]
|
||||
end
|
||||
end
|
||||
|
||||
----------------------[Table Comparison]----------------------
|
||||
|
||||
-- Check if tow list have same elements
|
||||
function TABLE.compare(a,b)
|
||||
if #a~=#b then return false end
|
||||
if a==b then return true end
|
||||
for i=1,#a do
|
||||
if a[i]~=b[i] then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check if tow table have same elements
|
||||
function TABLE.equal(a,b)
|
||||
if #a~=#b then return false end
|
||||
if a==b then return true end
|
||||
for k,v in next,a do
|
||||
if b[k]~=v then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
----------------------[Table Operations]----------------------
|
||||
|
||||
-- Find value in [1~#], like string.find
|
||||
function TABLE.find(t,val,start)
|
||||
for i=start or 1,#t do if t[i]==val then return i end end
|
||||
end
|
||||
|
||||
-- Get subset of table, like string.sub
|
||||
function TABLE.sub(t,i,j)
|
||||
local subTable={}
|
||||
for k=max(i,1),(j and min(j,#t) or #t) do
|
||||
subTable[k-i+1]=t[k]
|
||||
end
|
||||
return subTable
|
||||
end
|
||||
|
||||
-- Replace value in [1~#], like string.gsub
|
||||
function TABLE.gsub(t,v_old,v_new,count,start)
|
||||
if not start then start=1 end
|
||||
if not count then count=1e99 end
|
||||
while t[start] and count>0 do
|
||||
if t[start]==v_old then
|
||||
t[start]=v_new
|
||||
count=count-1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Return next value of [1~#] (by value)
|
||||
function TABLE.next(t,val)
|
||||
for i=1,#t do if t[i]==val then return t[i%#t+1] end end
|
||||
end
|
||||
|
||||
-- Find value in whole table
|
||||
function TABLE.search(t,val)
|
||||
for k,v in next,t do if v==val then return k end end
|
||||
end
|
||||
|
||||
-- Replace all value in t
|
||||
function TABLE.replace(t,v_old,v_new)
|
||||
for k,v in next,t do
|
||||
if v==v_old then
|
||||
t[k]=v_new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-index string value of a table
|
||||
function TABLE.reIndex(org)
|
||||
for k,v in next,org do
|
||||
if type(v)=='string' then
|
||||
org[k]=org[v]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Return table where keys and values are swapped (useful for hashmap)
|
||||
function TABLE.kvSwap(t)
|
||||
local output={}
|
||||
for k,v in next,t do output[v]=k end
|
||||
return output
|
||||
end
|
||||
|
||||
--[[
|
||||
Extracts a value from each sub-table in table.
|
||||
Example input: ({{name='A'},{name='B'},{name='C'}}, 'name')
|
||||
Output: {'A','B'}
|
||||
]]
|
||||
function TABLE.extract(t,keyName)
|
||||
local output={}
|
||||
for k,v in next,t do output[k]=v[keyName] end
|
||||
return output
|
||||
end
|
||||
|
||||
-- Get element count of table
|
||||
function TABLE.getSize(t)
|
||||
local size=0
|
||||
for _ in next,t do size=size+1 end
|
||||
return size
|
||||
end
|
||||
|
||||
-----------------------[Table Rotation]-----------------------
|
||||
|
||||
-- Copy a rotated matrix table
|
||||
function TABLE.rotate(cb,dir)
|
||||
local icb={}
|
||||
if dir=='R' then-- Rotate CW
|
||||
for y=1,#cb[1] do
|
||||
icb[y]={}
|
||||
for x=1,#cb do
|
||||
icb[y][x]=cb[x][#cb[1]-y+1]
|
||||
end
|
||||
end
|
||||
elseif dir=='L' then-- Rotate CCW
|
||||
for y=1,#cb[1] do
|
||||
icb[y]={}
|
||||
for x=1,#cb do
|
||||
icb[y][x]=cb[#cb-x+1][y]
|
||||
end
|
||||
end
|
||||
elseif dir=='F' then-- Rotate 180 degree
|
||||
for y=1,#cb do
|
||||
icb[y]={}
|
||||
for x=1,#cb[1] do
|
||||
icb[y][x]=cb[#cb-y+1][#cb[1]-x+1]
|
||||
end
|
||||
end
|
||||
end
|
||||
return icb
|
||||
end
|
||||
|
||||
----------------------[Table Functions]-----------------------
|
||||
|
||||
-- Return a function that return a value of table
|
||||
function TABLE.func_getVal(t,k)
|
||||
return function() return t[k] end
|
||||
end
|
||||
|
||||
-- Return a function that reverse a value of table
|
||||
function TABLE.func_revVal(t,k)
|
||||
return function() t[k]=not t[k] end
|
||||
end
|
||||
|
||||
-- Return a function that set a value of table
|
||||
function TABLE.func_setVal(t,k)
|
||||
return function(v) t[k]=v end
|
||||
end
|
||||
|
||||
-------------------------[Table Dump]-------------------------
|
||||
|
||||
-- Dump a simple lua table (no whitespaces)
|
||||
do-- function TABLE.dumpDeflate(L,t)
|
||||
local function dump(L)
|
||||
if type(L)~='table' then return end
|
||||
local s='{'
|
||||
local count=1
|
||||
for k,v in next,L do
|
||||
local T=type(k)
|
||||
if T=='number' then
|
||||
if k==count then
|
||||
k=''
|
||||
count=count+1
|
||||
else
|
||||
k='['..k..']='
|
||||
end
|
||||
elseif T=='string' then
|
||||
if find(k,'[^0-9a-zA-Z_]') then
|
||||
k='[\''..k..'\']='
|
||||
else
|
||||
k=k..'='
|
||||
end
|
||||
elseif T=='boolean' then k='['..k..']='
|
||||
else error("Error key type!")
|
||||
end
|
||||
T=type(v)
|
||||
if T=='number' then v=tostring(v)
|
||||
elseif T=='string' then v='\''..v..'\''
|
||||
elseif T=='table' then v=dump(v)
|
||||
elseif T=='boolean' then v=tostring(v)
|
||||
else v='*'..tostring(v)
|
||||
end
|
||||
s=s..k..v..','
|
||||
end
|
||||
return s..'}'
|
||||
end
|
||||
TABLE.dumpDeflate=dump
|
||||
end
|
||||
|
||||
-- Dump a simple lua table
|
||||
do-- function TABLE.dump(L,t)
|
||||
local tabs=setmetatable({
|
||||
[0]='',
|
||||
'\t',
|
||||
},{__index=function(self,k)
|
||||
if k>=626 then error("Too many tabs!") end
|
||||
for i=#self+1,k do
|
||||
self[i]=self[i-1]..'\t'
|
||||
end
|
||||
return self[k]
|
||||
end})
|
||||
local function dump(L,t)
|
||||
local s='{\n'
|
||||
if not t then
|
||||
s='return {\n'
|
||||
t=1
|
||||
if type(L)~='table' then
|
||||
return
|
||||
end
|
||||
end
|
||||
local count=1
|
||||
for k,v in next,L do
|
||||
local T=type(k)
|
||||
if T=='number' then
|
||||
if k==count then
|
||||
k=''
|
||||
count=count+1
|
||||
else
|
||||
k='['..k..']='
|
||||
end
|
||||
elseif T=='string' then
|
||||
if find(k,'[^0-9a-zA-Z_]') then
|
||||
k='[\''..k..'\']='
|
||||
else
|
||||
k=k..'='
|
||||
end
|
||||
elseif T=='boolean' then k='['..k..']='
|
||||
else k='[\'*'..tostring(k)..'\']='
|
||||
end
|
||||
T=type(v)
|
||||
if T=='number' then v=tostring(v)
|
||||
elseif T=='string' then v='\''..v..'\''
|
||||
elseif T=='table' then v=dump(v,t+1)
|
||||
elseif T=='boolean' then v=tostring(v)
|
||||
else v='*'..tostring(v)
|
||||
end
|
||||
s=s..tabs[t]..k..v..',\n'
|
||||
end
|
||||
return s..tabs[t-1]..'}'
|
||||
end
|
||||
TABLE.dump=dump
|
||||
end
|
||||
|
||||
return TABLE
|
||||
83
Zframework/task.lua
Normal file
83
Zframework/task.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
local rem=table.remove
|
||||
local assert,resume,status=assert,coroutine.resume,coroutine.status
|
||||
local rawset=rawset
|
||||
local timer=love.timer.getTime
|
||||
|
||||
local TASK={}
|
||||
|
||||
-- Locks
|
||||
local locks=setmetatable({},{
|
||||
__index=function(self,k) rawset(self,k,-1e99)return -1e99 end,
|
||||
__newindex=function(self,k) rawset(self,k,-1e99) end,
|
||||
})
|
||||
function TASK.lock(name,T)
|
||||
if timer()>=locks[name] then
|
||||
locks[name]=timer()+(T or 1e99)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
function TASK.unlock(name)
|
||||
locks[name]=-1e99
|
||||
end
|
||||
function TASK.getLock(name)
|
||||
local v=locks[name]-timer()
|
||||
return v>0 and v
|
||||
end
|
||||
function TASK.clearLock()
|
||||
for k in next,locks do
|
||||
locks[k]=nil
|
||||
end
|
||||
end
|
||||
|
||||
local tasks={}
|
||||
|
||||
function TASK.getCount()
|
||||
return #tasks
|
||||
end
|
||||
local trigFrame=0
|
||||
function TASK.update(dt)
|
||||
trigFrame=trigFrame+dt*60
|
||||
for _=1,trigFrame do
|
||||
for i=#tasks,1,-1 do
|
||||
local T=tasks[i]
|
||||
if status(T.thread)=='dead' then
|
||||
rem(tasks,i)
|
||||
else
|
||||
assert(resume(T.thread,dt/trigFrame))
|
||||
end
|
||||
end
|
||||
end
|
||||
trigFrame=1
|
||||
end
|
||||
function TASK.new(code,...)
|
||||
local thread=coroutine.create(code)
|
||||
assert(resume(thread,...))
|
||||
if status(thread)~='dead' then
|
||||
tasks[#tasks+1]={
|
||||
thread=thread,
|
||||
code=code,
|
||||
args={...},
|
||||
}
|
||||
end
|
||||
end
|
||||
function TASK.removeTask_code(code)
|
||||
for i=#tasks,1,-1 do
|
||||
if tasks[i].code==code then
|
||||
rem(tasks,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
function TASK.removeTask_iterate(func,...)
|
||||
for i=#tasks,1,-1 do
|
||||
if func(tasks[i],...) then
|
||||
rem(tasks,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
function TASK.clear()
|
||||
TABLE.cut(tasks)
|
||||
end
|
||||
|
||||
return TASK
|
||||
18
Zframework/test.lua
Normal file
18
Zframework/test.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
local yield=coroutine.yield
|
||||
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
|
||||
|
||||
function TEST.yieldT(timeout)
|
||||
local t=0
|
||||
repeat t=t+yield() until t>=timeout
|
||||
end
|
||||
|
||||
return TEST
|
||||
152
Zframework/text.lua
Normal file
152
Zframework/text.lua
Normal file
@@ -0,0 +1,152 @@
|
||||
local getColor,setColor=GC.getColor,GC.setColor
|
||||
|
||||
local floor,rnd=math.floor,math.random
|
||||
local ins,rem=table.insert,table.remove
|
||||
local draw=GC.draw
|
||||
|
||||
local texts={}
|
||||
|
||||
local textFX={}
|
||||
function textFX.appear(t)
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.sudden(t)
|
||||
setColor(1,1,1,1-t.c)
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.fly(t)
|
||||
draw(
|
||||
t.text,t.x+(t.c-.5)^3*300,t.y,
|
||||
nil,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.stretch(t)
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
t.c<.3 and (.3-t.c)*1.6+1 or 1,1,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.drive(t)
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5,
|
||||
t.c<.3 and (.3-t.c)*2 or 0,0
|
||||
)
|
||||
end
|
||||
function textFX.spin(t)
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
t.c<.3 and (.3-t.c)^2*4 or t.c<.8 and 0 or (t.c-.8)^2*-4,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.flicker(t)
|
||||
local _,_,_,T=getColor()
|
||||
setColor(1,1,1,T*(rnd()+.5))
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.zoomout(t)
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
t.c^.5*.1+1,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.beat(t)
|
||||
local k=t.c<.3 and 1.3-t.c^2/.3 or 1
|
||||
draw(
|
||||
t.text,t.x,t.y,
|
||||
nil,
|
||||
k,k,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
function textFX.score(t)
|
||||
local _,_,_,T=getColor()
|
||||
setColor(1,1,1,T*.5)
|
||||
draw(
|
||||
t.text,t.x,t.y-0-t.c^.2*50,
|
||||
nil,
|
||||
nil,nil,
|
||||
t.text:getWidth()*.5,t.text:getHeight()*.5
|
||||
)
|
||||
end
|
||||
|
||||
local TEXT={}
|
||||
function TEXT.clear()
|
||||
texts={}
|
||||
end
|
||||
function TEXT.show(text,x,y,font,style,spd,stop)
|
||||
ins(texts,{
|
||||
c=0, -- Timer
|
||||
text=GC.newText(FONT.get(floor(font/5)*5 or 40),text), -- String
|
||||
x=x or 0, -- X
|
||||
y=y or 0, -- Y
|
||||
spd=(spd or 1), -- Timing speed(1=last 1 sec)
|
||||
stop=stop, -- Stop time(sustained text)
|
||||
draw=assert(textFX[style or 'appear'],"no text type:"..style),-- Draw method
|
||||
})
|
||||
end
|
||||
function TEXT.getText(text,x,y,font,style,spd,stop)-- Another version of TEXT.show(), but only return text object, need manual management
|
||||
return {
|
||||
c=0,
|
||||
text=GC.newText(FONT.get(floor(font/5)*5 or 40),text),
|
||||
x=x or 0,
|
||||
y=y or 0,
|
||||
spd=(spd or 1),
|
||||
stop=stop,
|
||||
draw=textFX[style or 'appear'] or error("unavailable type:"..style),
|
||||
}
|
||||
end
|
||||
function TEXT.update(dt,list)
|
||||
if not list then
|
||||
list=texts
|
||||
end
|
||||
for i=#list,1,-1 do
|
||||
local t=list[i]
|
||||
t.c=t.c+t.spd*dt
|
||||
if t.stop then
|
||||
if t.c>t.stop then
|
||||
t.c=t.stop
|
||||
end
|
||||
end
|
||||
if t.c>1 then
|
||||
rem(list,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
function TEXT.draw(list)
|
||||
if not list then
|
||||
list=texts
|
||||
end
|
||||
for i=1,#list do
|
||||
local t=list[i]
|
||||
local p=t.c
|
||||
setColor(1,1,1,p<.2 and p*5 or p<.8 and 1 or 5-p*5)
|
||||
t:draw()
|
||||
end
|
||||
end
|
||||
return TEXT
|
||||
26
Zframework/upcaser.txt
Normal file
26
Zframework/upcaser.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
a=A,b=B,c=C,d=D,e=E,f=F,g=G,h=H,i=I,j=J,k=K,l=L,m=M,n=N,o=O,p=P,q=Q,r=R,s=S,t=T,u=U,v=V,w=W,x=X,y=Y,z=Z
|
||||
µ=Μ,ß=SS,à=À,á=Á,â=Â,ã=Ã,ä=Ä,å=Å,æ=Æ,ç=Ç,è=È,é=É,ê=Ê,ë=Ë,ì=Ì,í=Í,î=Î,ï=Ï,ð=Ð,ñ=Ñ,ò=Ò,ó=Ó,ô=Ô,õ=Õ,ö=Ö,ø=Ø,ù=Ù,ú=Ú,û=Û,ü=Ü,ý=Ý,þ=Þ,ÿ=Ÿ,ā=Ā,ă=Ă,ą=Ą,ć=Ć,ĉ=Ĉ,ċ=Ċ,č=Č,ď=Ď,đ=Đ,ē=Ē,ĕ=Ĕ,ė=Ė,ę=Ę,ě=Ě,ĝ=Ĝ,ğ=Ğ,ġ=Ġ,ģ=Ģ,ĥ=Ĥ,ħ=Ħ,ĩ=Ĩ,ī=Ī,ĭ=Ĭ,į=Į,ij=IJ,ĵ=Ĵ,ķ=Ķ,ĺ=Ĺ,ļ=Ļ,ľ=Ľ,ŀ=Ŀ,ł=Ł,ń=Ń,ņ=Ņ,ň=Ň,ŋ=Ŋ,ō=Ō,ŏ=Ŏ,ő=Ő,œ=Œ,ŕ=Ŕ,ŗ=Ŗ,ř=Ř,ś=Ś,ŝ=Ŝ,ş=Ş,š=Š,ţ=Ţ,ť=Ť,ŧ=Ŧ,ũ=Ũ,ū=Ū,ŭ=Ŭ,ů=Ů,ű=Ű,ų=Ų,ŵ=Ŵ,ŷ=Ŷ,ź=Ź,ż=Ż,ž=Ž
|
||||
ƀ=Ƀ,ƃ=Ƃ,ƅ=Ƅ,ƈ=Ƈ,ƌ=Ƌ,ƒ=Ƒ,ƕ=Ƕ,ƙ=Ƙ,ƚ=Ƚ,ƞ=Ƞ,ơ=Ơ,ƣ=Ƣ,ƥ=Ƥ,ƨ=Ƨ,ƭ=Ƭ,ư=Ư,ƴ=Ƴ,ƶ=Ƶ,ƹ=Ƹ,ƽ=Ƽ,ƿ=Ƿ,dž=DŽ,lj=LJ,nj=NJ,ǎ=Ǎ,ǐ=Ǐ,ǒ=Ǒ,ǔ=Ǔ,ǖ=Ǖ,ǘ=Ǘ,ǚ=Ǚ,ǜ=Ǜ,ǝ=Ǝ,ǟ=Ǟ,ǡ=Ǡ,ǣ=Ǣ,ǥ=Ǥ,ǧ=Ǧ,ǩ=Ǩ,ǫ=Ǫ,ǭ=Ǭ,ǯ=Ǯ,dz=DZ,ǵ=Ǵ,ǹ=Ǹ,ǻ=Ǻ,ǽ=Ǽ,ǿ=Ǿ,ȁ=Ȁ,ȃ=Ȃ,ȅ=Ȅ,ȇ=Ȇ,ȉ=Ȉ,ȋ=Ȋ,ȍ=Ȍ,ȏ=Ȏ,ȑ=Ȑ,ȓ=Ȓ,ȕ=Ȕ,ȗ=Ȗ,ș=Ș,ț=Ț,ȝ=Ȝ,ȟ=Ȟ,ȣ=Ȣ,ȥ=Ȥ,ȧ=Ȧ,ȩ=Ȩ,ȫ=Ȫ,ȭ=Ȭ,ȯ=Ȯ,ȱ=Ȱ,ȳ=Ȳ,ȼ=Ȼ,ȿ=Ȿ,ɀ=Ɀ,ɂ=Ɂ,ɇ=Ɇ,ɉ=Ɉ,ɋ=Ɋ,ɍ=Ɍ,ɏ=Ɏ
|
||||
ɐ=Ɐ,ɑ=Ɑ,ɒ=Ɒ,ɓ=Ɓ,ɔ=Ɔ,ɖ=Ɖ,ɗ=Ɗ,ə=Ə,ɛ=Ɛ,ɜ=Ɜ,ɠ=Ɠ,ɡ=Ɡ,ɣ=Ɣ,ɥ=Ɥ,ɦ=Ɦ,ɨ=Ɨ,ɩ=Ɩ,ɪ=Ɪ,ɫ=Ɫ,ɬ=Ɬ,ɯ=Ɯ,ɱ=Ɱ,ɲ=Ɲ,ɵ=Ɵ,ɽ=Ɽ,ʀ=Ʀ,ʂ=Ʂ,ʃ=Ʃ,ʇ=Ʇ,ʈ=Ʈ,ʉ=Ʉ,ʊ=Ʊ,ʋ=Ʋ,ʌ=Ʌ,ʒ=Ʒ,ʝ=Ʝ,ʞ=Ʞ
|
||||
ͱ=Ͱ,ͳ=Ͳ,ͷ=Ͷ,ͻ=Ͻ,ͼ=Ͼ,ͽ=Ͽ,ά=Ά,έ=Έ,ή=Ή,ί=Ί,α=Α,β=Β,γ=Γ,δ=Δ,ε=Ε,ζ=Ζ,η=Η,θ=Θ,κ=Κ,λ=Λ,ν=Ν,ξ=Ξ,ο=Ο,π=Π,ρ=Ρ,σ=Σ,τ=Τ,υ=Υ,φ=Φ,χ=Χ,ψ=Ψ,ω=Ω,ϊ=Ϊ,ϋ=Ϋ,ό=Ό,ύ=Ύ,ώ=Ώ,ϗ=Ϗ,ϙ=Ϙ,ϛ=Ϛ,ϝ=Ϝ,ϟ=Ϟ,ϡ=Ϡ,ϣ=Ϣ,ϥ=Ϥ,ϧ=Ϧ,ϩ=Ϩ,ϫ=Ϫ,ϭ=Ϭ,ϯ=Ϯ,ϲ=Ϲ,ϳ=Ϳ,ϸ=Ϸ,ϻ=Ϻ
|
||||
а=А,б=Б,в=В,г=Г,д=Д,е=Е,ж=Ж,з=З,и=И,й=Й,к=К,л=Л,м=М,н=Н,о=О,п=П,р=Р,с=С,т=Т,у=У,ф=Ф,х=Х,ц=Ц,ч=Ч,ш=Ш,щ=Щ,ъ=Ъ,ы=Ы,ь=Ь,э=Э,ю=Ю,я=Я,ѐ=Ѐ,ё=Ё,ђ=Ђ,ѓ=Ѓ,є=Є,ѕ=Ѕ,і=І,ї=Ї,ј=Ј,љ=Љ,њ=Њ,ћ=Ћ,ќ=Ќ,ѝ=Ѝ,ў=Ў,џ=Џ,ѡ=Ѡ,ѣ=Ѣ,ѥ=Ѥ,ѧ=Ѧ,ѩ=Ѩ,ѫ=Ѫ,ѭ=Ѭ,ѯ=Ѯ,ѱ=Ѱ,ѳ=Ѳ,ѵ=Ѵ,ѷ=Ѷ,ѹ=Ѹ,ѻ=Ѻ,ѽ=Ѽ,ѿ=Ѿ,ҁ=Ҁ,ҋ=Ҋ,ҍ=Ҍ,ҏ=Ҏ,ґ=Ґ,ғ=Ғ,ҕ=Ҕ,җ=Җ,ҙ=Ҙ,қ=Қ,ҝ=Ҝ,ҟ=Ҟ,ҡ=Ҡ,ң=Ң,ҥ=Ҥ,ҧ=Ҧ,ҩ=Ҩ,ҫ=Ҫ,ҭ=Ҭ,ү=Ү,ұ=Ұ,ҳ=Ҳ,ҵ=Ҵ,ҷ=Ҷ,ҹ=Ҹ,һ=Һ,ҽ=Ҽ,ҿ=Ҿ,ӂ=Ӂ,ӄ=Ӄ,ӆ=Ӆ,ӈ=Ӈ,ӊ=Ӊ,ӌ=Ӌ,ӎ=Ӎ,ӏ=Ӏ,ӑ=Ӑ,ӓ=Ӓ,ӕ=Ӕ,ӗ=Ӗ,ә=Ә,ӛ=Ӛ,ӝ=Ӝ,ӟ=Ӟ,ӡ=Ӡ,ӣ=Ӣ,ӥ=Ӥ,ӧ=Ӧ,ө=Ө,ӫ=Ӫ,ӭ=Ӭ,ӯ=Ӯ,ӱ=Ӱ,ӳ=Ӳ,ӵ=Ӵ,ӷ=Ӷ,ӹ=Ӹ,ӻ=Ӻ,ӽ=Ӽ,ӿ=Ӿ,ԁ=Ԁ,ԃ=Ԃ,ԅ=Ԅ,ԇ=Ԇ,ԉ=Ԉ,ԋ=Ԋ,ԍ=Ԍ,ԏ=Ԏ,ԑ=Ԑ,ԓ=Ԓ,ԕ=Ԕ,ԗ=Ԗ,ԙ=Ԙ,ԛ=Ԛ,ԝ=Ԝ,ԟ=Ԟ,ԡ=Ԡ,ԣ=Ԣ,ԥ=Ԥ,ԧ=Ԧ,ԩ=Ԩ,ԫ=Ԫ,ԭ=Ԭ,ԯ=Ԯ
|
||||
ա=Ա,բ=Բ,գ=Գ,դ=Դ,ե=Ե,զ=Զ,է=Է,ը=Ը,թ=Թ,ժ=Ժ,ի=Ի,լ=Լ,խ=Խ,ծ=Ծ,կ=Կ,հ=Հ,ձ=Ձ,ղ=Ղ,ճ=Ճ,մ=Մ,յ=Յ,ն=Ն,շ=Շ,ո=Ո,չ=Չ,պ=Պ,ջ=Ջ,ռ=Ռ,ս=Ս,վ=Վ,տ=Տ,ր=Ր,ց=Ց,ւ=Ւ,փ=Փ,ք=Ք,օ=Օ,ֆ=Ֆ
|
||||
ა=Ა,ბ=Ბ,გ=Გ,დ=Დ,ე=Ე,ვ=Ვ,ზ=Ზ,თ=Თ,ი=Ი,კ=Კ,ლ=Ლ,მ=Მ,ნ=Ნ,ო=Ო,პ=Პ,ჟ=Ჟ,რ=Რ,ს=Ს,ტ=Ტ,უ=Უ,ფ=Ფ,ქ=Ქ,ღ=Ღ,ყ=Ყ,შ=Შ,ჩ=Ჩ,ც=Ც,ძ=Ძ,წ=Წ,ჭ=Ჭ,ხ=Ხ,ჯ=Ჯ,ჰ=Ჰ,ჱ=Ჱ,ჲ=Ჲ,ჳ=Ჳ,ჴ=Ჴ,ჵ=Ჵ,ჶ=Ჶ,ჷ=Ჷ,ჸ=Ჸ,ჹ=Ჹ,ჺ=Ჺ,ჽ=Ჽ,ჾ=Ჾ,ჿ=Ჿ
|
||||
ᏸ=Ᏸ,ᏹ=Ᏹ,ᏺ=Ᏺ,ᏻ=Ᏻ,ᏼ=Ᏼ,ᏽ=Ᏽ
|
||||
ᲈ=Ꙋ,ᵹ=Ᵹ,ᵽ=Ᵽ,ᶎ=Ᶎ,ḁ=Ḁ,ḃ=Ḃ,ḅ=Ḅ,ḇ=Ḇ,ḉ=Ḉ,ḋ=Ḋ,ḍ=Ḍ,ḏ=Ḏ,ḑ=Ḑ,ḓ=Ḓ,ḕ=Ḕ,ḗ=Ḗ,ḙ=Ḙ,ḛ=Ḛ,ḝ=Ḝ,ḟ=Ḟ,ḡ=Ḡ,ḣ=Ḣ,ḥ=Ḥ,ḧ=Ḧ,ḩ=Ḩ,ḫ=Ḫ,ḭ=Ḭ,ḯ=Ḯ,ḱ=Ḱ,ḳ=Ḳ,ḵ=Ḵ,ḷ=Ḷ,ḹ=Ḹ,ḻ=Ḻ,ḽ=Ḽ,ḿ=Ḿ,ṁ=Ṁ,ṃ=Ṃ,ṅ=Ṅ,ṇ=Ṇ,ṉ=Ṉ,ṋ=Ṋ,ṍ=Ṍ,ṏ=Ṏ,ṑ=Ṑ,ṓ=Ṓ,ṕ=Ṕ,ṗ=Ṗ,ṙ=Ṙ,ṛ=Ṛ,ṝ=Ṝ,ṟ=Ṟ,ṡ=Ṡ,ṣ=Ṣ,ṥ=Ṥ,ṧ=Ṧ,ṩ=Ṩ,ṫ=Ṫ,ṭ=Ṭ,ṯ=Ṯ,ṱ=Ṱ,ṳ=Ṳ,ṵ=Ṵ,ṷ=Ṷ,ṹ=Ṹ,ṻ=Ṻ,ṽ=Ṽ,ṿ=Ṿ,ẁ=Ẁ,ẃ=Ẃ,ẅ=Ẅ,ẇ=Ẇ,ẉ=Ẉ,ẋ=Ẋ,ẍ=Ẍ,ẏ=Ẏ,ẑ=Ẑ,ẓ=Ẓ,ẕ=Ẕ,ạ=Ạ,ả=Ả,ấ=Ấ,ầ=Ầ,ẩ=Ẩ,ẫ=Ẫ,ậ=Ậ,ắ=Ắ,ằ=Ằ,ẳ=Ẳ,ẵ=Ẵ,ặ=Ặ,ẹ=Ẹ,ẻ=Ẻ,ẽ=Ẽ,ế=Ế,ề=Ề,ể=Ể,ễ=Ễ,ệ=Ệ,ỉ=Ỉ,ị=Ị,ọ=Ọ,ỏ=Ỏ,ố=Ố,ồ=Ồ,ổ=Ổ,ỗ=Ỗ,ộ=Ộ,ớ=Ớ,ờ=Ờ,ở=Ở,ỡ=Ỡ,ợ=Ợ,ụ=Ụ,ủ=Ủ,ứ=Ứ,ừ=Ừ,ử=Ử,ữ=Ữ,ự=Ự,ỳ=Ỳ,ỵ=Ỵ,ỷ=Ỷ,ỹ=Ỹ,ỻ=Ỻ,ỽ=Ỽ,ỿ=Ỿ,ἀ=Ἀ,ἁ=Ἁ,ἂ=Ἂ,ἃ=Ἃ,ἄ=Ἄ,ἅ=Ἅ,ἆ=Ἆ,ἇ=Ἇ,ἐ=Ἐ,ἑ=Ἑ,ἒ=Ἒ,ἓ=Ἓ,ἔ=Ἔ,ἕ=Ἕ,ἠ=Ἠ,ἡ=Ἡ,ἢ=Ἢ,ἣ=Ἣ,ἤ=Ἤ,ἥ=Ἥ,ἦ=Ἦ,ἧ=Ἧ,ἰ=Ἰ,ἱ=Ἱ,ἲ=Ἲ,ἳ=Ἳ,ἴ=Ἴ,ἵ=Ἵ,ἶ=Ἶ,ἷ=Ἷ,ὀ=Ὀ,ὁ=Ὁ,ὂ=Ὂ,ὃ=Ὃ,ὄ=Ὄ,ὅ=Ὅ,ὑ=Ὑ,ὓ=Ὓ,ὕ=Ὕ,ὗ=Ὗ,ὠ=Ὠ,ὡ=Ὡ,ὢ=Ὢ,ὣ=Ὣ,ὤ=Ὤ,ὥ=Ὥ,ὦ=Ὦ,ὧ=Ὧ,ὰ=Ὰ,ά=Ά,ὲ=Ὲ,έ=Έ,ὴ=Ὴ,ή=Ή,ὶ=Ὶ,ί=Ί,ὸ=Ὸ,ό=Ό,ὺ=Ὺ,ύ=Ύ,ὼ=Ὼ,ώ=Ώ,ᾰ=Ᾰ,ᾱ=Ᾱ,ῐ=Ῐ,ῑ=Ῑ,ῠ=Ῠ,ῡ=Ῡ,ῥ=Ῥ,ⅎ=Ⅎ
|
||||
ⅰ=Ⅰ,ⅱ=Ⅱ,ⅲ=Ⅲ,ⅳ=Ⅳ,ⅴ=Ⅴ,ⅵ=Ⅵ,ⅶ=Ⅶ,ⅷ=Ⅷ,ⅸ=Ⅸ,ⅹ=Ⅹ,ⅺ=Ⅺ,ⅻ=Ⅻ,ⅼ=Ⅼ,ⅽ=Ⅽ,ⅾ=Ⅾ,ⅿ=Ⅿ,ↄ=Ↄ
|
||||
ⓐ=Ⓐ,ⓑ=Ⓑ,ⓒ=Ⓒ,ⓓ=Ⓓ,ⓔ=Ⓔ,ⓕ=Ⓕ,ⓖ=Ⓖ,ⓗ=Ⓗ,ⓘ=Ⓘ,ⓙ=Ⓙ,ⓚ=Ⓚ,ⓛ=Ⓛ,ⓜ=Ⓜ,ⓝ=Ⓝ,ⓞ=Ⓞ,ⓟ=Ⓟ,ⓠ=Ⓠ,ⓡ=Ⓡ,ⓢ=Ⓢ,ⓣ=Ⓣ,ⓤ=Ⓤ,ⓥ=Ⓥ,ⓦ=Ⓦ,ⓧ=Ⓧ,ⓨ=Ⓨ,ⓩ=Ⓩ
|
||||
ⰰ=Ⰰ,ⰱ=Ⰱ,ⰲ=Ⰲ,ⰳ=Ⰳ,ⰴ=Ⰴ,ⰵ=Ⰵ,ⰶ=Ⰶ,ⰷ=Ⰷ,ⰸ=Ⰸ,ⰹ=Ⰹ,ⰺ=Ⰺ,ⰻ=Ⰻ,ⰼ=Ⰼ,ⰽ=Ⰽ,ⰾ=Ⰾ,ⰿ=Ⰿ,ⱀ=Ⱀ,ⱁ=Ⱁ,ⱂ=Ⱂ,ⱃ=Ⱃ,ⱄ=Ⱄ,ⱅ=Ⱅ,ⱆ=Ⱆ,ⱇ=Ⱇ,ⱈ=Ⱈ,ⱉ=Ⱉ,ⱊ=Ⱊ,ⱋ=Ⱋ,ⱌ=Ⱌ,ⱍ=Ⱍ,ⱎ=Ⱎ,ⱏ=Ⱏ,ⱐ=Ⱐ,ⱑ=Ⱑ,ⱒ=Ⱒ,ⱓ=Ⱓ,ⱔ=Ⱔ,ⱕ=Ⱕ,ⱖ=Ⱖ,ⱗ=Ⱗ,ⱘ=Ⱘ,ⱙ=Ⱙ,ⱚ=Ⱚ,ⱛ=Ⱛ,ⱜ=Ⱜ,ⱝ=Ⱝ,ⱞ=Ⱞ,ⱟ=Ⱟ
|
||||
ⱡ=Ⱡ,ⱥ=Ⱥ,ⱦ=Ⱦ,ⱨ=Ⱨ,ⱪ=Ⱪ,ⱬ=Ⱬ,ⱳ=Ⱳ,ⱶ=Ⱶ
|
||||
ⲁ=Ⲁ,ⲃ=Ⲃ,ⲅ=Ⲅ,ⲇ=Ⲇ,ⲉ=Ⲉ,ⲋ=Ⲋ,ⲍ=Ⲍ,ⲏ=Ⲏ,ⲑ=Ⲑ,ⲓ=Ⲓ,ⲕ=Ⲕ,ⲗ=Ⲗ,ⲙ=Ⲙ,ⲛ=Ⲛ,ⲝ=Ⲝ,ⲟ=Ⲟ,ⲡ=Ⲡ,ⲣ=Ⲣ,ⲥ=Ⲥ,ⲧ=Ⲧ,ⲩ=Ⲩ,ⲫ=Ⲫ,ⲭ=Ⲭ,ⲯ=Ⲯ,ⲱ=Ⲱ,ⲳ=Ⲳ,ⲵ=Ⲵ,ⲷ=Ⲷ,ⲹ=Ⲹ,ⲻ=Ⲻ,ⲽ=Ⲽ,ⲿ=Ⲿ,ⳁ=Ⳁ,ⳃ=Ⳃ,ⳅ=Ⳅ,ⳇ=Ⳇ,ⳉ=Ⳉ,ⳋ=Ⳋ,ⳍ=Ⳍ,ⳏ=Ⳏ,ⳑ=Ⳑ,ⳓ=Ⳓ,ⳕ=Ⳕ,ⳗ=Ⳗ,ⳙ=Ⳙ,ⳛ=Ⳛ,ⳝ=Ⳝ,ⳟ=Ⳟ,ⳡ=Ⳡ,ⳣ=Ⳣ,ⳬ=Ⳬ,ⳮ=Ⳮ,ⳳ=Ⳳ
|
||||
ⴀ=Ⴀ,ⴁ=Ⴁ,ⴂ=Ⴂ,ⴃ=Ⴃ,ⴄ=Ⴄ,ⴅ=Ⴅ,ⴆ=Ⴆ,ⴇ=Ⴇ,ⴈ=Ⴈ,ⴉ=Ⴉ,ⴊ=Ⴊ,ⴋ=Ⴋ,ⴌ=Ⴌ,ⴍ=Ⴍ,ⴎ=Ⴎ,ⴏ=Ⴏ,ⴐ=Ⴐ,ⴑ=Ⴑ,ⴒ=Ⴒ,ⴓ=Ⴓ,ⴔ=Ⴔ,ⴕ=Ⴕ,ⴖ=Ⴖ,ⴗ=Ⴗ,ⴘ=Ⴘ,ⴙ=Ⴙ,ⴚ=Ⴚ,ⴛ=Ⴛ,ⴜ=Ⴜ,ⴝ=Ⴝ,ⴞ=Ⴞ,ⴟ=Ⴟ,ⴠ=Ⴠ,ⴡ=Ⴡ,ⴢ=Ⴢ,ⴣ=Ⴣ,ⴤ=Ⴤ,ⴥ=Ⴥ,ⴧ=Ⴧ
|
||||
ⴭ=Ⴭ,ꙁ=Ꙁ,ꙃ=Ꙃ,ꙅ=Ꙅ,ꙇ=Ꙇ,ꙉ=Ꙉ,ꙍ=Ꙍ,ꙏ=Ꙏ,ꙑ=Ꙑ,ꙓ=Ꙓ,ꙕ=Ꙕ,ꙗ=Ꙗ,ꙙ=Ꙙ,ꙛ=Ꙛ,ꙝ=Ꙝ,ꙟ=Ꙟ,ꙡ=Ꙡ,ꙣ=Ꙣ,ꙥ=Ꙥ,ꙧ=Ꙧ,ꙩ=Ꙩ,ꙫ=Ꙫ,ꙭ=Ꙭ,ꚁ=Ꚁ,ꚃ=Ꚃ,ꚅ=Ꚅ,ꚇ=Ꚇ,ꚉ=Ꚉ,ꚋ=Ꚋ,ꚍ=Ꚍ,ꚏ=Ꚏ,ꚑ=Ꚑ,ꚓ=Ꚓ,ꚕ=Ꚕ,ꚗ=Ꚗ,ꚙ=Ꚙ,ꚛ=Ꚛ,ꜣ=Ꜣ,ꜥ=Ꜥ,ꜧ=Ꜧ,ꜩ=Ꜩ,ꜫ=Ꜫ,ꜭ=Ꜭ,ꜯ=Ꜯ,ꜳ=Ꜳ,ꜵ=Ꜵ,ꜷ=Ꜷ,ꜹ=Ꜹ,ꜻ=Ꜻ,ꜽ=Ꜽ,ꜿ=Ꜿ,ꝁ=Ꝁ,ꝃ=Ꝃ,ꝅ=Ꝅ,ꝇ=Ꝇ,ꝉ=Ꝉ,ꝋ=Ꝋ,ꝍ=Ꝍ,ꝏ=Ꝏ,ꝑ=Ꝑ,ꝓ=Ꝓ,ꝕ=Ꝕ,ꝗ=Ꝗ,ꝙ=Ꝙ,ꝛ=Ꝛ,ꝝ=Ꝝ,ꝟ=Ꝟ,ꝡ=Ꝡ,ꝣ=Ꝣ,ꝥ=Ꝥ,ꝧ=Ꝧ,ꝩ=Ꝩ,ꝫ=Ꝫ,ꝭ=Ꝭ,ꝯ=Ꝯ,ꝺ=Ꝺ,ꝼ=Ꝼ,ꝿ=Ꝿ,ꞁ=Ꞁ,ꞃ=Ꞃ,ꞅ=Ꞅ,ꞇ=Ꞇ,ꞌ=Ꞌ,ꞑ=Ꞑ,ꞓ=Ꞓ,ꞔ=Ꞔ,ꞗ=Ꞗ,ꞙ=Ꞙ,ꞛ=Ꞛ,ꞝ=Ꞝ,ꞟ=Ꞟ,ꞡ=Ꞡ,ꞣ=Ꞣ,ꞥ=Ꞥ,ꞧ=Ꞧ,ꞩ=Ꞩ,ꞵ=Ꞵ,ꞷ=Ꞷ,ꞹ=Ꞹ,ꞻ=Ꞻ,ꞽ=Ꞽ,ꞿ=Ꞿ,ꟁ=Ꟁ,ꟃ=Ꟃ,ꟈ=Ꟈ,ꟊ=Ꟊ,ꟑ=Ꟑ,ꟗ=Ꟗ,ꟙ=Ꟙ,ꟶ=Ꟶ,ꭓ=Ꭓ
|
||||
ꭰ=Ꭰ,ꭱ=Ꭱ,ꭲ=Ꭲ,ꭳ=Ꭳ,ꭴ=Ꭴ,ꭵ=Ꭵ,ꭶ=Ꭶ,ꭷ=Ꭷ,ꭸ=Ꭸ,ꭹ=Ꭹ,ꭺ=Ꭺ,ꭻ=Ꭻ,ꭼ=Ꭼ,ꭽ=Ꭽ,ꭾ=Ꭾ,ꭿ=Ꭿ,ꮀ=Ꮀ,ꮁ=Ꮁ,ꮂ=Ꮂ,ꮃ=Ꮃ,ꮄ=Ꮄ,ꮅ=Ꮅ,ꮆ=Ꮆ,ꮇ=Ꮇ,ꮈ=Ꮈ,ꮉ=Ꮉ,ꮊ=Ꮊ,ꮋ=Ꮋ,ꮌ=Ꮌ,ꮍ=Ꮍ,ꮎ=Ꮎ,ꮏ=Ꮏ,ꮐ=Ꮐ,ꮑ=Ꮑ,ꮒ=Ꮒ,ꮓ=Ꮓ,ꮔ=Ꮔ,ꮕ=Ꮕ,ꮖ=Ꮖ,ꮗ=Ꮗ,ꮘ=Ꮘ,ꮙ=Ꮙ,ꮚ=Ꮚ,ꮛ=Ꮛ,ꮜ=Ꮜ,ꮝ=Ꮝ,ꮞ=Ꮞ,ꮟ=Ꮟ,ꮠ=Ꮠ,ꮡ=Ꮡ,ꮢ=Ꮢ,ꮣ=Ꮣ,ꮤ=Ꮤ,ꮥ=Ꮥ,ꮦ=Ꮦ,ꮧ=Ꮧ,ꮨ=Ꮨ,ꮩ=Ꮩ,ꮪ=Ꮪ,ꮫ=Ꮫ,ꮬ=Ꮬ,ꮭ=Ꮭ,ꮮ=Ꮮ,ꮯ=Ꮯ,ꮰ=Ꮰ,ꮱ=Ꮱ,ꮲ=Ꮲ,ꮳ=Ꮳ,ꮴ=Ꮴ,ꮵ=Ꮵ,ꮶ=Ꮶ,ꮷ=Ꮷ,ꮸ=Ꮸ,ꮹ=Ꮹ,ꮺ=Ꮺ,ꮻ=Ꮻ,ꮼ=Ꮼ,ꮽ=Ꮽ,ꮾ=Ꮾ,ꮿ=Ꮿ
|
||||
a=A,b=B,c=C,d=D,e=E,f=F,g=G,h=H,i=I,j=J,k=K,l=L,m=M,n=N,o=O,p=P,q=Q,r=R,s=S,t=T,u=U,v=V,w=W,x=X,y=Y,z=Z
|
||||
𐐨=𐐀,𐐩=𐐁,𐐪=𐐂,𐐫=𐐃,𐐬=𐐄,𐐭=𐐅,𐐮=𐐆,𐐯=𐐇,𐐰=𐐈,𐐱=𐐉,𐐲=𐐊,𐐳=𐐋,𐐴=𐐌,𐐵=𐐍,𐐶=𐐎,𐐷=𐐏,𐐸=𐐐,𐐹=𐐑,𐐺=𐐒,𐐻=𐐓,𐐼=𐐔,𐐽=𐐕,𐐾=𐐖,𐐿=𐐗,𐑀=𐐘,𐑁=𐐙,𐑂=𐐚,𐑃=𐐛,𐑄=𐐜,𐑅=𐐝,𐑆=𐐞,𐑇=𐐟,𐑈=𐐠,𐑉=𐐡,𐑊=𐐢,𐑋=𐐣,𐑌=𐐤,𐑍=𐐥,𐑎=𐐦,𐑏=𐐧
|
||||
𐓘=𐒰,𐓙=𐒱,𐓚=𐒲,𐓛=𐒳,𐓜=𐒴,𐓝=𐒵,𐓞=𐒶,𐓟=𐒷,𐓠=𐒸,𐓡=𐒹,𐓢=𐒺,𐓣=𐒻,𐓤=𐒼,𐓥=𐒽,𐓦=𐒾,𐓧=𐒿,𐓨=𐓀,𐓩=𐓁,𐓪=𐓂,𐓫=𐓃,𐓬=𐓄,𐓭=𐓅,𐓮=𐓆,𐓯=𐓇,𐓰=𐓈,𐓱=𐓉,𐓲=𐓊,𐓳=𐓋,𐓴=𐓌,𐓵=𐓍,𐓶=𐓎,𐓷=𐓏,𐓸=𐓐,𐓹=𐓑,𐓺=𐓒,𐓻=𐓓
|
||||
𐳀=𐲀,𐳁=𐲁,𐳂=𐲂,𐳃=𐲃,𐳄=𐲄,𐳅=𐲅,𐳆=𐲆,𐳇=𐲇,𐳈=𐲈,𐳉=𐲉,𐳊=𐲊,𐳋=𐲋,𐳌=𐲌,𐳍=𐲍,𐳎=𐲎,𐳏=𐲏,𐳐=𐲐,𐳑=𐲑,𐳒=𐲒,𐳓=𐲓,𐳔=𐲔,𐳕=𐲕,𐳖=𐲖,𐳗=𐲗,𐳘=𐲘,𐳙=𐲙,𐳚=𐲚,𐳛=𐲛,𐳜=𐲜,𐳝=𐲝,𐳞=𐲞,𐳟=𐲟,𐳠=𐲠,𐳡=𐲡,𐳢=𐲢,𐳣=𐲣,𐳤=𐲤,𐳥=𐲥,𐳦=𐲦,𐳧=𐲧,𐳨=𐲨,𐳩=𐲩,𐳪=𐲪,𐳫=𐲫,𐳬=𐲬,𐳭=𐲭,𐳮=𐲮,𐳯=𐲯,𐳰=𐲰,𐳱=𐲱,𐳲=𐲲
|
||||
𑣀=𑢠,𑣁=𑢡,𑣂=𑢢,𑣃=𑢣,𑣄=𑢤,𑣅=𑢥,𑣆=𑢦,𑣇=𑢧,𑣈=𑢨,𑣉=𑢩,𑣊=𑢪,𑣋=𑢫,𑣌=𑢬,𑣍=𑢭,𑣎=𑢮,𑣏=𑢯,𑣐=𑢰,𑣑=𑢱,𑣒=𑢲,𑣓=𑢳,𑣔=𑢴,𑣕=𑢵,𑣖=𑢶,𑣗=𑢷,𑣘=𑢸,𑣙=𑢹,𑣚=𑢺,𑣛=𑢻,𑣜=𑢼,𑣝=𑢽,𑣞=𑢾,𑣟=𑢿
|
||||
𖹠=𖹀,𖹡=𖹁,𖹢=𖹂,𖹣=𖹃,𖹤=𖹄,𖹥=𖹅,𖹦=𖹆,𖹧=𖹇,𖹨=𖹈,𖹩=𖹉,𖹪=𖹊,𖹫=𖹋,𖹬=𖹌,𖹭=𖹍,𖹮=𖹎,𖹯=𖹏,𖹰=𖹐,𖹱=𖹑,𖹲=𖹒,𖹳=𖹓,𖹴=𖹔,𖹵=𖹕,𖹶=𖹖,𖹷=𖹗,𖹸=𖹘,𖹹=𖹙,𖹺=𖹚,𖹻=𖹛,𖹼=𖹜,𖹽=𖹝,𖹾=𖹞,𖹿=𖹟
|
||||
𞤢=𞤀,𞤣=𞤁,𞤤=𞤂,𞤥=𞤃,𞤦=𞤄,𞤧=𞤅,𞤨=𞤆,𞤩=𞤇,𞤪=𞤈,𞤫=𞤉,𞤬=𞤊,𞤭=𞤋,𞤮=𞤌,𞤯=𞤍,𞤰=𞤎,𞤱=𞤏,𞤲=𞤐,𞤳=𞤑,𞤴=𞤒,𞤵=𞤓,𞤶=𞤔,𞤷=𞤕,𞤸=𞤖,𞤹=𞤗,𞤺=𞤘,𞤻=𞤙,𞤼=𞤚,𞤽=𞤛,𞤾=𞤜,𞤿=𞤝,𞥀=𞤞,𞥁=𞤟,𞥂=𞤠,𞥃=𞤡
|
||||
i̇=İ,ʼn=ʼN,ǰ=J̌,ΐ=Ϊ́,ΰ=Ϋ́,և=ԵՒ,ẖ=H̱,ẗ=T̈,ẘ=W̊,ẙ=Y̊,ẚ=Aʾ,ὐ=Υ̓,ὒ=Υ̓̀,ὔ=Υ̓́,ὖ=Υ̓͂,ᾀ=ἈΙ,ᾁ=ἉΙ,ᾂ=ἊΙ,ᾃ=ἋΙ,ᾄ=ἌΙ,ᾅ=ἍΙ,ᾆ=ἎΙ,ᾇ=ἏΙ,ᾐ=ἨΙ,ᾑ=ἩΙ,ᾒ=ἪΙ,ᾓ=ἫΙ,ᾔ=ἬΙ,ᾕ=ἭΙ,ᾖ=ἮΙ,ᾗ=ἯΙ,ᾠ=ὨΙ,ᾡ=ὩΙ,ᾢ=ὪΙ,ᾣ=ὫΙ,ᾤ=ὬΙ,ᾥ=ὭΙ,ᾦ=ὮΙ,ᾧ=ὯΙ,ᾲ=ᾺΙ,ᾳ=ΑΙ,ᾴ=ΆΙ,ᾶ=Α͂,ᾷ=Α͂Ι,ῂ=ῊΙ,ῃ=ΗΙ,ῄ=ΉΙ,ῆ=Η͂,ῇ=Η͂Ι,ῒ=Ϊ̀,ῖ=Ι͂,ῗ=Ϊ͂,ῢ=Ϋ̀,ῤ=Ρ̓,ῦ=Υ͂,ῧ=Ϋ͂,ῲ=ῺΙ,ῳ=ΩΙ,ῴ=ΏΙ,ῶ=Ω͂,ῷ=Ω͂Ι,ﬓ=ՄՆ,ﬔ=ՄԵ,ﬕ=ՄԻ,ﬖ=ՎՆ,ﬗ=ՄԽ
|
||||
12
Zframework/vibrate.lua
Normal file
12
Zframework/vibrate.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
local level={0,0,.01,.016,.023,.03,.04,.05,.06,.07,.08,.09,.12,.15}
|
||||
local vib=love.system.vibrate
|
||||
return SYSTEM=='iOS' and
|
||||
function(t)
|
||||
t=level[t]
|
||||
if t then vib(t<=.03 and 1 or t<=.09 and 2 or 3) end
|
||||
end
|
||||
or
|
||||
function(t)
|
||||
t=level[t]
|
||||
if t then vib(t) end
|
||||
end
|
||||
144
Zframework/voice.lua
Normal file
144
Zframework/voice.lua
Normal file
@@ -0,0 +1,144 @@
|
||||
local rnd=math.random
|
||||
local volume=1
|
||||
local diversion=0
|
||||
local voiceQueue={free=0}
|
||||
local VOC={
|
||||
getCount=function() return 0 end,
|
||||
getQueueCount=function() return 0 end,
|
||||
load=function() error("Cannot load before init!") end,
|
||||
getFreeChannel=NULL,
|
||||
play=NULL,
|
||||
update=NULL,
|
||||
}
|
||||
function VOC.setDiversion(n)
|
||||
assert(type(n)=='number' and n>0 and n<12,'Wrong div')
|
||||
diversion=n
|
||||
end
|
||||
function VOC.setVol(v)
|
||||
assert(type(v)=='number' and v>=0 and v<=1,'Wrong volume')
|
||||
volume=v
|
||||
for i=1,#voiceQueue do
|
||||
local Q=voiceQueue[i]
|
||||
for j=1,#Q do
|
||||
local s=Q[j]
|
||||
if type(s)=='userdata' then
|
||||
s:setVolume(volume)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function VOC.init(list)
|
||||
VOC.init=nil
|
||||
local rem=table.remove
|
||||
local bank={}-- {vocName1={SRC1s},vocName2={SRC2s},...}
|
||||
local Source={}
|
||||
|
||||
local count=#list function VOC.getCount() return count end
|
||||
local function _loadVoiceFile(path,N,vocName)
|
||||
local fullPath=path..vocName..'.ogg'
|
||||
if love.filesystem.getInfo(fullPath) then
|
||||
bank[vocName]={love.audio.newSource(fullPath,'stream')}
|
||||
table.insert(Source[N],vocName)
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- Load voice with string
|
||||
local function _getVoice(str)
|
||||
local L=bank[str]
|
||||
local n=1
|
||||
while L[n]:isPlaying() do
|
||||
n=n+1
|
||||
if not L[n] then
|
||||
L[n]=L[1]:clone()
|
||||
L[n]:seek(0)
|
||||
break
|
||||
end
|
||||
end
|
||||
return L[n]
|
||||
end
|
||||
function VOC.load(path)
|
||||
for i=1,count do
|
||||
Source[list[i]]={}
|
||||
|
||||
local n=0
|
||||
repeat n=n+1 until not _loadVoiceFile(path,list[i],list[i]..'_'..n)
|
||||
|
||||
if n==1 then
|
||||
if not _loadVoiceFile(path,list[i],list[i]) then
|
||||
LOG("No VOC: "..list[i],.1)
|
||||
end
|
||||
end
|
||||
if not Source[list[i]][1] then
|
||||
Source[list[i]]=nil
|
||||
end
|
||||
end
|
||||
|
||||
function VOC.getQueueCount()
|
||||
return #voiceQueue
|
||||
end
|
||||
function VOC.getQueueLength(chn)
|
||||
return voiceQueue[chn] and #voiceQueue[chn]
|
||||
end
|
||||
function VOC.getFreeChannel()
|
||||
local l=#voiceQueue
|
||||
for i=1,l do
|
||||
if #voiceQueue[i]==0 then return i end
|
||||
end
|
||||
voiceQueue[l+1]={s=0}
|
||||
return l+1
|
||||
end
|
||||
|
||||
function VOC.play(s,chn)
|
||||
if volume>0 then
|
||||
local _=Source[s]
|
||||
if not _ then return end
|
||||
if chn then
|
||||
local L=voiceQueue[chn]
|
||||
L[#L+1]=_[rnd(#_)]
|
||||
L.s=1
|
||||
-- Add to queue[chn]
|
||||
else
|
||||
voiceQueue[VOC.getFreeChannel()]={s=1,_[rnd(#_)]}
|
||||
-- Create new channel & play
|
||||
end
|
||||
end
|
||||
end
|
||||
function VOC.update()
|
||||
for i=#voiceQueue,1,-1 do
|
||||
local Q=voiceQueue[i]
|
||||
if Q.s==0 then-- Free channel, auto delete when >3
|
||||
if i>3 then
|
||||
rem(voiceQueue,i)
|
||||
end
|
||||
elseif Q.s==1 then-- Waiting load source
|
||||
Q[1]=_getVoice(Q[1])
|
||||
Q[1]:setVolume(volume)
|
||||
Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1)))
|
||||
Q[1]:play()
|
||||
Q.s=Q[2] and 2 or 4
|
||||
elseif Q.s==2 then-- Playing 1,ready 2
|
||||
if Q[1]:getDuration()-Q[1]:tell()<.08 then
|
||||
Q[2]=_getVoice(Q[2])
|
||||
Q[2]:setVolume(volume)
|
||||
Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1)))
|
||||
Q[2]:play()
|
||||
Q.s=3
|
||||
end
|
||||
elseif Q.s==3 then-- Playing 12 same time
|
||||
if not Q[1]:isPlaying() then
|
||||
for j=1,#Q do
|
||||
Q[j]=Q[j+1]
|
||||
end
|
||||
Q.s=Q[2] and 2 or 4
|
||||
end
|
||||
elseif Q.s==4 then-- Playing last
|
||||
if not Q[1].isPlaying(Q[1]) then
|
||||
Q[1]=nil
|
||||
Q.s=0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return VOC
|
||||
128
Zframework/wait.lua
Normal file
128
Zframework/wait.lua
Normal file
@@ -0,0 +1,128 @@
|
||||
local WAIT={
|
||||
state=false,
|
||||
timer=false,
|
||||
totalTimer=false,
|
||||
|
||||
enterTime=.2,
|
||||
leaveTime=.2,
|
||||
timeout=6,
|
||||
coverColor={.1,.1,.1},
|
||||
coverAlpha=.6,
|
||||
|
||||
arg=false,
|
||||
}
|
||||
|
||||
local arcAlpha={1,.6,.4,.3}
|
||||
local function defaultDraw(a,t)
|
||||
GC.setLineWidth(SCR.h/26)
|
||||
t=t*2.6
|
||||
for i=1,4 do
|
||||
GC.setColor(1,1,1,a*arcAlpha[i])
|
||||
GC.arc('line','open',SCR.w/2,SCR.h/2,SCR.h/5,t+MATH.tau*(i/4),t+MATH.tau*((i+1)/4))
|
||||
end
|
||||
end
|
||||
|
||||
function WAIT.new(arg)
|
||||
if WAIT.state then return end
|
||||
|
||||
assert(type(arg)=='table',"arg must be table")
|
||||
assert(arg.init==nil or type(arg.init) =='function',"Field 'enter' must be function")
|
||||
assert(arg.update==nil or type(arg.update) =='function',"Field 'update' must be function")
|
||||
assert(arg.quit==nil or type(arg.quit) =='function',"Field 'leave' must be function")
|
||||
assert(arg.draw==nil or type(arg.draw) =='function',"Field 'draw' must be function")
|
||||
assert(arg.escapable==nil or type(arg.escapable) =='boolean', "Field 'escapable' must be boolean")
|
||||
if arg.init then arg.init() end
|
||||
|
||||
WAIT.arg=arg
|
||||
WAIT.state='enter'
|
||||
WAIT.timer=0
|
||||
WAIT.totalTimer=0
|
||||
end
|
||||
|
||||
function WAIT.interrupt()
|
||||
if WAIT.state and WAIT.state~='leave' then
|
||||
WAIT.state='leave'
|
||||
WAIT.timer=WAIT.leaveTime*WAIT.timer/WAIT.enterTime
|
||||
end
|
||||
end
|
||||
|
||||
function WAIT.update(dt)
|
||||
if WAIT.state then
|
||||
WAIT.totalTimer=WAIT.totalTimer+dt
|
||||
if WAIT.arg.update then WAIT.arg.update(dt) end
|
||||
|
||||
if WAIT.state~='leave' and WAIT.totalTimer>=(WAIT.arg.timeout or WAIT.timeout) then
|
||||
WAIT.interrupt()
|
||||
end
|
||||
|
||||
if WAIT.state=='enter' then
|
||||
WAIT.timer=math.min(WAIT.timer+dt,WAIT.enterTime)
|
||||
if WAIT.timer>=WAIT.enterTime then WAIT.state='wait' end
|
||||
elseif WAIT.state=='leave' then
|
||||
WAIT.timer=WAIT.timer-dt
|
||||
if WAIT.timer<=0 then
|
||||
WAIT.state=false
|
||||
if WAIT.arg.quit then WAIT.arg.quit() end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function WAIT.draw()
|
||||
if WAIT.state then
|
||||
local alpha=(
|
||||
WAIT.state=='enter' and WAIT.timer/WAIT.enterTime or
|
||||
WAIT.state=='wait' and 1 or
|
||||
WAIT.state=='leave' and WAIT.timer/WAIT.leaveTime
|
||||
)
|
||||
GC.setColor(
|
||||
WAIT.coverColor[1],
|
||||
WAIT.coverColor[2],
|
||||
WAIT.coverColor[3],
|
||||
alpha*WAIT.coverAlpha
|
||||
)
|
||||
GC.rectangle('fill',0,0,SCR.w,SCR.h);
|
||||
|
||||
(WAIT.arg.draw or defaultDraw)(alpha,WAIT.totalTimer)
|
||||
end
|
||||
end
|
||||
|
||||
function WAIT.setEnterTime(t)
|
||||
assert(type(t)=='number' and t>0,"Arg #1 must be number larger then 0")
|
||||
WAIT.enterTime=t
|
||||
end
|
||||
function WAIT.setLeaveTime(t)
|
||||
assert(type(t)=='number' and t>0,"Arg #1 must be number larger then 0")
|
||||
WAIT.leaveTime=t
|
||||
end
|
||||
function WAIT.setTimeout(t)
|
||||
assert(type(t)=='number' and t>0,"Arg #1 must be number larger then 0")
|
||||
WAIT.timeout=t
|
||||
end
|
||||
function WAIT.setCoverColor(r,g,b)
|
||||
if type(r)=='table' then
|
||||
r,g,b=r[1],r[2],r[3]
|
||||
end
|
||||
if
|
||||
type(r)=='number' and r>=0 and r<=1 and
|
||||
type(g)=='number' and g>=0 and g<=1 and
|
||||
type(b)=='number' and b>=0 and b<=1
|
||||
then
|
||||
WAIT.coverColor[1],WAIT.coverColor[2],WAIT.coverColor[3]=r,g,b
|
||||
else
|
||||
error("Arg must be r,g,b or {r,g,b}")
|
||||
end
|
||||
end
|
||||
function WAIT.setCoverAlpha(a)
|
||||
assert(type(a)=='number',"Arg #1 must be number between 0~1")
|
||||
end
|
||||
function WAIT.setDefaultDraw(f)
|
||||
assert(type(f)=='function',"Arg #1 must be function")
|
||||
defaultDraw=f
|
||||
end
|
||||
|
||||
setmetatable(WAIT,{__call=function(self,arg)
|
||||
self.new(arg)
|
||||
end,__metatable=true})
|
||||
|
||||
return WAIT
|
||||
194
Zframework/websocket.lua
Normal file
194
Zframework/websocket.lua
Normal file
@@ -0,0 +1,194 @@
|
||||
local host='127.0.0.1'
|
||||
local port='80'
|
||||
local path=''
|
||||
|
||||
-- lua + LÖVE threading websocket client
|
||||
-- Original pure lua ver. by flaribbit and Particle_G
|
||||
-- Threading version by MrZ
|
||||
|
||||
local type=type
|
||||
local timer=love.timer.getTime
|
||||
local TRD=love.thread.newThread("\n")
|
||||
local TRD_isRunning=TRD.isRunning
|
||||
|
||||
local WS={}
|
||||
local wsList=setmetatable({},{
|
||||
__index=function(l,k)
|
||||
local ws={
|
||||
real=false,
|
||||
status='dead',
|
||||
lastPongTime=timer(),
|
||||
sendTimer=0,
|
||||
alertTimer=0,
|
||||
pongTimer=0,
|
||||
}
|
||||
l[k]=ws
|
||||
return ws
|
||||
end
|
||||
})
|
||||
|
||||
function WS.switchHost(_1,_2,_3)
|
||||
for k in next,wsList do
|
||||
WS.close(k)
|
||||
end
|
||||
host=_1
|
||||
port=_2 or port
|
||||
path=_3 or path
|
||||
end
|
||||
|
||||
function WS.connect(name,subPath,head,timeout)
|
||||
if head then
|
||||
local l=""
|
||||
for k,v in next,head do
|
||||
l=l..(k..": "..v..'\r\n')
|
||||
end
|
||||
head=l
|
||||
else
|
||||
head=""
|
||||
end
|
||||
if wsList[name] and wsList[name].thread then
|
||||
wsList[name].thread:release()
|
||||
end
|
||||
local ws={
|
||||
real=true,
|
||||
thread=love.thread.newThread('Zframework/websocket_thread.lua'),
|
||||
triggerCHN=love.thread.newChannel(),
|
||||
sendCHN=love.thread.newChannel(),
|
||||
readCHN=love.thread.newChannel(),
|
||||
lastPingTime=0,
|
||||
lastPongTime=timer(),
|
||||
pingInterval=6,
|
||||
status='connecting',-- 'connecting', 'running', 'dead'
|
||||
sendTimer=0,
|
||||
alertTimer=0,
|
||||
pongTimer=0,
|
||||
}
|
||||
wsList[name]=ws
|
||||
ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN)
|
||||
ws.sendCHN:push(host)
|
||||
ws.sendCHN:push(port)
|
||||
ws.sendCHN:push(path..subPath)
|
||||
ws.sendCHN:push(head)
|
||||
ws.sendCHN:push(timeout or 2.6)
|
||||
end
|
||||
|
||||
function WS.status(name)
|
||||
local ws=wsList[name]
|
||||
return ws.status or 'dead'
|
||||
end
|
||||
|
||||
function WS.getTimers(name)
|
||||
local ws=wsList[name]
|
||||
return ws.pongTimer,ws.sendTimer,ws.alertTimer
|
||||
end
|
||||
|
||||
function WS.setPingInterval(name,time)
|
||||
local ws=wsList[name]
|
||||
ws.pingInterval=math.max(time or 2.6,2.6)
|
||||
end
|
||||
|
||||
function WS.alert(name)
|
||||
local ws=wsList[name]
|
||||
ws.alertTimer=2.6
|
||||
end
|
||||
|
||||
local OPcode={
|
||||
continue=0,
|
||||
text=1,
|
||||
binary=2,
|
||||
close=8,
|
||||
ping=9,
|
||||
pong=10,
|
||||
}
|
||||
local OPname={
|
||||
[0]='continue',
|
||||
[1]='text',
|
||||
[2]='binary',
|
||||
[8]='close',
|
||||
[9]='ping',
|
||||
[10]='pong',
|
||||
}
|
||||
function WS.send(name,message,op)
|
||||
if type(message)=='string' then
|
||||
local ws=wsList[name]
|
||||
if ws.real and ws.status=='running' then
|
||||
ws.sendCHN:push(op and OPcode[op] or 2)-- 2=binary
|
||||
ws.sendCHN:push(message)
|
||||
ws.lastPingTime=timer()
|
||||
ws.sendTimer=1
|
||||
end
|
||||
else
|
||||
MES.new('error',"Attempt to send non-string value!")
|
||||
MES.traceback()
|
||||
end
|
||||
end
|
||||
|
||||
function WS.read(name)
|
||||
local ws=wsList[name]
|
||||
if ws.real and ws.status~='connecting' and ws.readCHN:getCount()>=2 then
|
||||
local op,message=ws.readCHN:pop(),ws.readCHN:pop()
|
||||
if op==8 then-- 8=close
|
||||
ws.status='dead'
|
||||
elseif op==9 then-- 9=ping
|
||||
WS.send(name,message or "",'pong')
|
||||
end
|
||||
ws.lastPongTime=timer()
|
||||
ws.pongTimer=1
|
||||
return message,OPname[op] or op
|
||||
end
|
||||
end
|
||||
|
||||
function WS.close(name)
|
||||
local ws=wsList[name]
|
||||
if ws.real then
|
||||
ws.sendCHN:push(8)-- 8=close
|
||||
ws.sendCHN:push("")
|
||||
ws.status='dead'
|
||||
end
|
||||
end
|
||||
|
||||
function WS.update(dt)
|
||||
local time=timer()
|
||||
for name,ws in next,wsList do
|
||||
if ws.real and ws.status~='dead' then
|
||||
if TRD_isRunning(ws.thread) then
|
||||
if ws.triggerCHN:getCount()==0 then
|
||||
ws.triggerCHN:push(0)
|
||||
end
|
||||
if ws.status=='connecting' then
|
||||
local mes=ws.readCHN:pop()
|
||||
if mes then
|
||||
if mes=='success' then
|
||||
ws.status='running'
|
||||
ws.lastPingTime=time
|
||||
ws.lastPongTime=time
|
||||
ws.pongTimer=1
|
||||
else
|
||||
ws.status='dead'
|
||||
MES.new('warn',text.wsFailed:repD(mes))
|
||||
end
|
||||
end
|
||||
elseif ws.status=='running' then
|
||||
if time-ws.lastPingTime>ws.pingInterval then
|
||||
WS.send(name,"",'pong')
|
||||
end
|
||||
if time-ws.lastPongTime>6+2*ws.pingInterval then
|
||||
WS.close(name)
|
||||
end
|
||||
end
|
||||
if ws.sendTimer>0 then ws.sendTimer=ws.sendTimer-dt end
|
||||
if ws.pongTimer>0 then ws.pongTimer=ws.pongTimer-dt end
|
||||
if ws.alertTimer>0 then ws.alertTimer=ws.alertTimer-dt end
|
||||
else
|
||||
ws.status='dead'
|
||||
local err=ws.thread:getError()
|
||||
if err then
|
||||
MES.new('warn',text.wsClose:repD(err:match(":.-:(.-)\n")))
|
||||
WS.alert(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return WS
|
||||
189
Zframework/websocket_thread.lua
Normal file
189
Zframework/websocket_thread.lua
Normal file
@@ -0,0 +1,189 @@
|
||||
local triggerCHN,sendCHN,readCHN=...
|
||||
|
||||
local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount
|
||||
local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop
|
||||
|
||||
local SOCK=require'socket'.tcp()
|
||||
local JSON=require'Zframework.json'
|
||||
|
||||
do-- Connect
|
||||
local host=CHN_demand(sendCHN)
|
||||
local port=CHN_demand(sendCHN)
|
||||
local path=CHN_demand(sendCHN)
|
||||
local head=CHN_demand(sendCHN)
|
||||
local timeout=CHN_demand(sendCHN)
|
||||
|
||||
SOCK:settimeout(timeout)
|
||||
local res,err=SOCK:connect(host,port)
|
||||
assert(res,err)
|
||||
|
||||
-- WebSocket handshake
|
||||
SOCK:send(
|
||||
'GET '..path..' HTTP/1.1\r\n'..
|
||||
'Host: '..host..':'..port..'\r\n'..
|
||||
'Connection: Upgrade\r\n'..
|
||||
'Upgrade: websocket\r\n'..
|
||||
'Sec-WebSocket-Version: 13\r\n'..
|
||||
'Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n'..-- secKey
|
||||
head..
|
||||
'\r\n'
|
||||
)
|
||||
|
||||
-- First line of HTTP
|
||||
res,err=SOCK:receive('*l')
|
||||
assert(res,err)
|
||||
local code,ctLen
|
||||
code=res:find(' ')
|
||||
code=res:sub(code+1,code+3)
|
||||
|
||||
-- Get body length from headers and remove headers
|
||||
repeat
|
||||
res,err=SOCK:receive('*l')
|
||||
assert(res,err)
|
||||
if not ctLen and res:find('length') then
|
||||
ctLen=tonumber(res:match('%d+'))
|
||||
end
|
||||
until res==''
|
||||
|
||||
-- Result
|
||||
if ctLen then
|
||||
if code=='101' then
|
||||
CHN_push(readCHN,'success')
|
||||
else
|
||||
res,err=SOCK:receive(ctLen)
|
||||
res=JSON.decode(assert(res,err))
|
||||
error((code or "XXX")..":"..(res and res.reason or "Server Error"))
|
||||
end
|
||||
end
|
||||
SOCK:settimeout(0)
|
||||
end
|
||||
|
||||
local yield=coroutine.yield
|
||||
local byte,char=string.byte,string.char
|
||||
local band,bor,bxor=bit.band,bit.bor,bit.bxor
|
||||
local shl,shr=bit.lshift,bit.rshift
|
||||
|
||||
local mask_key={1,14,5,14}
|
||||
local mask_str=char(unpack(mask_key))
|
||||
local function _send(op,message)
|
||||
-- Message type
|
||||
SOCK:send(char(bor(op,0x80)))
|
||||
|
||||
if message then
|
||||
-- Length
|
||||
local length=#message
|
||||
if length>65535 then
|
||||
SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff)))
|
||||
elseif length>125 then
|
||||
SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff)))
|
||||
else
|
||||
SOCK:send(char(bor(length,0x80)))
|
||||
end
|
||||
local msgbyte={byte(message,1,length)}
|
||||
for i=1,length do
|
||||
msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1])
|
||||
end
|
||||
return SOCK:send(mask_str..char(unpack(msgbyte)))
|
||||
else
|
||||
SOCK:send('\128'..mask_str)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
local sendThread=coroutine.wrap(function()
|
||||
while true do
|
||||
while CHN_getCount(sendCHN)>=2 do
|
||||
_send(CHN_pop(sendCHN),CHN_pop(sendCHN))
|
||||
end
|
||||
yield()
|
||||
end
|
||||
end)
|
||||
|
||||
local function _receive(sock,len)
|
||||
local buffer=""
|
||||
while true do
|
||||
local r,e,p=sock:receive(len)
|
||||
if r then
|
||||
buffer=buffer..r
|
||||
len=len-#r
|
||||
elseif p then
|
||||
buffer=buffer..p
|
||||
len=len-#p
|
||||
elseif e then
|
||||
return nil,e
|
||||
end
|
||||
if len==0 then
|
||||
return buffer
|
||||
end
|
||||
yield()
|
||||
end
|
||||
end
|
||||
local readThread=coroutine.wrap(function()
|
||||
local res,err
|
||||
local op,fin
|
||||
local lBuffer=""-- Long multi-pack buffer
|
||||
while true do
|
||||
-- Byte 0-1
|
||||
res,err=_receive(SOCK,2)
|
||||
assert(res,err)
|
||||
|
||||
op=band(byte(res,1),0x0f)
|
||||
fin=band(byte(res,1),0x80)==0x80
|
||||
|
||||
-- Calculating data length
|
||||
local length=band(byte(res,2),0x7f)
|
||||
if length==126 then
|
||||
res,err=_receive(SOCK,2)
|
||||
assert(res,err)
|
||||
length=shl(byte(res,1),8)+byte(res,2)
|
||||
elseif length==127 then
|
||||
local lenData
|
||||
lenData,err=_receive(SOCK,8)
|
||||
assert(res,err)
|
||||
local _,_,_,_,_5,_6,_7,_8=byte(lenData,1,8)
|
||||
length=shl(_5,24)+shl(_6,16)+shl(_7,8)+_8
|
||||
end
|
||||
res,err=_receive(SOCK,length)
|
||||
assert(res,err)
|
||||
|
||||
-- React
|
||||
if op==8 then-- 8=close
|
||||
CHN_push(readCHN,8)-- close
|
||||
if type(res)=='string' then
|
||||
CHN_push(readCHN,res:sub(3))--[Warning] 2 bytes close code at start so :sub(3)
|
||||
else
|
||||
CHN_push(readCHN,"WS closed")
|
||||
end
|
||||
return
|
||||
elseif op==0 then-- 0=continue
|
||||
lBuffer=lBuffer..res
|
||||
if fin then
|
||||
CHN_push(readCHN,lBuffer)
|
||||
lBuffer=""
|
||||
end
|
||||
else
|
||||
CHN_push(readCHN,op)
|
||||
if fin then
|
||||
CHN_push(readCHN,res)
|
||||
lBuffer=""
|
||||
else
|
||||
lBuffer=res
|
||||
end
|
||||
end
|
||||
yield()
|
||||
end
|
||||
end)
|
||||
|
||||
local success,err
|
||||
|
||||
while true do-- Running
|
||||
CHN_demand(triggerCHN)
|
||||
success,err=pcall(sendThread)
|
||||
if not success or err then break end
|
||||
success,err=pcall(readThread)
|
||||
if not success or err then break end
|
||||
end
|
||||
|
||||
SOCK:close()
|
||||
CHN_push(readCHN,8)-- close
|
||||
CHN_push(readCHN,err or "Disconnected")
|
||||
error()
|
||||
19
Zframework/wheelScroll.lua
Normal file
19
Zframework/wheelScroll.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
local love=love
|
||||
local max,min=math.max,math.min
|
||||
local trigDist=0
|
||||
return function(y,key1,key2)
|
||||
if y>0 then
|
||||
trigDist=max(trigDist,0)+y^1.2
|
||||
elseif y<0 then
|
||||
if trigDist>0 then trigDist=0 end
|
||||
trigDist=min(trigDist,0)-(-y)^1.2
|
||||
end
|
||||
while trigDist>=1 do
|
||||
love.keypressed(key1 or 'up')
|
||||
trigDist=trigDist-1
|
||||
end
|
||||
while trigDist<=-1 do
|
||||
love.keypressed(key2 or 'down')
|
||||
trigDist=trigDist+1
|
||||
end
|
||||
end
|
||||
1525
Zframework/widget.lua
Normal file
1525
Zframework/widget.lua
Normal file
File diff suppressed because it is too large
Load Diff
10
conf.lua
10
conf.lua
@@ -1,9 +1,9 @@
|
||||
SYSTEM=love._os
|
||||
if SYSTEM=='OS X' then SYSTEM='macOS' end
|
||||
MOBILE=SYSTEM=='Android' or SYSTEM=='iOS'
|
||||
FNNS=SYSTEM:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
|
||||
local OS=love._os
|
||||
if OS=='OS X' then OS='macOS' end
|
||||
MOBILE=OS=='Android' or OS=='iOS'
|
||||
FNNS=OS:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
|
||||
|
||||
if SYSTEM=='Web' then
|
||||
if OS=='Web' then
|
||||
local oldRead=love.filesystem.read
|
||||
function love.filesystem.read(name,size)
|
||||
if love.filesystem.getInfo(name) then
|
||||
|
||||
41
main.lua
41
main.lua
@@ -50,14 +50,11 @@ BGM.setMaxSources(5)
|
||||
VOC.setDiversion(.62)
|
||||
|
||||
WIDGET.setOnChange(function()
|
||||
if SCN.cur~='net_game' and SCN.cur~='custom_field' then
|
||||
local colorList=THEME.getThemeColor()
|
||||
if colorList then
|
||||
for _,W in next,SCN.scenes[SCN.cur].widgetList do
|
||||
if W.color then
|
||||
W.color=colorList[math.random(#colorList)]
|
||||
end
|
||||
end
|
||||
if SCN.cur=='net_game' or SCN.cur=='custom_field' then return end
|
||||
local colorList=THEME.getThemeColor()
|
||||
if colorList then
|
||||
for _,W in next,SCN.scenes[SCN.cur].widgetList do
|
||||
W.color=W.color and colorList[math.random(#colorList)]
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -191,7 +188,7 @@ Z.setOnFnKeys({
|
||||
Z.setOnGlobalKey('f11',function()
|
||||
if not MOBILE then
|
||||
SETTING.fullscreen=not SETTING.fullscreen
|
||||
applySettings()
|
||||
applySettings('fullscreen')
|
||||
saveSettings()
|
||||
end
|
||||
end)
|
||||
@@ -376,30 +373,6 @@ then
|
||||
MES.new('error',"An error occured during loading, and some data was lost.")
|
||||
end
|
||||
|
||||
-- Initialize fields, sequence, missions, gameEnv for cutsom game
|
||||
local fieldData=loadFile('conf/customBoards','-string -canSkip')
|
||||
if fieldData then
|
||||
fieldData=STRING.split(fieldData,"!")
|
||||
for i=1,#fieldData do
|
||||
DATA.pasteBoard(fieldData[i],i)
|
||||
end
|
||||
else
|
||||
FIELD[1]=DATA.newBoard()
|
||||
end
|
||||
local sequenceData=loadFile('conf/customSequence','-string -canSkip')
|
||||
if sequenceData then
|
||||
DATA.pasteSequence(sequenceData)
|
||||
end
|
||||
local missionData=loadFile('conf/customMissions','-string -canSkip')
|
||||
if missionData then
|
||||
DATA.pasteMission(missionData)
|
||||
end
|
||||
local customData=loadFile('conf/customEnv','-canSkip')
|
||||
if customData and customData['version']==VERSION.code then
|
||||
TABLE.complete(customData,CUSTOMENV)
|
||||
end
|
||||
TABLE.complete(require"parts.customEnv0",CUSTOMENV)
|
||||
|
||||
-- Update data
|
||||
do
|
||||
if type(STAT.version)~='number' then
|
||||
@@ -426,6 +399,7 @@ do
|
||||
end
|
||||
if RANKS.bigbang then fs.remove('record/bigbang.rec') end
|
||||
if RANKS.clearRush then fs.remove('record/clearRush.rec') end
|
||||
if STAT.version<1715 then fs.remove('record/dig_quad_10l.rec') end
|
||||
|
||||
if STAT.version~=VERSION.code then
|
||||
for k,v in next,MODE_UPDATE_MAP do
|
||||
@@ -463,6 +437,7 @@ do
|
||||
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
|
||||
if RANKS.master_l then RANKS.master_n,RANKS.master_l=RANKS.master_l end
|
||||
if RANKS.master_u then RANKS.master_h,RANKS.master_u=RANKS.master_u end
|
||||
if RANKS.secret_grade then RANKS.construct_sg,RANKS.secret_grade=RANKS.secret_grade end
|
||||
for _,v in next,VK_ORG do v.color=nil end
|
||||
for name,rank in next,RANKS do
|
||||
if type(name)=='number' or type(rank)~='number' then
|
||||
|
||||
BIN
media/effect/chiptune/mod_off.ogg
Normal file
BIN
media/effect/chiptune/mod_off.ogg
Normal file
Binary file not shown.
BIN
media/effect/chiptune/mod_on.ogg
Normal file
BIN
media/effect/chiptune/mod_on.ogg
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 5.4 KiB |
2
media/image/modeicon/note.txt
Normal file
2
media/image/modeicon/note.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
If the modeicon you're looking for isn't here, try looking in /parts/scenes/load.lua.
|
||||
We vectorized some of them for better scalability.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 489 B |
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 801 B |
Binary file not shown.
|
Before Width: | Height: | Size: 395 B |
@@ -170,7 +170,7 @@ do
|
||||
},-- T
|
||||
function(P,d)
|
||||
if P.gameEnv.easyFresh then
|
||||
P:freshBlock('fresh')
|
||||
P:freshBlockDelay()
|
||||
end
|
||||
if P.gameEnv.ospin then
|
||||
local x,y=P.curX,P.curY
|
||||
@@ -203,7 +203,7 @@ do
|
||||
C.dir=dir
|
||||
P.spinLast=2
|
||||
P.stat.rotate=P.stat.rotate+1
|
||||
P:freshBlock('move')
|
||||
P:freshMoveBlock()
|
||||
C.spinSeq=nil
|
||||
return
|
||||
end
|
||||
@@ -328,23 +328,20 @@ do
|
||||
[13]={'+0+0','+0+1','-1+0'},
|
||||
[31]={'+0+0','+0-1','+1+0'},
|
||||
},-- W
|
||||
function(P,d)
|
||||
if P.type=='human' then
|
||||
SFX.play('rotate',nil,P:getCenterX()*.15)
|
||||
end
|
||||
local kickData=XspinList[d]
|
||||
for test=1,#kickData do
|
||||
local x,y=P.curX+kickData[test][1],P.curY+kickData[test][2]
|
||||
if not P:ifoverlap(P.cur.bk,x,y) then
|
||||
P.curX,P.curY=x,y
|
||||
P.spinLast=1
|
||||
P:freshBlock('move')
|
||||
P.stat.rotate=P.stat.rotate+1
|
||||
return
|
||||
end
|
||||
end
|
||||
P:freshBlock('fresh')
|
||||
end,-- X
|
||||
{
|
||||
[01]=XspinList[1],
|
||||
[12]=XspinList[1],
|
||||
[23]=XspinList[1],
|
||||
[30]=XspinList[1],
|
||||
[02]=XspinList[2],
|
||||
[13]=XspinList[2],
|
||||
[20]=XspinList[2],
|
||||
[31]=XspinList[2],
|
||||
[03]=XspinList[3],
|
||||
[10]=XspinList[3],
|
||||
[21]=XspinList[3],
|
||||
[32]=XspinList[3],
|
||||
},-- X
|
||||
{
|
||||
[01]={'+0+0','-1+0','-1+1','+0-3','-1+1','-1+2','+0+1'},
|
||||
[10]={'+0+0','-1+0','+1-1','+0+3','+1-1','+1-2','+0+1'},
|
||||
@@ -592,7 +589,7 @@ do
|
||||
local F=_strToVec{'+0+0','+0-1','+0+1','+0+2'}
|
||||
local list={
|
||||
{[02]=L,[20]=R,[13]=R,[31]=L},-- Z
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- S
|
||||
{[02]=R,[20]=L,[13]=R,[31]=L},-- S
|
||||
{[02]=L,[20]=R,[13]=L,[31]=R},-- J
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- L
|
||||
{[02]=F,[20]=F,[13]=L,[31]=R},-- T
|
||||
@@ -602,20 +599,20 @@ do
|
||||
{[02]=L,[20]=L,[13]=R,[31]=R},-- Z5
|
||||
{[02]=R,[20]=R,[13]=L,[31]=L},-- S5
|
||||
{[02]=L,[20]=R,[13]=L,[31]=R},-- P
|
||||
{[02]=R,[20]=L,[13]=R,[31]=L},-- Q
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- F
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- Q
|
||||
{[02]=R,[20]=L,[13]=R,[31]=L},-- F
|
||||
{[02]=L,[20]=R,[13]=R,[31]=L},-- E
|
||||
{[02]=F,[20]=F,[13]=L,[31]=R},-- T5
|
||||
{[02]=F,[20]=F,[13]=L,[31]=R},-- U
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- V
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- W
|
||||
{},-- W
|
||||
{[02]=F,[20]=F,[13]=F,[31]=F},-- X
|
||||
{[02]=L,[20]=R,[13]=R,[31]=L},-- J5
|
||||
{[02]=L,[20]=R,[13]=L,[31]=R},-- J5
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- L5
|
||||
{[02]=L,[20]=R,[13]=R,[31]=L},-- R
|
||||
{[02]=L,[20]=R,[13]=L,[31]=R},-- R
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- Y
|
||||
{[02]=L,[20]=R,[13]=R,[31]=L},-- N
|
||||
{[02]=R,[20]=L,[13]=L,[31]=R},-- H
|
||||
{[02]=R,[20]=L,[13]=R,[31]=L},-- H
|
||||
{[02]=F,[20]=F,[13]=F,[31]=F},-- I5
|
||||
|
||||
{[02]=F,[20]=F,[13]=F,[31]=F},-- I3
|
||||
@@ -631,6 +628,14 @@ do
|
||||
list[i][01]=a; list[i][10]=b; list[i][03]=b; list[i][30]=a
|
||||
list[i][12]=a; list[i][21]=b; list[i][32]=b; list[i][23]=a
|
||||
end
|
||||
list[17]={ -- Fix W
|
||||
[01]=L,[32]=R,
|
||||
[03]=L,[30]=R,
|
||||
[10]=R,[23]=L,
|
||||
[12]=L,[21]=R,
|
||||
[02]=R,[20]=L,
|
||||
[31]=L,[13]=R,
|
||||
}
|
||||
BiRS={
|
||||
centerTex=GC.DO{10,10,
|
||||
{'setCL',1,1,1,.6},
|
||||
@@ -676,7 +681,7 @@ do
|
||||
|
||||
local t=P.freshTime
|
||||
if not ifpre then
|
||||
P:freshBlock('move')
|
||||
P:freshMoveBlock()
|
||||
end
|
||||
if fdy>0 and P.freshTime==t and P.curY~=P.imgY then
|
||||
P.freshTime=P.freshTime-1
|
||||
@@ -685,7 +690,7 @@ do
|
||||
local sfx
|
||||
if ifpre then
|
||||
sfx='prerotate'
|
||||
elseif P:ifoverlap(icb,x,y+1) and P:ifoverlap(icb,x-1,y) and P:ifoverlap(icb,x+1,y) then
|
||||
elseif y==P.ghoY and P:ifoverlap(icb,x,y+1) and P:ifoverlap(icb,x-1,y) and P:ifoverlap(icb,x+1,y) then
|
||||
sfx='rotatekick'
|
||||
P:_rotateField(d)
|
||||
else
|
||||
|
||||
@@ -19,9 +19,9 @@ function back.update()
|
||||
t=t-1
|
||||
if t==0 then
|
||||
local S={
|
||||
ang=6.2832*rnd(),
|
||||
ang=MATH.tau*rnd(),
|
||||
d=SCR.rad*1.05/2,
|
||||
rotate=6.2832*rnd(),
|
||||
rotate=MATH.tau*rnd(),
|
||||
va=.05-rnd()*.1,
|
||||
size=SCR.rad*(2+rnd()*3)/100,
|
||||
texture=SKIN.lib[SETTING.skinSet][rnd(16)],
|
||||
|
||||
@@ -21,7 +21,7 @@ function back.update()
|
||||
x=SCR.w*rnd(),
|
||||
y=SCR.h*-.05,
|
||||
k=SCR.rad/200,
|
||||
ang=rnd()*6.2832,
|
||||
ang=rnd()*MATH.tau,
|
||||
vy=.5+rnd()*.4,
|
||||
vx=rnd()*.4-.2,
|
||||
va=rnd()*.04-.02,
|
||||
|
||||
@@ -21,8 +21,8 @@ function back.update()
|
||||
ins(mino,{
|
||||
block=TEXTURE.miniBlock[r],
|
||||
color=BLOCK_COLORS[SETTING.skin[r]],
|
||||
ang=6.2832*rnd(),
|
||||
rotate=6.2832*rnd(),
|
||||
ang=MATH.tau*rnd(),
|
||||
rotate=MATH.tau*rnd(),
|
||||
vr=.05-rnd()*.1,
|
||||
d=0,
|
||||
v=.5+rnd(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local L={
|
||||
zChan={-- F0000~F003F
|
||||
zChan={-- F0000 - F003F
|
||||
none= 0xF0000,
|
||||
normal= 0xF0001,
|
||||
full= 0xF0002,
|
||||
@@ -15,7 +15,7 @@ local L={
|
||||
angry= 0xF000C,
|
||||
shocked= 0xF000D,
|
||||
ellipses= 0xF000E,
|
||||
sweat_drop= 0xF000F,
|
||||
sweatDrop= 0xF000F,
|
||||
cry= 0xF0010,
|
||||
cracked= 0xF0011,
|
||||
qualified= 0xF0012,
|
||||
@@ -24,7 +24,7 @@ local L={
|
||||
thinking= 0xF0015,
|
||||
spark= 0xF0016,
|
||||
},
|
||||
mino={-- F0040~F007F
|
||||
mino={-- F0040 - F007F
|
||||
Z=0xF0040,
|
||||
S=0xF0041,
|
||||
J=0xF0042,
|
||||
@@ -57,7 +57,7 @@ local L={
|
||||
I2=0xF005B,
|
||||
O1=0xF005C,
|
||||
},
|
||||
icon={-- F0080~F00FF
|
||||
icon={-- F0080 - F00FF
|
||||
menu= 0xF0080,
|
||||
music= 0xF0081,
|
||||
language= 0xF0082,
|
||||
@@ -154,8 +154,12 @@ local L={
|
||||
rewind30= 0xF00DD,
|
||||
foward10= 0xF00DE,
|
||||
foward30= 0xF00DF,
|
||||
fontUp= 0xF00E0,
|
||||
fontDown= 0xF00E1,
|
||||
erase= 0xF00E2,
|
||||
auto= 0xF00E3,
|
||||
},
|
||||
key={-- F0100~F017F
|
||||
key={-- F0100 - F017F
|
||||
macCmd= 0xF0100,
|
||||
macOpt= 0xF0101,
|
||||
macCtrl= 0xF0102,
|
||||
@@ -196,7 +200,7 @@ local L={
|
||||
macPgdnAlt= 0xF0125,
|
||||
iecPower= 0xF0126,
|
||||
},
|
||||
controller={-- F0180~F01FF
|
||||
controller={-- F0180 - F01FF
|
||||
xbox= 0xF0180,
|
||||
lt= 0xF0181,
|
||||
rt= 0xF0182,
|
||||
@@ -236,7 +240,7 @@ local L={
|
||||
psCreate= 0xF01A4,
|
||||
psOption= 0xF01A5,
|
||||
},
|
||||
mahjong={-- F0200~F027F
|
||||
mahjong={-- F0200 - F027F
|
||||
m1= 0xF0200,
|
||||
m2= 0xF0201,
|
||||
m3= 0xF0202,
|
||||
@@ -323,6 +327,67 @@ local L={
|
||||
s1j= 0xF0253,
|
||||
s1jBase= 0xF0254,
|
||||
s1jComb= 0xF0255,
|
||||
},
|
||||
cards={-- F0300 - F070F
|
||||
cardBack= 0xF0300,
|
||||
clubA= 0xF0301,
|
||||
club2= 0xF0302,
|
||||
club3= 0xF0303,
|
||||
club4= 0xF0304,
|
||||
club5= 0xF0305,
|
||||
club6= 0xF0306,
|
||||
club7= 0xF0307,
|
||||
club8= 0xF0308,
|
||||
club9= 0xF0309,
|
||||
club10= 0xF030A,
|
||||
clubJ= 0xF030B,
|
||||
clubC= 0xF030C,
|
||||
clubQ= 0xF030D,
|
||||
clubK= 0xF030E,
|
||||
heartA= 0xF0401,
|
||||
heart2= 0xF0402,
|
||||
heart3= 0xF0403,
|
||||
heart4= 0xF0404,
|
||||
heart5= 0xF0405,
|
||||
heart6= 0xF0406,
|
||||
heart7= 0xF0407,
|
||||
heart8= 0xF0408,
|
||||
heart9= 0xF0409,
|
||||
heart10= 0xF040A,
|
||||
heartJ= 0xF040B,
|
||||
heartC= 0xF040C,
|
||||
heartQ= 0xF040D,
|
||||
heartK= 0xF040E,
|
||||
diamondA= 0xF0501,
|
||||
diamond2= 0xF0502,
|
||||
diamond3= 0xF0503,
|
||||
diamond4= 0xF0504,
|
||||
diamond5= 0xF0505,
|
||||
diamond6= 0xF0506,
|
||||
diamond7= 0xF0507,
|
||||
diamond8= 0xF0508,
|
||||
diamond9= 0xF0509,
|
||||
diamond10= 0xF050A,
|
||||
diamondJ= 0xF050B,
|
||||
diamondC= 0xF050C,
|
||||
diamondQ= 0xF050D,
|
||||
diamondK= 0xF050E,
|
||||
jokerBlack= 0xF050F,
|
||||
clubA= 0xF0601,
|
||||
club2= 0xF0602,
|
||||
club3= 0xF0603,
|
||||
club4= 0xF0604,
|
||||
club5= 0xF0605,
|
||||
club6= 0xF0606,
|
||||
club7= 0xF0607,
|
||||
club8= 0xF0608,
|
||||
club9= 0xF0609,
|
||||
club10= 0xF060A,
|
||||
clubJ= 0xF060B,
|
||||
clubC= 0xF060C,
|
||||
clubQ= 0xF060D,
|
||||
clubK= 0xF060E,
|
||||
jokerWhite= 0xF060F,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
192
parts/data.lua
192
parts/data.lua
@@ -2,7 +2,7 @@ local floor=math.floor
|
||||
local char,byte=string.char,string.byte
|
||||
local ins=table.insert
|
||||
|
||||
local BAG,FIELD,MISSION,CUSTOMENV,GAME=BAG,FIELD,MISSION,CUSTOMENV,GAME
|
||||
local GAME=GAME
|
||||
|
||||
local DATA={}
|
||||
-- Sep symbol: 33 (!)
|
||||
@@ -13,13 +13,13 @@ local DATA={}
|
||||
Encode: A[B] sequence, A = block ID, B = repeat times, no B means do not repeat.
|
||||
Example: "abcdefg" is [SZJLTOI], "a^aDb)" is [Z*63,Z*37,S*10]
|
||||
]]
|
||||
function DATA.copySequence()
|
||||
function DATA.copySequence(bag)
|
||||
local str=""
|
||||
|
||||
local count=1
|
||||
for i=1,#BAG+1 do
|
||||
if BAG[i+1]~=BAG[i] or count==64 then
|
||||
str=str..char(96+BAG[i])
|
||||
for i=1,#bag+1 do
|
||||
if bag[i+1]~=bag[i] or count==64 then
|
||||
str=str..char(96+bag[i])
|
||||
if count>1 then
|
||||
str=str..char(32+count)
|
||||
count=1
|
||||
@@ -32,7 +32,7 @@ function DATA.copySequence()
|
||||
return str
|
||||
end
|
||||
function DATA.pasteSequence(str)
|
||||
TABLE.cut(BAG)
|
||||
local bag={}
|
||||
local b,reg
|
||||
for i=1,#str do
|
||||
b=byte(str,i)
|
||||
@@ -44,20 +44,20 @@ function DATA.pasteSequence(str)
|
||||
end
|
||||
else
|
||||
if b>=97 and b<=125 then
|
||||
ins(BAG,reg)
|
||||
ins(bag,reg)
|
||||
reg=b-96
|
||||
elseif b>=34 and b<=96 then
|
||||
for _=1,b-32 do
|
||||
ins(BAG,reg)
|
||||
ins(bag,reg)
|
||||
end
|
||||
reg=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if reg then
|
||||
ins(BAG,reg)
|
||||
ins(bag,reg)
|
||||
end
|
||||
return true
|
||||
return true,bag
|
||||
end
|
||||
|
||||
local fieldMeta={__index=function(self,h)
|
||||
@@ -69,8 +69,7 @@ end}
|
||||
function DATA.newBoard(f)-- Generate a new board
|
||||
return setmetatable(f and TABLE.shift(f) or{},fieldMeta)
|
||||
end
|
||||
function DATA.copyBoard(page)-- Copy the [page] board
|
||||
local F=FIELD[page or 1]
|
||||
function DATA.copyBoard(F)-- Copy the [page] board
|
||||
local str=""
|
||||
|
||||
-- Encode field
|
||||
@@ -84,21 +83,15 @@ function DATA.copyBoard(page)-- Copy the [page] board
|
||||
end
|
||||
return STRING.packBin(str)
|
||||
end
|
||||
function DATA.copyBoards()
|
||||
function DATA.copyBoards(field)
|
||||
local out={}
|
||||
for i=1,#FIELD do
|
||||
out[i]=DATA.copyBoard(i)
|
||||
for i=1,#field do
|
||||
out[i]=DATA.copyBoard(field[i])
|
||||
end
|
||||
return table.concat(out,"!")
|
||||
end
|
||||
function DATA.pasteBoard(str,page)-- Paste [str] data to [page] board
|
||||
if not page then
|
||||
page=1
|
||||
end
|
||||
if not FIELD[page] then
|
||||
FIELD[page]=DATA.newBoard()
|
||||
end
|
||||
local F=FIELD[page]
|
||||
function DATA.pasteBoard(str)-- Paste [str] data to [page] board
|
||||
local F=DATA.newBoard()
|
||||
|
||||
-- Decode
|
||||
str=STRING.unpackBin(str)
|
||||
@@ -106,6 +99,7 @@ function DATA.pasteBoard(str,page)-- Paste [str] data to [page] board
|
||||
|
||||
local fX,fY=1,1-- *ptr for Field(r*10+(c-1))
|
||||
local p=1
|
||||
local lineLimit=126
|
||||
while true do
|
||||
local b=byte(str,p)-- 1byte
|
||||
|
||||
@@ -127,13 +121,13 @@ function DATA.pasteBoard(str,page)-- Paste [str] data to [page] board
|
||||
fX=fX+1
|
||||
else
|
||||
fY=fY+1
|
||||
if fY>60 then break end
|
||||
if fY>lineLimit then break end
|
||||
fX=1
|
||||
end
|
||||
p=p+1
|
||||
end
|
||||
|
||||
return true
|
||||
return true,F,#str>lineLimit*10
|
||||
end
|
||||
|
||||
--[[
|
||||
@@ -152,14 +146,14 @@ end
|
||||
O1=61,O2=62,O3=63,O4=64,
|
||||
I1=71,I2=72,I3=73,I4=74,
|
||||
]]
|
||||
function DATA.copyMission()
|
||||
function DATA.copyMission(mission)
|
||||
local _
|
||||
local str=""
|
||||
|
||||
local count=1
|
||||
for i=1,#MISSION+1 do
|
||||
if MISSION[i+1]~=MISSION[i] or count==13 then
|
||||
_=33+MISSION[i]
|
||||
for i=1,#mission+1 do
|
||||
if mission[i+1]~=mission[i] or count==13 then
|
||||
_=33+mission[i]
|
||||
str=str..char(_)
|
||||
if count>1 then
|
||||
str=str..char(113+count)
|
||||
@@ -174,7 +168,7 @@ function DATA.copyMission()
|
||||
end
|
||||
function DATA.pasteMission(str)
|
||||
local b
|
||||
TABLE.cut(MISSION)
|
||||
local mission={}
|
||||
local reg
|
||||
for i=1,#str do
|
||||
b=byte(str,i)
|
||||
@@ -187,28 +181,28 @@ function DATA.pasteMission(str)
|
||||
else
|
||||
if b>=34 and b<=114 then
|
||||
if ENUM_MISSION[reg] then
|
||||
ins(MISSION,reg)
|
||||
ins(mission,reg)
|
||||
reg=b-33
|
||||
else
|
||||
TABLE.cut(MISSION)
|
||||
TABLE.cut(mission)
|
||||
return
|
||||
end
|
||||
elseif b>=115 and b<=126 then
|
||||
for _=1,b-113 do
|
||||
ins(MISSION,reg)
|
||||
ins(mission,reg)
|
||||
end
|
||||
reg=false
|
||||
end
|
||||
end
|
||||
end
|
||||
if reg then
|
||||
ins(MISSION,reg)
|
||||
ins(mission,reg)
|
||||
end
|
||||
return true
|
||||
return true,mission
|
||||
end
|
||||
|
||||
function DATA.copyQuestArgs()
|
||||
local ENV=CUSTOMENV
|
||||
function DATA.copyQuestArgs(custom_env)
|
||||
local ENV=custom_env
|
||||
local str=""..
|
||||
ENV.holdCount..
|
||||
(ENV.ospin and "O" or "Z")..
|
||||
@@ -218,14 +212,37 @@ function DATA.copyQuestArgs()
|
||||
end
|
||||
function DATA.pasteQuestArgs(str)
|
||||
if #str<4 then return end
|
||||
local ENV=CUSTOMENV
|
||||
ENV.holdCount= str:byte(1)-48
|
||||
local ENV={}
|
||||
ENV.holdCount= MATH.clamp(str:byte(1)-48,0,26)
|
||||
ENV.ospin= str:byte(2)~=90
|
||||
ENV.missionKill=str:byte(3)~=90
|
||||
ENV.sequence= str:sub(4)
|
||||
return true
|
||||
if select(2,require"parts.player.seqGenerators"(ENV.sequence)) then
|
||||
MES.new('warn',text.invalidSequence)
|
||||
ENV.sequence='bag'
|
||||
end
|
||||
return true,ENV
|
||||
end
|
||||
|
||||
local function _encode(t)
|
||||
if t<128 then return char(t) end
|
||||
local buffer2=char(t%128)
|
||||
t=floor(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=floor(t/128)
|
||||
end
|
||||
return char(128+t)..buffer2
|
||||
end
|
||||
local function _decode(str,p)
|
||||
local ret=0
|
||||
repeat
|
||||
local b=byte(str,p)
|
||||
p=p+1
|
||||
ret=ret*128+(b<128 and b or b-128)
|
||||
until b<128
|
||||
return ret,p
|
||||
end
|
||||
--[[
|
||||
Replay file:
|
||||
a zlib-compressed json table
|
||||
@@ -250,7 +267,7 @@ end
|
||||
]]
|
||||
function DATA.dumpRecording(list,ptr)
|
||||
local out=""
|
||||
local buffer,buffer2=""
|
||||
local buffer=""
|
||||
if not ptr then ptr=1 end
|
||||
local prevFrm=list[ptr-2] or 0
|
||||
while list[ptr] do
|
||||
@@ -263,31 +280,10 @@ function DATA.dumpRecording(list,ptr)
|
||||
-- Encode time
|
||||
local t=list[ptr]-prevFrm
|
||||
prevFrm=list[ptr]
|
||||
if t>=128 then
|
||||
buffer2=char(t%128)
|
||||
t=floor(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=floor(t/128)
|
||||
end
|
||||
buffer=buffer..char(128+t)..buffer2
|
||||
else
|
||||
buffer=buffer..char(t)
|
||||
end
|
||||
buffer=buffer.._encode(t)
|
||||
|
||||
-- Encode event
|
||||
t=list[ptr+1]
|
||||
if t>=128 then
|
||||
buffer2=char(t%128)
|
||||
t=floor(t/128)
|
||||
while t>=128 do
|
||||
buffer2=char(128+t%128)..buffer2
|
||||
t=floor(t/128)
|
||||
end
|
||||
buffer=buffer..char(128+t)..buffer2
|
||||
else
|
||||
buffer=buffer..char(t)
|
||||
end
|
||||
buffer=buffer.._encode(list[ptr+1])
|
||||
|
||||
-- Step
|
||||
ptr=ptr+2
|
||||
@@ -299,66 +295,53 @@ function DATA.pumpRecording(str,L)
|
||||
local p=1
|
||||
|
||||
local curFrm=L[#L-1] or 0
|
||||
local code
|
||||
while p<=len do
|
||||
local code,event
|
||||
-- Read delta time
|
||||
code=0
|
||||
local b=byte(str,p)
|
||||
while b>=128 do
|
||||
code=code*128+b-128
|
||||
p=p+1
|
||||
b=byte(str,p)
|
||||
end
|
||||
curFrm=curFrm+code*128+b
|
||||
L[#L+1]=curFrm
|
||||
p=p+1
|
||||
code,p=_decode(str,p)
|
||||
curFrm=curFrm+code
|
||||
ins(L,curFrm)
|
||||
|
||||
local event=0
|
||||
b=byte(str,p)
|
||||
while b>=128 do
|
||||
event=event*128+b-128
|
||||
p=p+1
|
||||
b=byte(str,p)
|
||||
end
|
||||
L[#L+1]=event*128+b
|
||||
p=p+1
|
||||
event,p=_decode(str,p)
|
||||
ins(L,event)
|
||||
end
|
||||
end
|
||||
do-- function DATA.saveReplay()
|
||||
local noRecList={"custom","solo","round","techmino"}
|
||||
local function _getModList()
|
||||
local res={}
|
||||
for _,v in next,GAME.mod do
|
||||
if v.sel>0 then
|
||||
ins(res,{v.no,v.sel})
|
||||
for number,sel in next,GAME.mod do
|
||||
if sel>0 then
|
||||
ins(res,{MODOPT[number].no,sel})
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
function DATA.saveReplay()
|
||||
-- Filtering modes that cannot be saved
|
||||
for _,v in next,noRecList do
|
||||
if GAME.curModeName:find(v) then
|
||||
MES.new('error',"Cannot save recording of this mode now!")
|
||||
return
|
||||
end
|
||||
if GAME.initPlayerCount~=1 then
|
||||
MES.new('error',"Cannot save recording of more than 1 player now!")
|
||||
return
|
||||
end
|
||||
|
||||
-- Write file
|
||||
local fileName=os.date("replay/%Y_%m_%d_%H%M%S.rep")
|
||||
if not love.filesystem.getInfo(fileName) then
|
||||
local metadata={
|
||||
date=os.date("%Y/%m/%d %H:%M:%S"),
|
||||
mode=GAME.curModeName,
|
||||
version=VERSION.string,
|
||||
player=USERS.getUsername(USER.uid),
|
||||
seed=GAME.seed,
|
||||
setting=GAME.setting,
|
||||
mod=_getModList(),
|
||||
tasUsed=GAME.tasUsed,
|
||||
}
|
||||
if GAME.curMode.savePrivate then
|
||||
metadata.private=GAME.curMode.savePrivate()
|
||||
end
|
||||
love.filesystem.write(fileName,
|
||||
love.data.compress('string','zlib',
|
||||
JSON.encode{
|
||||
date=os.date("%Y/%m/%d %H:%M:%S"),
|
||||
mode=GAME.curModeName,
|
||||
version=VERSION.string,
|
||||
player=USERS.getUsername(USER.uid),
|
||||
seed=GAME.seed,
|
||||
setting=GAME.setting,
|
||||
mod=_getModList(),
|
||||
tasUsed=GAME.tasUsed,
|
||||
}.."\n"..
|
||||
JSON.encode(metadata).."\n"..
|
||||
DATA.dumpRecording(GAME.rep)
|
||||
)
|
||||
)
|
||||
@@ -413,6 +396,9 @@ function DATA.parseReplayData(fileName,fileData,ifFull)
|
||||
tasUsed=metaData.tasUsed,
|
||||
}
|
||||
if ifFull then rep.data=fileData end
|
||||
if metaData.private then
|
||||
rep.private=metaData.private
|
||||
end
|
||||
return rep
|
||||
end
|
||||
return DATA
|
||||
|
||||
@@ -8,7 +8,7 @@ return {
|
||||
for i=#P.field,1,-1 do
|
||||
P.field[i],P.visTime[i]=nil
|
||||
end
|
||||
setField(P,D.finished+1)
|
||||
setField(P,FIELD[D.finished+1])
|
||||
SYSFX.newShade(1.4,P.absFieldX,P.absFieldY,300*P.size,610*P.size,.6,.8,.6)
|
||||
SFX.play('warn_1')
|
||||
else
|
||||
|
||||
@@ -7,21 +7,21 @@ end
|
||||
local function GetGravity(lvl)
|
||||
lvl=lvl%256
|
||||
return
|
||||
lvl==0 and 48 or
|
||||
lvl==1 and 43 or
|
||||
lvl==2 and 38 or
|
||||
lvl==3 and 33 or
|
||||
lvl==4 and 28 or
|
||||
lvl==5 and 23 or
|
||||
lvl==6 and 18 or
|
||||
lvl==7 and 13 or
|
||||
lvl==8 and 8 or
|
||||
lvl==9 and 6 or
|
||||
lvl<13 and 5 or
|
||||
lvl<16 and 4 or
|
||||
lvl<19 and 3 or
|
||||
lvl<29 and 2 or
|
||||
1
|
||||
lvl==0 and 48 or
|
||||
lvl==1 and 43 or
|
||||
lvl==2 and 38 or
|
||||
lvl==3 and 33 or
|
||||
lvl==4 and 28 or
|
||||
lvl==5 and 23 or
|
||||
lvl==6 and 18 or
|
||||
lvl==7 and 13 or
|
||||
lvl==8 and 8 or
|
||||
lvl==9 and 6 or
|
||||
lvl<13 and 5 or
|
||||
lvl<16 and 4 or
|
||||
lvl<19 and 3 or
|
||||
lvl<29 and 2 or
|
||||
1
|
||||
end
|
||||
return {
|
||||
das=16,arr=6,
|
||||
|
||||
@@ -7,21 +7,21 @@ end
|
||||
local function GetGravity(lvl)
|
||||
lvl=lvl%256
|
||||
return
|
||||
lvl==0 and 48 or
|
||||
lvl==1 and 43 or
|
||||
lvl==2 and 38 or
|
||||
lvl==3 and 33 or
|
||||
lvl==4 and 28 or
|
||||
lvl==5 and 23 or
|
||||
lvl==6 and 18 or
|
||||
lvl==7 and 13 or
|
||||
lvl==8 and 8 or
|
||||
lvl==9 and 6 or
|
||||
lvl<13 and 5 or
|
||||
lvl<16 and 4 or
|
||||
lvl<19 and 3 or
|
||||
lvl<29 and 2 or
|
||||
1
|
||||
lvl==0 and 48 or
|
||||
lvl==1 and 43 or
|
||||
lvl==2 and 38 or
|
||||
lvl==3 and 33 or
|
||||
lvl==4 and 28 or
|
||||
lvl==5 and 23 or
|
||||
lvl==6 and 18 or
|
||||
lvl==7 and 13 or
|
||||
lvl==8 and 8 or
|
||||
lvl==9 and 6 or
|
||||
lvl<13 and 5 or
|
||||
lvl<16 and 4 or
|
||||
lvl<19 and 3 or
|
||||
lvl<29 and 2 or
|
||||
1
|
||||
end
|
||||
return {
|
||||
das=16,arr=6,
|
||||
|
||||
@@ -7,21 +7,21 @@ end
|
||||
local function GetGravity(lvl)
|
||||
lvl=lvl%256
|
||||
return
|
||||
lvl==0 and 48 or
|
||||
lvl==1 and 43 or
|
||||
lvl==2 and 38 or
|
||||
lvl==3 and 33 or
|
||||
lvl==4 and 28 or
|
||||
lvl==5 and 23 or
|
||||
lvl==6 and 18 or
|
||||
lvl==7 and 13 or
|
||||
lvl==8 and 8 or
|
||||
lvl==9 and 6 or
|
||||
lvl<13 and 5 or
|
||||
lvl<16 and 4 or
|
||||
lvl<19 and 3 or
|
||||
lvl<29 and 2 or
|
||||
1
|
||||
lvl==0 and 48 or
|
||||
lvl==1 and 43 or
|
||||
lvl==2 and 38 or
|
||||
lvl==3 and 33 or
|
||||
lvl==4 and 28 or
|
||||
lvl==5 and 23 or
|
||||
lvl==6 and 18 or
|
||||
lvl==7 and 13 or
|
||||
lvl==8 and 8 or
|
||||
lvl==9 and 6 or
|
||||
lvl<13 and 5 or
|
||||
lvl<16 and 4 or
|
||||
lvl<19 and 3 or
|
||||
lvl<29 and 2 or
|
||||
1
|
||||
end
|
||||
return {
|
||||
das=16,arr=6,
|
||||
|
||||
114
parts/eventsets/construct_checker.lua
Normal file
114
parts/eventsets/construct_checker.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
local gc_setColor,gc_draw=love.graphics.setColor,love.graphics.draw
|
||||
local ply_applyField=PLY.draw.applyField
|
||||
|
||||
local holePatterns={
|
||||
{-1,21,-1,21,-1,21,-1,21,-1,21},
|
||||
{21,-1,21,-1,21,-1,21,-1,21,-1}
|
||||
}
|
||||
|
||||
local targetField={}
|
||||
|
||||
local function generateGuide(y,mirror)
|
||||
local tfLength=#targetField
|
||||
if tfLength>y then return end
|
||||
mirror=mirror and 1 or 0
|
||||
for i=tfLength,y do
|
||||
table.insert(targetField,TABLE.shift(
|
||||
holePatterns[(i+mirror)%2+1]
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
local function calculateRankPts(P)
|
||||
local points=1
|
||||
for y=1,#P.field do
|
||||
local flag
|
||||
for x=1,10 do
|
||||
-- X guide is filled
|
||||
if P.field[y][x]>0 and targetField[y][x]<0 then flag=true break end
|
||||
-- Block guide is empty
|
||||
if P.field[y][x]==0 and targetField[y][x]>0 then flag=true break end
|
||||
end
|
||||
if flag then break end
|
||||
points=points+1
|
||||
end
|
||||
P.modeData.rankPts=points
|
||||
P.modeData.maxRankPts=math.max(points,P.modeData.maxRankPts)
|
||||
end
|
||||
|
||||
return {
|
||||
fkey1=function(P) P.modeData.showGuide=not P.modeData.showGuide end,
|
||||
fkey2=function(P)
|
||||
P.modeData.mirror=not P.modeData.mirror
|
||||
TABLE.cut(targetField)
|
||||
generateGuide(#P.field+10,P.modeData.mirror)
|
||||
calculateRankPts(P)
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
local D=P.modeData
|
||||
mText(TEXTOBJ.grade,63,190)
|
||||
mText(TEXTOBJ.line,63,310)
|
||||
setFont(55)
|
||||
GC.mStr(getConstructGrade(D.rankPts),63,125)
|
||||
GC.mStr(D.rankPts-1,63,245)
|
||||
|
||||
-- Display highest grade
|
||||
if D.maxRankPts>D.rankPts then
|
||||
gc_setColor(COLOR.lX)
|
||||
setFont(20)
|
||||
GC.mStr(text.highest:repD(getConstructGrade(D.maxRankPts)),63,216)
|
||||
GC.mStr(text.highest:repD(D.maxRankPts-1),63,336)
|
||||
end
|
||||
|
||||
if not D.showGuide then return end
|
||||
ply_applyField(P)
|
||||
local mark=TEXTURE.puzzleMark
|
||||
local firstMistake=nil
|
||||
for y=1,D.rankPts+1 do
|
||||
for x=1,10 do
|
||||
local texture=targetField[y][x]
|
||||
-- Missing blocks
|
||||
if not P:solid(x,y) and texture>0 then
|
||||
-- Missing block under overhang
|
||||
if P:solid(x,y+1) then
|
||||
firstMistake=firstMistake or y
|
||||
gc_setColor(COLOR.R)
|
||||
else
|
||||
gc_setColor(COLOR.Z)
|
||||
end
|
||||
gc_draw(mark[texture],30*x-30,600-30*y)
|
||||
elseif texture<0 then
|
||||
-- X always gets displayed, color changes based on whether there is a block there
|
||||
if P:solid(x,y) then
|
||||
gc_setColor(COLOR.R)
|
||||
firstMistake=firstMistake or y
|
||||
elseif D.rankPts>y then
|
||||
gc_setColor(COLOR.G)
|
||||
else
|
||||
gc_setColor(COLOR.Z)
|
||||
end
|
||||
gc_draw(mark[texture],30*x-30,600-30*y)
|
||||
end
|
||||
end
|
||||
if y==firstMistake then
|
||||
gc_setColor(1,0,0,.2*(math.sin(2*TIME())+1))
|
||||
love.graphics.rectangle("fill",0,600-30*y,300,30)
|
||||
end
|
||||
end
|
||||
PLY.draw.cancelField()
|
||||
end,
|
||||
task=function(P)
|
||||
local D=P.modeData
|
||||
D.rankPts=1
|
||||
D.maxRankPts=1
|
||||
D.showGuide=true
|
||||
D.mirror=false
|
||||
TABLE.cut(targetField)
|
||||
generateGuide(10)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
calculateRankPts(P)
|
||||
generateGuide(#P.field+10)
|
||||
end
|
||||
}
|
||||
118
parts/eventsets/construct_invsg.lua
Normal file
118
parts/eventsets/construct_invsg.lua
Normal file
@@ -0,0 +1,118 @@
|
||||
local gc_setColor,gc_draw=love.graphics.setColor,love.graphics.draw
|
||||
local ply_applyField=PLY.draw.applyField
|
||||
|
||||
local targetField={}
|
||||
|
||||
local function getOpenHole(y,mirror)
|
||||
if mirror then y=y+9 end
|
||||
return -math.abs(((y-1) % 18)-9)+10
|
||||
end
|
||||
local function generateGuide(y,mirror)
|
||||
local l=#targetField
|
||||
if l>y then
|
||||
return
|
||||
end
|
||||
for i=l,y do
|
||||
targetField[i] = {}
|
||||
local h=getOpenHole(i,mirror)
|
||||
for j=1,10 do
|
||||
targetField[i][j]=h==j and 21 or -1
|
||||
end
|
||||
end
|
||||
end
|
||||
local function calculateRankPts(P)
|
||||
local points=1
|
||||
for y=1,#P.field do
|
||||
local holePos=getOpenHole(y,P.modeData.mirror)
|
||||
local flag
|
||||
for x=1,10 do
|
||||
if P.field[y][x]>0 and holePos~=x then flag=true break end
|
||||
if P.field[y][x]==0 and holePos==x then flag=true break end
|
||||
end
|
||||
if flag then break end
|
||||
if P:solid(holePos,y+1) then break end
|
||||
points=points+1
|
||||
end
|
||||
P.modeData.rankPts=points
|
||||
P.modeData.maxRankPts=math.max(points,P.modeData.maxRankPts)
|
||||
end
|
||||
|
||||
return {
|
||||
fkey1=function(P) P.modeData.showGuide=not P.modeData.showGuide end,
|
||||
fkey2=function(P)
|
||||
P.modeData.mirror=not P.modeData.mirror
|
||||
TABLE.cut(targetField)
|
||||
generateGuide(#P.field+10,P.modeData.mirror)
|
||||
calculateRankPts(P)
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
local D=P.modeData
|
||||
mText(TEXTOBJ.grade,63,190)
|
||||
mText(TEXTOBJ.line,63,310)
|
||||
setFont(55)
|
||||
GC.mStr(getConstructGrade(D.rankPts),63,125)
|
||||
GC.mStr(D.rankPts-1,63,245)
|
||||
|
||||
-- Display highest grade
|
||||
if D.maxRankPts>D.rankPts then
|
||||
gc_setColor(COLOR.lX)
|
||||
setFont(20)
|
||||
GC.mStr(text.highest:repD(getConstructGrade(D.maxRankPts)),63,216)
|
||||
GC.mStr(text.highest:repD(D.maxRankPts-1),63,336)
|
||||
end
|
||||
|
||||
if not D.showGuide then return end
|
||||
ply_applyField(P)
|
||||
local mark=TEXTURE.puzzleMark
|
||||
local firstMistake=nil
|
||||
for y=1,D.rankPts+1 do
|
||||
for x=1,10 do
|
||||
local texture=targetField[y][x]
|
||||
-- Missing blocks
|
||||
if not P:solid(x,y) and texture>0 then
|
||||
-- Missing block under overhang
|
||||
if P:solid(x,y+1) then
|
||||
firstMistake=firstMistake or y
|
||||
gc_setColor(COLOR.R)
|
||||
else
|
||||
gc_setColor(COLOR.Z)
|
||||
end
|
||||
gc_draw(mark[texture],30*x-30,600-30*y)
|
||||
elseif texture<0 then
|
||||
-- X always gets displayed, color changes based on whether there is a block there
|
||||
if P:solid(x,y) then
|
||||
gc_setColor(COLOR.R)
|
||||
firstMistake=firstMistake or y
|
||||
elseif D.rankPts>y then
|
||||
gc_setColor(COLOR.G)
|
||||
else
|
||||
gc_setColor(COLOR.Z)
|
||||
end
|
||||
gc_draw(mark[texture],30*x-30,600-30*y)
|
||||
end
|
||||
end
|
||||
if y==firstMistake then
|
||||
gc_setColor(1,0,0,.2*(math.sin(2*TIME())+1))
|
||||
love.graphics.rectangle("fill",0,600-30*y,300,30)
|
||||
end
|
||||
end
|
||||
PLY.draw.cancelField()
|
||||
end,
|
||||
task=function(P)
|
||||
local D=P.modeData
|
||||
D.rankPts=1
|
||||
D.showGuide=true
|
||||
D.maxRankPts=1
|
||||
D.mirror=false
|
||||
TABLE.cut(targetField)
|
||||
generateGuide(10,D.mirror)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
local oldPts=P.modeData.rankPts
|
||||
calculateRankPts(P)
|
||||
if oldPts>P.modeData.rankPts+2 then
|
||||
P:_showText("REGRET!!",0,-120,80,'beat',.8)
|
||||
end
|
||||
generateGuide(#P.field+10,P.modeData.mirror)
|
||||
end
|
||||
}
|
||||
114
parts/eventsets/construct_sg.lua
Normal file
114
parts/eventsets/construct_sg.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
local gc_setColor,gc_draw=love.graphics.setColor,love.graphics.draw
|
||||
local ply_applyField=PLY.draw.applyField
|
||||
|
||||
local targetField={}
|
||||
|
||||
local function getOpenHole(y,mirror)
|
||||
if mirror then y=y+9 end
|
||||
return -math.abs(((y-1) % 18)-9)+10
|
||||
end
|
||||
local function generateGuide(y,mirror)
|
||||
local l=#targetField
|
||||
if l>y then
|
||||
return
|
||||
end
|
||||
for i=l,y do
|
||||
targetField[i] = {}
|
||||
local h=getOpenHole(i,mirror)
|
||||
for j=1,10 do
|
||||
targetField[i][j]=h==j and -1 or 21
|
||||
end
|
||||
end
|
||||
end
|
||||
local function calculateRankPts(P)
|
||||
local points=1
|
||||
for y=1,#P.field do
|
||||
local holePos=getOpenHole(y,P.modeData.mirror)
|
||||
local flag
|
||||
for x=1,10 do
|
||||
if P.field[y][x]>0 and holePos==x then flag=true break end
|
||||
if P.field[y][x]==0 and holePos~=x then flag=true break end
|
||||
end
|
||||
if flag then break end
|
||||
if not P:solid(holePos,y+1) then break end
|
||||
points=points+1
|
||||
end
|
||||
P.modeData.rankPts=points
|
||||
P.modeData.maxRankPts=math.max(points,P.modeData.maxRankPts)
|
||||
end
|
||||
|
||||
return {
|
||||
fkey1=function(P) P.modeData.showGuide=not P.modeData.showGuide end,
|
||||
fkey2=function(P)
|
||||
P.modeData.mirror=not P.modeData.mirror
|
||||
TABLE.cut(targetField)
|
||||
generateGuide(#P.field+10,P.modeData.mirror)
|
||||
calculateRankPts(P)
|
||||
end,
|
||||
mesDisp=function(P)
|
||||
local D=P.modeData
|
||||
mText(TEXTOBJ.grade,63,190)
|
||||
mText(TEXTOBJ.line,63,310)
|
||||
setFont(55)
|
||||
GC.mStr(getConstructGrade(D.rankPts),63,125)
|
||||
GC.mStr(D.rankPts-1,63,245)
|
||||
|
||||
-- Display highest grade
|
||||
if D.maxRankPts>D.rankPts then
|
||||
gc_setColor(COLOR.lX)
|
||||
setFont(20)
|
||||
GC.mStr(text.highest:repD(getConstructGrade(D.maxRankPts)),63,216)
|
||||
GC.mStr(text.highest:repD(D.maxRankPts-1),63,336)
|
||||
end
|
||||
|
||||
if not D.showGuide then return end
|
||||
ply_applyField(P)
|
||||
local mark=TEXTURE.puzzleMark
|
||||
local firstMistake=nil
|
||||
for y=1,D.rankPts+1 do
|
||||
for x=1,10 do
|
||||
local texture=targetField[y][x]
|
||||
-- Missing blocks
|
||||
if not P:solid(x,y) and texture>0 then
|
||||
-- Missing block under overhang
|
||||
if P:solid(x,y+1) then
|
||||
firstMistake=firstMistake or y
|
||||
gc_setColor(COLOR.R)
|
||||
else
|
||||
gc_setColor(COLOR.Z)
|
||||
end
|
||||
gc_draw(mark[texture],30*x-30,600-30*y)
|
||||
elseif texture<0 then
|
||||
-- X always gets displayed, color changes based on whether there is a block there
|
||||
if P:solid(x,y) then
|
||||
gc_setColor(COLOR.R)
|
||||
firstMistake=firstMistake or y
|
||||
elseif D.rankPts>y then
|
||||
gc_setColor(COLOR.G)
|
||||
else
|
||||
gc_setColor(COLOR.Z)
|
||||
end
|
||||
gc_draw(mark[texture],30*x-30,600-30*y)
|
||||
end
|
||||
end
|
||||
if y==firstMistake then
|
||||
gc_setColor(1,0,0,.2*(math.sin(2*TIME())+1))
|
||||
love.graphics.rectangle("fill",0,600-30*y,300,30)
|
||||
end
|
||||
end
|
||||
PLY.draw.cancelField()
|
||||
end,
|
||||
task=function(P)
|
||||
local D=P.modeData
|
||||
D.rankPts=1
|
||||
D.showGuide=true
|
||||
D.maxRankPts=1
|
||||
D.mirror=false
|
||||
TABLE.cut(targetField)
|
||||
generateGuide(10,D.mirror)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
calculateRankPts(P)
|
||||
generateGuide(#P.field+10,P.modeData.mirror)
|
||||
end
|
||||
}
|
||||
@@ -15,54 +15,54 @@ local cool_time={3120,3120,2940,2700,2700,2520,2520,2280,2280,0}
|
||||
local regret_time= {5400,4500,4500,4080,3600,3600,3000,3000,3000,3000}
|
||||
local function getGrav(l)
|
||||
return
|
||||
l<30 and 64 or
|
||||
l<35 and 43 or
|
||||
l<40 and 32 or
|
||||
l<50 and 26 or
|
||||
l<60 and 21 or
|
||||
l<70 and 16 or
|
||||
l<80 and 8 or
|
||||
l<90 and 6 or
|
||||
l<120 and 4 or
|
||||
l<160 and 3 or
|
||||
l<200 and 2 or
|
||||
l<220 and 64 or
|
||||
l<230 and 8 or
|
||||
l<233 and 4 or
|
||||
l<236 and 3 or
|
||||
l<243 and 2 or
|
||||
l<300 and 1 or
|
||||
l<360 and 0.5 or
|
||||
l<450 and 0.25 or
|
||||
0
|
||||
l<30 and 64 or
|
||||
l<35 and 43 or
|
||||
l<40 and 32 or
|
||||
l<50 and 26 or
|
||||
l<60 and 21 or
|
||||
l<70 and 16 or
|
||||
l<80 and 8 or
|
||||
l<90 and 6 or
|
||||
l<120 and 4 or
|
||||
l<160 and 3 or
|
||||
l<200 and 2 or
|
||||
l<220 and 64 or
|
||||
l<230 and 8 or
|
||||
l<233 and 4 or
|
||||
l<236 and 3 or
|
||||
l<243 and 2 or
|
||||
l<300 and 1 or
|
||||
l<360 and 0.5 or
|
||||
l<450 and 0.25 or
|
||||
0
|
||||
end
|
||||
local function getLock(l)
|
||||
return
|
||||
l<900 and 30 or
|
||||
l<1100 and 19 or
|
||||
15
|
||||
l<900 and 30 or
|
||||
l<1100 and 19 or
|
||||
15
|
||||
end
|
||||
local function getWait(l)
|
||||
return
|
||||
l<700 and 23 or
|
||||
l<800 and 16 or
|
||||
l<1000 and 12 or
|
||||
l<1100 and 7 or
|
||||
6
|
||||
l<700 and 23 or
|
||||
l<800 and 16 or
|
||||
l<1000 and 12 or
|
||||
l<1100 and 7 or
|
||||
6
|
||||
end
|
||||
local function getFall(l)
|
||||
return
|
||||
l<500 and 25 or
|
||||
l<600 and 18 or
|
||||
l<700 and 12 or
|
||||
l<800 and 8 or
|
||||
4
|
||||
l<500 and 25 or
|
||||
l<600 and 18 or
|
||||
l<700 and 12 or
|
||||
l<800 and 8 or
|
||||
4
|
||||
end
|
||||
local function getDas(l)
|
||||
return
|
||||
l<500 and 10 or
|
||||
l<900 and 8 or
|
||||
6
|
||||
l<500 and 10 or
|
||||
l<900 and 8 or
|
||||
6
|
||||
end
|
||||
local function getCurrentGrade(D)
|
||||
if not D.int_grade then D.int_grade=0 end
|
||||
@@ -175,7 +175,7 @@ return {
|
||||
GC.rectangle('line',0,240,126,80,4)
|
||||
GC.setColor(.98,.98,.98,.4)
|
||||
GC.rectangle('fill',0+2,240+2,126-4,80-4,2) -- draw time box
|
||||
|
||||
|
||||
setFont(45) -- Draw time text
|
||||
local t=(P.stat.frame-D.prevSectTime)/60
|
||||
local T=("%.1f"):format(60-t)
|
||||
@@ -261,7 +261,7 @@ return {
|
||||
elseif s==5 then
|
||||
if P.stat.frame>420*60 then
|
||||
D.pt=500
|
||||
P:win('finish')
|
||||
P:torikanEnd(420)
|
||||
return
|
||||
else
|
||||
BG.set('glow')
|
||||
|
||||
@@ -40,7 +40,7 @@ return {
|
||||
elseif s==5 then
|
||||
if P.stat.frame>183*60 then
|
||||
D.pt=500
|
||||
P:win('finish')
|
||||
P:torikanEnd(183)
|
||||
return
|
||||
else
|
||||
E.bone=true
|
||||
|
||||
@@ -38,9 +38,9 @@ return {
|
||||
elseif s==4 then
|
||||
BG.set('rainbow2')
|
||||
elseif s==5 then
|
||||
if P.stat.frame>260*60 then
|
||||
if P.stat.time>260 then
|
||||
D.pt=500
|
||||
P:win('finish')
|
||||
P:torikanEnd(260)
|
||||
return
|
||||
else
|
||||
P.gameEnv.freshLimit=10
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
local gc_setColor,gc_draw=love.graphics.setColor,love.graphics.draw
|
||||
local ply_applyField=PLY.draw.applyField
|
||||
local function getOpenHole(num)
|
||||
return -math.abs(((num-1) % 18)-9)+10
|
||||
end
|
||||
local F={}
|
||||
|
||||
-- local ranks={"10","9","8","7","6","5","4","3","2","1","S1","S2","S3","S4","S5","S6","S7","S8","S9","GM","GM+","TM","TM+","TM+₂","TM+₃", "TM+₄","TM+₅"}
|
||||
-- lines: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
||||
|
||||
local function generateGuide(num)
|
||||
local l=#F
|
||||
if l>num then
|
||||
return
|
||||
end
|
||||
for i=l,num do
|
||||
F[i] = {}
|
||||
local h=getOpenHole(i)
|
||||
for j=1,10 do
|
||||
F[i][j]=h==j and -1 or 21
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
fkey1=function(P) P.modeData.showGuide=not P.modeData.showGuide end,
|
||||
mesDisp=function(P)
|
||||
mText(TEXTOBJ.grade,63,190)
|
||||
mText(TEXTOBJ.line,63,310)
|
||||
setFont(55)
|
||||
GC.mStr(getSecretGrade(P.modeData.rankPts),63,125)
|
||||
GC.mStr(P.modeData.rankPts-1,63,245)
|
||||
ply_applyField(P)
|
||||
local mark=TEXTURE.puzzleMark
|
||||
gc_setColor(1,1,1)
|
||||
if P.modeData.showGuide then
|
||||
for y=1,P.modeData.rankPts+1 do for x=1,10 do
|
||||
local T=F[y][x]
|
||||
if T~=0 then
|
||||
gc_draw(mark[T],30*x-30,600-30*y)
|
||||
end
|
||||
end end
|
||||
end
|
||||
PLY.draw.cancelField()
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.rankPts=1
|
||||
P.modeData.showGuide=true
|
||||
generateGuide(10)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
D.rankPts=0
|
||||
for i=1,#P.field do
|
||||
local h=getOpenHole(i)
|
||||
local flag
|
||||
for j=1,10 do
|
||||
if P.field[i][j]>0 and h==j then flag=true break end-- goto post_pts_calc
|
||||
if P.field[i][j]==0 and h~=j then flag=true break end-- goto post_pts_calc
|
||||
end
|
||||
if flag then break end
|
||||
if i==#P.field then break end-- goto post_pts_calc
|
||||
if P.field[i+1][h]==0 then break end-- goto post_pts_calc
|
||||
D.rankPts=D.rankPts+1
|
||||
end
|
||||
-- ::post_pts_calc::
|
||||
generateGuide(D.rankPts+20)
|
||||
end
|
||||
}
|
||||
@@ -15,13 +15,13 @@ return {
|
||||
if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY) then
|
||||
P:createMoveFX('left')
|
||||
P.curX=P.curX-1
|
||||
P:freshBlock('move')
|
||||
P:freshMoveBlock()
|
||||
end
|
||||
elseif r==2 then
|
||||
if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY) then
|
||||
P:createMoveFX('left')
|
||||
P.curX=P.curX-1
|
||||
P:freshBlock('move')
|
||||
P:freshMoveBlock()
|
||||
end
|
||||
elseif r==3 then
|
||||
P:act_rotRight()
|
||||
|
||||
@@ -3,6 +3,7 @@ local function lockKey(P,keys)
|
||||
P.keyAvailable[v]=false
|
||||
VK.keys[v].ava=false
|
||||
VK.release(v)
|
||||
P:releaseKey(v)
|
||||
end
|
||||
end
|
||||
local function unlockKey(P,keys)
|
||||
@@ -15,7 +16,10 @@ local function lockMovement(P)
|
||||
lockKey(P,{1,2})
|
||||
end
|
||||
local function lockRotation(P)
|
||||
lockKey(P,{3,4,5})
|
||||
lockKey(P,{3,4})
|
||||
end
|
||||
local function lockRotation180(P)
|
||||
lockKey(P,{5})
|
||||
end
|
||||
local function unlock(P)
|
||||
if P.cur and P.cur.name==6 and not P.gameEnv.skipOCheck then -- don't unlock rotation if O piece & no O-spin
|
||||
@@ -39,37 +43,38 @@ local function onMove(P)
|
||||
P.holdTime=0
|
||||
lockKey(P,{8})
|
||||
|
||||
-- return if overhang
|
||||
if P:_roofCheck() then return end
|
||||
|
||||
P.modeData.moveCount=P.modeData.moveCount+1
|
||||
if P.modeData.moveCount>=2 then lockMovement(P) end
|
||||
if not P:_roofCheck() then
|
||||
P.modeData.moveCount=P.modeData.moveCount+1
|
||||
if P.modeData.moveCount>=2 then lockMovement(P) end
|
||||
end
|
||||
end
|
||||
local function onAutoMove(P)
|
||||
if P:_roofCheck() then unlock(P) end
|
||||
end
|
||||
local function onRotate(P)
|
||||
local function onRotate(P,dir)
|
||||
if not P.cur then return end
|
||||
|
||||
P.holdTime=0
|
||||
lockKey(P,{8})
|
||||
|
||||
-- return if overhang
|
||||
if P:_roofCheck() then return end
|
||||
|
||||
P.modeData.rotations=P.modeData.rotations+1
|
||||
if P.modeData.rotations>=2 then lockRotation(P) end
|
||||
if not P:_roofCheck() then
|
||||
P.modeData.rotations=P.modeData.rotations+(dir==2 and 2 or 1)
|
||||
lockRotation180(P)
|
||||
if P.modeData.rotations>=2 then
|
||||
lockRotation(P)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
arr=0,
|
||||
fineKill=true,
|
||||
mesDisp=function(P)
|
||||
setFont(45)
|
||||
GC.mStr(("%d"):format(P.stat.atk),63,190)
|
||||
GC.mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,310)
|
||||
mText(TEXTOBJ.atk,63,243)
|
||||
mText(TEXTOBJ.eff,63,363)
|
||||
setFont(55)
|
||||
local r=40-P.stat.row
|
||||
if r<0 then r=0 end
|
||||
GC.mStr(r,63,265)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
end,
|
||||
task=function(P)
|
||||
resetLock(P)
|
||||
@@ -82,7 +87,7 @@ return {
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
resetLock(P)
|
||||
if P.stat.atk>=100 then
|
||||
if P.stat.row>=40 then
|
||||
P:win('finish')
|
||||
end
|
||||
end,
|
||||
@@ -90,6 +95,7 @@ return {
|
||||
if P.gameEnv.skipOCheck then return end
|
||||
if P.cur.name==6 then
|
||||
lockRotation(P)
|
||||
lockRotation180(P)
|
||||
else
|
||||
resetLock(P)
|
||||
end
|
||||
@@ -98,11 +104,12 @@ return {
|
||||
if P.gameEnv.skipOCheck then return end
|
||||
if P.cur.name==6 then
|
||||
lockRotation(P)
|
||||
lockRotation180(P)
|
||||
else
|
||||
resetLock(P)
|
||||
end
|
||||
end,
|
||||
hook_left_manual=onMove, hook_right_manual=onMove,
|
||||
hook_left_auto=onAutoMove, hook_right_auto=onAutoMove,
|
||||
hook_rotLeft=onRotate, hook_rotRight=onRotate, hook_rot180=onRotate,
|
||||
hook_rotate=onRotate
|
||||
}
|
||||
@@ -26,7 +26,7 @@ return {
|
||||
P.garbageBeneath=P.garbageBeneath-bonus
|
||||
end
|
||||
end
|
||||
P:freshBlock('push')
|
||||
P:freshBlockGhost()
|
||||
end
|
||||
end,
|
||||
}
|
||||
@@ -26,7 +26,7 @@ return {
|
||||
P.garbageBeneath=P.garbageBeneath-bonus
|
||||
end
|
||||
end
|
||||
P:freshBlock('push')
|
||||
P:freshBlockGhost()
|
||||
end
|
||||
end,
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
local function lockKey(P,keys)
|
||||
for _,v in next,keys do
|
||||
P.keyAvailable[v]=false
|
||||
VK.keys[v].ava=false
|
||||
VK.release(v)
|
||||
end
|
||||
end
|
||||
local function unlockKey(P,keys)
|
||||
for _,v in next,keys do
|
||||
P.keyAvailable[v]=true
|
||||
VK.keys[v].ava=true
|
||||
end
|
||||
end
|
||||
local function lockMovement(P)
|
||||
lockKey(P,{1,2})
|
||||
end
|
||||
local function lockRotation(P)
|
||||
lockKey(P,{3,4,5})
|
||||
end
|
||||
local function unlock(P)
|
||||
if P.cur and P.cur.name==6 and not P.gameEnv.skipOCheck then -- don't unlock rotation if O piece & no O-spin
|
||||
unlockKey(P,{1,2,6,7})
|
||||
return
|
||||
end
|
||||
unlockKey(P,{1,2,3,4,5,6,7})
|
||||
end
|
||||
local function resetLock(P)
|
||||
unlock(P)
|
||||
unlockKey(P,{8})
|
||||
|
||||
P.modeData.moveCount=0
|
||||
P.modeData.rotations=0
|
||||
P.holdTime=1
|
||||
end
|
||||
|
||||
local function onMove(P)
|
||||
if not P.cur then return end
|
||||
|
||||
P.holdTime=0
|
||||
lockKey(P,{8})
|
||||
|
||||
-- return if overhang
|
||||
if P:_roofCheck() then return end
|
||||
|
||||
P.modeData.moveCount=P.modeData.moveCount+1
|
||||
if P.modeData.moveCount>=2 then lockMovement(P) end
|
||||
end
|
||||
local function onAutoMove(P)
|
||||
if P:_roofCheck() then unlock(P) end
|
||||
end
|
||||
local function onRotate(P)
|
||||
if not P.cur then return end
|
||||
|
||||
P.holdTime=0
|
||||
lockKey(P,{8})
|
||||
|
||||
-- return if overhang
|
||||
if P:_roofCheck() then return end
|
||||
|
||||
P.modeData.rotations=P.modeData.rotations+1
|
||||
if P.modeData.rotations>=2 then lockRotation(P) end
|
||||
end
|
||||
|
||||
return {
|
||||
arr=0,
|
||||
fineKill=true,
|
||||
mesDisp=function(P)
|
||||
setFont(45)
|
||||
GC.mStr(("%d"):format(P.stat.atk),63,190)
|
||||
GC.mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,310)
|
||||
mText(TEXTOBJ.atk,63,243)
|
||||
mText(TEXTOBJ.eff,63,363)
|
||||
end,
|
||||
task=function(P)
|
||||
resetLock(P)
|
||||
local RSname=P.RS.name
|
||||
P.gameEnv.skipOCheck=(
|
||||
string.find(RSname,'TRS') or
|
||||
string.find(RSname,'BiRS') or
|
||||
string.find(RSname,'ASC')
|
||||
)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
resetLock(P)
|
||||
|
||||
local C=P.lastPiece
|
||||
if C.row>0 then
|
||||
if not C.special then
|
||||
P:lose()
|
||||
return
|
||||
end
|
||||
end
|
||||
if P.stat.atk>=100 then
|
||||
P:win('finish')
|
||||
end
|
||||
end,
|
||||
hook_spawn=function(P)
|
||||
if P.gameEnv.skipOCheck then return end
|
||||
if P.cur.name==6 then
|
||||
lockRotation(P)
|
||||
else
|
||||
resetLock(P)
|
||||
end
|
||||
end,
|
||||
hook_hold=function(P)
|
||||
if P.gameEnv.skipOCheck then return end
|
||||
if P.cur.name==6 then
|
||||
lockRotation(P)
|
||||
else
|
||||
resetLock(P)
|
||||
end
|
||||
end,
|
||||
hook_left_manual=onMove, hook_right_manual=onMove,
|
||||
hook_left_auto=onAutoMove, hook_right_auto=onAutoMove,
|
||||
hook_rotLeft=onRotate, hook_rotRight=onRotate, hook_rot180=onRotate
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -115,7 +115,7 @@ do-- function applySettings()
|
||||
light={.2,.8},
|
||||
color={-.2,1.2},
|
||||
}
|
||||
function applySettings()
|
||||
function applySettings(reason)
|
||||
-- Apply language
|
||||
text=LANG.get(SETTING.locale)
|
||||
WIDGET.setLang(text.WidgetText)
|
||||
@@ -157,9 +157,12 @@ do-- function applySettings()
|
||||
SHADER.fieldSatur:send('k',m[2])
|
||||
|
||||
-- Apply BG
|
||||
if reason=='fullscreen' then return end
|
||||
if SETTING.bg=='on' then
|
||||
BG.unlock()
|
||||
BG.setDefault(SETTING.defaultBG)
|
||||
BG.set()
|
||||
if SETTING.lockBG then BG.lock() end
|
||||
elseif SETTING.bg=='off' then
|
||||
BG.unlock()
|
||||
BG.set('fixColor',SETTING.bgAlpha,SETTING.bgAlpha,SETTING.bgAlpha)
|
||||
@@ -192,13 +195,13 @@ local function getSmallNum(num)
|
||||
local str=tostring(num)
|
||||
local out=""
|
||||
for i=1,#str do
|
||||
out=out..smallDigits[tonumber(string.sub(str,i,i))]
|
||||
out=out..smallDigits[tonumber(str:sub(i,i))]
|
||||
end
|
||||
return out
|
||||
end
|
||||
do -- Secret Grade
|
||||
local r={"GM","GM+","TM","TM+"}
|
||||
function getSecretGrade(index)
|
||||
function getConstructGrade(index)
|
||||
if index<11 then -- rank 10 - 1
|
||||
return tostring(11-index)
|
||||
elseif index<20 then -- S1 - S9 ranks
|
||||
@@ -210,11 +213,11 @@ do -- Secret Grade
|
||||
end
|
||||
end
|
||||
end
|
||||
function getSecretGradeText(index)
|
||||
function getConstructGradeText(index)
|
||||
if index<11 then
|
||||
return "Grade "..tostring(11-index)
|
||||
else
|
||||
return getSecretGrade(index)
|
||||
return getConstructGrade(index)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -424,8 +427,7 @@ function notEmptyLine(L)
|
||||
end
|
||||
end
|
||||
end
|
||||
function setField(P,page)
|
||||
local F=FIELD[page]
|
||||
function setField(P,F)
|
||||
local height=0
|
||||
for y=#F,1,-1 do
|
||||
if notEmptyLine(F[y]) then
|
||||
@@ -504,8 +506,8 @@ function mergeStat(stat,delta)-- Merge delta stat. to global stat.
|
||||
end
|
||||
end
|
||||
function scoreValid()-- Check if any unranked mods are activated
|
||||
for _,M in next,GAME.mod do
|
||||
if M.unranked then
|
||||
for number,sel in next,GAME.mod do
|
||||
if sel>0 and MODOPT[number].unranked then
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -994,17 +996,23 @@ do-- function dumpBasicConfig()
|
||||
end
|
||||
end
|
||||
do-- function resetGameData(args)
|
||||
local function task_showMods()
|
||||
local time=0
|
||||
while true do
|
||||
coroutine.yield()
|
||||
if time%20==0 then
|
||||
local M=GAME.mod[time/20+1]
|
||||
if not M then return end
|
||||
local function task_showMods() -- TODO
|
||||
coroutine.yield()
|
||||
local counter=0
|
||||
for number,sel in next,GAME.mod do
|
||||
if sel>0 then
|
||||
if counter==0 then
|
||||
coroutine.yield()
|
||||
else
|
||||
for _=1,20 do
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
local M=MODOPT[number]
|
||||
SFX.play('collect',.2)
|
||||
TEXT.show(M.id,640+(time/20%5-2)*80,26,45,'spin')
|
||||
TEXT.show(M.id,640+(counter%5-2)*80,26,45,'spin')
|
||||
counter=counter+1
|
||||
end
|
||||
time=time+1
|
||||
end
|
||||
end
|
||||
local gameSetting={
|
||||
@@ -1064,6 +1072,7 @@ do-- function resetGameData(args)
|
||||
else
|
||||
PLY.newPlayer(1)
|
||||
end
|
||||
GAME.initPlayerCount=#PLAYERS
|
||||
freshPlayerPosition((args:find'q') and 'quick' or 'normal')
|
||||
VK.restore()
|
||||
|
||||
@@ -1126,6 +1135,14 @@ do-- function checkWarning(P,dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
function usingMod()
|
||||
for _,sel in next,GAME.mod do
|
||||
if sel>0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1176,6 +1193,9 @@ function drawWarning()
|
||||
gc_pop()
|
||||
end
|
||||
end
|
||||
function setModBackgroundColor()
|
||||
gc_setColor(.42,.26,.62,.62+.26*math.sin(TIME()*12.6))
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1210,8 +1230,7 @@ do-- function pressKey(k)
|
||||
return cache[k]
|
||||
end
|
||||
end
|
||||
do-- CUS/SETXXX(k)
|
||||
local CUSTOMENV=CUSTOMENV
|
||||
do-- SETXXX(k) & ROOMXXX(k)
|
||||
local warnList={
|
||||
'das','arr','dascut','dropcut','sddas','sdarr',
|
||||
'ihs','irs','ims','RS',
|
||||
@@ -1219,13 +1238,10 @@ do-- CUS/SETXXX(k)
|
||||
'VKSwitch','VKIcon','VKTrack','VKDodge',
|
||||
'simpMode',
|
||||
}
|
||||
function CUSval(k) return function() return CUSTOMENV[k] end end
|
||||
function ROOMval(k) return function() return ROOMENV[k] end end
|
||||
function SETval(k) return function() return SETTING[k] end end
|
||||
function CUSrev(k) return function() CUSTOMENV[k]=not CUSTOMENV[k] end end
|
||||
function ROOMrev(k) return function() ROOMENV[k]=not ROOMENV[k] end end
|
||||
function SETrev(k) return function() if TABLE.find(warnList,k) then trySettingWarn() end SETTING[k]=not SETTING[k] end end
|
||||
function CUSsto(k) return function(i) CUSTOMENV[k]=i end end
|
||||
function ROOMsto(k) return function(i) ROOMENV[k]=i end end
|
||||
function SETsto(k) return function(i) if TABLE.find(warnList,k) then trySettingWarn() end SETTING[k]=i end end
|
||||
end
|
||||
|
||||
@@ -293,6 +293,7 @@ MODE_UPDATE_MAP={
|
||||
round_3="round_l",
|
||||
round_4="round_n",
|
||||
round_5="round_u",
|
||||
secret_grade="construct_sg",
|
||||
solo_1="solo_e",
|
||||
solo_2="solo_h",
|
||||
solo_3="solo_l",
|
||||
@@ -326,8 +327,8 @@ MODE_UPDATE_MAP={
|
||||
tsd_hard="tsd_h",
|
||||
tsd_ultimate="tsd_u",
|
||||
GM="master_ex",
|
||||
master_beginner="master_l",
|
||||
master_advance="master_u",
|
||||
master_beginner="master_n",
|
||||
master_advance="master_h",
|
||||
master_phantasm="master_ph",
|
||||
master_extra="master_ex",
|
||||
}
|
||||
@@ -495,7 +496,7 @@ do-- Mod data
|
||||
}
|
||||
for i=1,#MODOPT do
|
||||
local M=MODOPT[i]
|
||||
M.sel,M.time=0,0
|
||||
M.time=0
|
||||
M.color=COLOR[M.color]
|
||||
end
|
||||
end
|
||||
@@ -506,37 +507,38 @@ do-- Game data tables
|
||||
BAG={}-- Sequence for custom game
|
||||
MISSION={}-- Clearing mission for custom game
|
||||
GAME={-- Global game data
|
||||
playing=false, -- If in-game
|
||||
init=false, -- If need initializing game when enter scene-play
|
||||
net=false, -- If play net game
|
||||
playing=false, -- If in-game
|
||||
init=false, -- If need initializing game when enter scene-play
|
||||
net=false, -- If play net game
|
||||
|
||||
result=false, -- Game result (string)
|
||||
rank=0, -- Rank reached
|
||||
pauseTime=0, -- Time paused
|
||||
pauseCount=0, -- Pausing count
|
||||
warnLVL0=0, -- Warning level
|
||||
warnLVL=0, -- Warning level (show)
|
||||
result=false, -- Game result (string)
|
||||
rank=0, -- Rank reached
|
||||
pauseTime=0, -- Time paused
|
||||
pauseCount=0, -- Pausing count
|
||||
warnLVL0=0, -- Warning level
|
||||
warnLVL=0, -- Warning level (show)
|
||||
|
||||
seed=1046101471, -- Game seed
|
||||
curMode=false, -- Current gamemode object
|
||||
mod={}, -- List of loaded mods
|
||||
modeEnv=false, -- Current gamemode environment
|
||||
setting={}, -- Game settings
|
||||
rep={}, -- Recording list, key,time,key,time...
|
||||
statSaved=true, -- If recording saved
|
||||
recording=false, -- If recording
|
||||
replaying=false, -- If replaying
|
||||
saved=false, -- If recording saved
|
||||
tasUsed=false, -- If tasMode used
|
||||
seed=1046101471, -- Game seed
|
||||
curMode=false, -- Current gamemode object
|
||||
initPlayerCount=0, -- Player count when init game
|
||||
mod=TABLE.new(0,#MODOPT),-- List of loaded mods
|
||||
modeEnv=false, -- Current gamemode environment
|
||||
setting={}, -- Game settings
|
||||
rep={}, -- Recording list, key,time,key,time...
|
||||
statSaved=true, -- If recording saved
|
||||
recording=false, -- If recording
|
||||
replaying=false, -- If replaying
|
||||
saved=false, -- If recording saved
|
||||
tasUsed=false, -- If tasMode used
|
||||
|
||||
prevBG=false, -- Previous background, for restore BG when quit setting page
|
||||
prevBG=false, -- Previous background, for restore BG when quit setting page
|
||||
|
||||
-- Data for royale mode
|
||||
stage=false, -- Game stage
|
||||
mostBadge=false, -- Most badge owner
|
||||
secBadge=false, -- Second badge owner
|
||||
mostDangerous=false,-- Most dangerous player
|
||||
secDangerous=false, -- Second dangerous player
|
||||
stage=false, -- Game stage
|
||||
mostBadge=false, -- Most badge owner
|
||||
secBadge=false, -- Second badge owner
|
||||
mostDangerous=false, -- Most dangerous player
|
||||
secDangerous=false, -- Second dangerous player
|
||||
}
|
||||
ROYALEDATA={
|
||||
powerUp=false,
|
||||
@@ -657,6 +659,9 @@ do-- Userdata tables
|
||||
msaa=0,
|
||||
bg='on',
|
||||
bgAlpha=.26,
|
||||
defaultBG='space',
|
||||
lockBG=false,
|
||||
noTheme=false,
|
||||
powerInfo=false,
|
||||
clickFX=true,
|
||||
warn=true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
-- Automatically generated by a Python script, from a markdown source file.
|
||||
-- The script can be found here: https://github.com/user670/techmino-dictionary-converter/blob/master/tool.py
|
||||
-- **NOTE TO TRANSLATORS**: In English (and in this file) the symbol ~ (tilde) is commonly used to express "approximately". Some languages use this symbol to express ranges or "from/up to a value", but it is not commonly used in English.
|
||||
return {
|
||||
{"Translator Note 1",
|
||||
"",
|
||||
@@ -827,7 +828,7 @@ FNNS and {"Support 3",
|
||||
{"Finesse",
|
||||
"finesse",
|
||||
"term",
|
||||
"A technique that moves a block to the desired location with the minimum number of keypresses. Finesse usually doesn't consider locations that require soft drops to move into. Finesses save time and reduce the chances of misdropping a block.\nFinesse is an essential skill in playing Tetris. We recommend that you start learning finesse as soon as possible. You can find videos about finesse on YouTube. Start by learning the basics and then start practicing, keeping accuracy as the first priority before speeding up.\nNote that in Techmino, finesses are not exactly \"the theoretically simplest keystroke sequence it takes to move a block to a particular location.\" Finesses are only detected when a piece locks into a position that does not require soft drops, so the finesses strikes are not reset after a spin or a tuck. Techmino also counts holding a block when it's the same block you're controlling and holding a block after manipulating it as finesse errors.\nIn Techmino, the finesse rate (%) is defined as 100% (Perfect) when the number of keypresses is equal to or less than the standard reference, 50% (Great) when one keypress is above the standard, 25% (Bad) when two keypresses are above the standard, and 0% (Miss) when three or more keypresses are above the standard. A Bad or Miss breaks the finesse strike.\nFinesse is usually not considered in conditions such as locations that require soft drops, high gravity, or very high fields. The finesse counter also works the same in Techmino regardless of gravity (even in 20G modes), so the result may not be meaningful in high gravity conditions.",
|
||||
"A technique that moves a block to the desired location with the minimum number of keypresses. Finesse usually doesn't consider locations that require soft drops to move into. Finesses save time and reduce the chances of misdropping a block.\nFinesse is an essential skill in playing Tetris. We recommend that you start learning finesse as soon as possible. You can find videos about finesse on YouTube. Start by learning the basics and then start practicing, keeping accuracy as the first priority before speeding up.\nNote that in Techmino, finesses are not exactly \"the theoretically simplest keystroke sequence it takes to move a block to a particular location.\" Finesses are only detected when a piece locks into a position that does not require soft drops, so the finesses strikes are not reset after a spin or a tuck.\nIn Techmino, the finesse rate (%) is defined as 100% (Perfect) when the number of keypresses is equal to or less than the standard reference, 50% (Great) when one keypress is above the standard, 25% (Bad) when two keypresses above, and 0% (Miss) when three or more keypresses above. A Bad or Miss breaks the finesse strike.\nFinesse is usually not considered in conditions such as locations that require soft drops, high gravity, or very high fields. The finesse counter also works the same in Techmino regardless of gravity (even in 20G modes), so the result may not be meaningful in high gravity conditions.",
|
||||
},
|
||||
{"'Researching'",
|
||||
"scientificresearching",
|
||||
|
||||
@@ -924,7 +924,7 @@ FNNS and {"サポート3",
|
||||
{"Finesse(最適化)",
|
||||
"finesse 最適化 効率 操作 初心者 下級者 上達 練習",
|
||||
"term",
|
||||
"ミスなく最低限の操作で目的の場所にミノを移動させる技術\n速さが上がり、ミスも減ります\nJstrisの「restart on finesse error」やTechminoの最適化失敗音を有効にすることで練習できます\n厳密にはTechminoの最適化判定は「理論上の最小入力数」ではなく、「ソフトドロップを必要としない位置の時、一定回数以下の入力かどうか」で判定しています\nそのためソフトドロップが必要なspinなどの時は最適化の判定を行っていません\nまたホールドと操作ミノが同じ時にホールドをしたり、ホールドする前のミノを無駄に動かしても最適化が失敗しているとは判定されません\nまたTechminoの最適化率は一定回数以下の場合100%、一定回数より入力が1多い場合50%、入力が2多い場合25%、入力が3以上多い場合0%とされています\nまた0Gと20Gで最適化の算出方法を変えていないため落下速度が速い時は不正確なことに注意してください",
|
||||
"ミスなく最低限の操作で目的の場所にミノを移動させる技術\n速さが上がり、ミスも減ります\nJstrisの「restart on finesse error」やTechminoの最適化失敗音を有効にすることで練習できます\n厳密にはTechminoの最適化判定は「理論上の最小入力数」ではなく、「ソフトドロップを必要としない位置の時、一定回数以下の入力かどうか」で判定しています\nそのためソフトドロップが必要なspinなどの時は最適化の判定を行っていません\nまたTechminoの最適化率は一定回数以下の場合100%、一定回数より入力が1多い場合50%、入力が2多い場合25%、入力が3以上多い場合0%とされています\nまた0Gと20Gで最適化の算出方法を変えていないため落下速度が速い時は不正確なことに注意してください",
|
||||
},
|
||||
{"‘Doing Research’",
|
||||
"scientificresearch 研究 上達 練習 科研",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -457,7 +457,7 @@ FNNS and {"赞助3",
|
||||
{"HPC",
|
||||
"hc clear banqing banquanqing banquanxiao",
|
||||
"term",
|
||||
"Half-PC\nPC(全消)的外延,“下方有剩余方块” 的全消(特别地,如果只消1行则必须不剩余玩家放置的方块),能打出一些攻击和防御(Techmino限定)。",
|
||||
"Half PC\nPC(全消)的外延,“下方有剩余方块” 的全消(特别地,如果只消1行则必须不剩余玩家放置的方块),能打出一些攻击和防御(Techmino限定)。",
|
||||
},
|
||||
-- # 术语(旋转相关)
|
||||
{"Spin",
|
||||
@@ -816,7 +816,7 @@ FNNS and {"赞助3",
|
||||
{"极简(Finesse)",
|
||||
"极简操作 最简操作 finesse jijiancaozuo zuijiancaozuo",
|
||||
"term",
|
||||
"用最少的按键数将方块移到想去的位置的技术(大多数时候只考虑纯硬降的落点),节约时间和减少Misdrop。\n\n该技能学习越早越好,建议先去找教程视频,看懂了然后自己多练习,开始以准确率第一,速度快慢不重要,熟练后自然就快了。\n\n注意,Techmino使用的极简判定系统不是说完全和理论最少操作数一样,而是不需要软降就能达到的位置才会按照标准出块方向和你的按键次数执行极简检测,故在此不像js存在软降后误杀。但是多了一些新的条件,比如【手上和Hold一样/已经按了超过3次按键后】再hold后按键次数不重置(让下一块极简失误)。\n极简率计算:\n没有超过标准极简法操作数的为Perfect计100%,超出一步为Great计50%,超出两步为Bad计25%,两步以上为Miss计0%,其中Bad和Miss会断连\n\n注1:一般说的极简不考虑带软降/高重力/场地很高的情况,仅研究空中移动/旋转后硬降。绝对理想的“极简”建议使用“最少按键数/操作数”表达。\n注2:20G下极简系统和0G一样工作,所以得到的数值不准确,参考价值偏低。",
|
||||
"用最少的按键数将方块移到想去的位置的技术(大多数时候只考虑纯硬降的落点),节约时间和减少Misdrop。\n\n该技能学习越早越好,建议先去找教程视频,看懂了然后自己多练习,开始以准确率第一,速度快慢不重要,熟练后自然就快了。\n\n注意,Techmino使用的极简判定系统不是说完全和理论最少操作数一样,而是不需要软降就能达到的位置才会按照标准出块方向和你的按键次数执行极简检测,故在此不像js存在软降后误杀。但是多了一些新的条件,比如已经按了超过3次按键后再hold后按键次数不重置(让下一块极简失误)。\n极简率计算:\n没有超过标准极简法操作数的为Perfect计100%,超出一步为Great计50%,超出两步为Bad计25%,两步以上为Miss计0%,其中Bad和Miss会断连\n\n注1:一般说的极简不考虑带软降/高重力/场地很高的情况,仅研究空中移动/旋转后硬降。绝对理想的“极简”建议使用“最少按键数/操作数”表达。\n注2:20G下极简系统和0G一样工作,所以得到的数值不准确,参考价值偏低。",
|
||||
},
|
||||
{"科研",
|
||||
"keyan",
|
||||
|
||||
@@ -28,7 +28,7 @@ return {
|
||||
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",
|
||||
PC="Perfect Clear",HPC="Half PC",
|
||||
replaying="[Replay]",
|
||||
tasUsing="[TAS]",
|
||||
|
||||
@@ -43,6 +43,7 @@ return {
|
||||
infHeightOn="Infinite Height ON",
|
||||
infHeightOff="Infinite Height OFF",
|
||||
infHeightHint="Toggle with Function 1 key",
|
||||
highest="(highest: $1)",
|
||||
|
||||
speedLV="Speed Level",
|
||||
piece="Piece",line="Lines",atk="Attack",eff="Efficiency",
|
||||
@@ -54,7 +55,7 @@ return {
|
||||
|
||||
win="Win!",
|
||||
lose="Lose",
|
||||
|
||||
torikan="Ended",
|
||||
finish="Finished",
|
||||
gamewin="You Won",
|
||||
gameover="Game Over",
|
||||
@@ -66,10 +67,13 @@ return {
|
||||
|
||||
page="Page ",
|
||||
|
||||
ai_puzzle="AI is incompatible with puzzle game mode",
|
||||
ai_mission="AI is incompatible with custom missions.",
|
||||
ai_badPiece="AI is incompatible with custom sequences that contain non-tetrominoes.",
|
||||
cc_fixed="CC is incompatible with fixed sequences.",
|
||||
cc_swap="CC is incompatible when the hold mode is set to Swap.",
|
||||
ai_prebag="AI is incompatible with custom sequences that contain non-tetrominoes.",
|
||||
ai_mission="AI is incompatible with custom missions.",
|
||||
cc_solid="CC is incompatible with filled line in the field.",
|
||||
cc_field_too_high="CC is incompatible with fields higher than 40.",
|
||||
switchSpawnSFX="Please turn on the block spawn SFX!",
|
||||
needRestart="Restart to apply all changes.",
|
||||
|
||||
@@ -91,6 +95,8 @@ return {
|
||||
dataCorrupted="Data corrupted",
|
||||
pasteWrongPlace="Did you paste in the wrong place?",
|
||||
noFile="File missing",
|
||||
invalidSequence="Invalid sequence mode",
|
||||
tooHighField="Field data exceeded 126 lines discarded",
|
||||
|
||||
nowPlaying="Now playing:",
|
||||
|
||||
@@ -233,7 +239,7 @@ return {
|
||||
"Pieces:",
|
||||
"Row/Dig:",
|
||||
"Attack/DigAtk:",
|
||||
"Received:",
|
||||
"Rise(Receive-Offset):",
|
||||
"Clears:",
|
||||
"Spins:",
|
||||
"B2B/B3B/PC/HPC:",
|
||||
@@ -247,7 +253,7 @@ return {
|
||||
"Play Time:",
|
||||
"Key/Rot./Hold:",
|
||||
"Block/Row/Atk.:",
|
||||
"Recv./Res./Asc.:",
|
||||
"Receive/Offset/Rise:",
|
||||
"Dig/Dig Atk.:",
|
||||
"Eff./Dig Eff.:",
|
||||
"B2B/B3B:",
|
||||
@@ -329,6 +335,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -412,7 +419,7 @@ B. Keyboard
|
||||
|
||||
C. Gamepad
|
||||
- Press $10 to display Help
|
||||
- Press $5 or $6 to scroll through the text, speed up with $11
|
||||
- Press $5 or $6 to scroll through the text
|
||||
- Press $7 to open the previous entry and $8 to open the next entry. Speed up with $11
|
||||
- Hold $11 and press $6 to decrease the font size or $5 to increase
|
||||
]]
|
||||
@@ -498,7 +505,7 @@ C. Gamepad
|
||||
capacity="Capacity",
|
||||
create="Create",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="No B2B Breaks",
|
||||
lockout="Fail on Lock Out",
|
||||
@@ -506,7 +513,7 @@ C. Gamepad
|
||||
deepDrop="Deep Drop",
|
||||
bone="Bone Blocks",
|
||||
|
||||
eventSet="Rule Set",
|
||||
eventSet="Ruleset",
|
||||
|
||||
holdMode="Hold Mode",
|
||||
nextCount="Next",
|
||||
@@ -580,7 +587,11 @@ C. Gamepad
|
||||
|
||||
bg_on="Normal B.G.",
|
||||
bg_off="No B.G.",
|
||||
bg_custom="Use Custom B.G.",
|
||||
bg_custom="Custom B.G.",
|
||||
defaultBG="Default B.G.",
|
||||
resetDbg="Reset to default",
|
||||
lockBG="Lock B.G.",
|
||||
noTheme="Disable theme",
|
||||
|
||||
blockSatur="Block Saturation",
|
||||
fieldSatur="Field Saturation",
|
||||
@@ -698,7 +709,7 @@ C. Gamepad
|
||||
sequence="Edit Sequences (S)",
|
||||
mission="Edit Missions (M)",
|
||||
|
||||
eventSet="Rule Set",
|
||||
eventSet="Ruleset",
|
||||
|
||||
holdMode="Hold Mode",
|
||||
nextCount="Next",
|
||||
@@ -716,7 +727,7 @@ C. Gamepad
|
||||
|
||||
bufferLimit="Buffer Limit",
|
||||
heightLimit="Height Limit",
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-Spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="No B2B Breaks",
|
||||
lockout="Fail on Lock Out",
|
||||
@@ -866,7 +877,9 @@ C. Gamepad
|
||||
['sprintPenta']= {"Sprint", "PENTOMINO", "40L with the 18 pentominoes"},
|
||||
['sprintMPH']= {"Sprint", "MPH", "Memoryless\nPreviewless\nHoldless"},
|
||||
['sprint123']= {"Sprint", "M123", "40L with only monominoes, dominoes, and triminoes"},
|
||||
['secret_grade']= {"Secret Grade", "", "Building a zigzag shape by following the guide!"},
|
||||
['construct_sg']= {"Construct", "SECRET GRADE", "Build a zigzag pattern by following the guide!"},
|
||||
['construct_checker']= {"Construct", "CHECKERBOARD", "Build a checkerboard pattern!"},
|
||||
['construct_invsg']= {"Construct", "INV. SG", "Build an inverted zigzag pattern!"},
|
||||
['dig_10l']= {"Dig", "10L", "Dig 10 garbage lines as fast as you can!"},
|
||||
['dig_40l']= {"Dig", "40L", "Dig 40 garbage lines as fast as you can!"},
|
||||
['dig_100l']= {"Dig", "100L", "Dig 100 garbage lines as fast as you can!"},
|
||||
@@ -885,12 +898,12 @@ C. Gamepad
|
||||
['solo_h']= {"Battle", "HARD", "Defeat the AI!"},
|
||||
['solo_l']= {"Battle", "LUNATIC", "Defeat the AI!"},
|
||||
['solo_u']= {"Battle", "ULTIMATE", "Defeat the AI!"},
|
||||
['techmino49_e']= {"Tech 49", "EASY", "49-player battle.\nThe last one standing wins"},
|
||||
['techmino49_h']= {"Tech 49", "HARD", "49-player battle.\nThe last one standing wins"},
|
||||
['techmino49_u']= {"Tech 49", "ULTIMATE", "49-player battle.\nThe last one standing wins"},
|
||||
['techmino99_e']= {"Tech 99", "EASY", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino99_h']= {"Tech 99", "HARD", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino99_u']= {"Tech 99", "ULTIMATE", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino49_e']= {"Tech VS 49", "EASY", "49-player battle.\nThe last one standing wins"},
|
||||
['techmino49_h']= {"Tech VS 49", "HARD", "49-player battle.\nThe last one standing wins"},
|
||||
['techmino49_u']= {"Tech VS 49", "ULTIMATE", "49-player battle.\nThe last one standing wins"},
|
||||
['techmino99_e']= {"Tech VS 99", "EASY", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino99_h']= {"Tech VS 99", "HARD", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino99_u']= {"Tech VS 99", "ULTIMATE", "99-player battle.\nThe last one standing wins"},
|
||||
['round_e']= {"Turn-Based", "EASY", "Take turns to play against the AI!"},
|
||||
['round_n']= {"Turn-Based", "NORMAL", "Take turns to play against the AI!"},
|
||||
['round_h']= {"Turn-Based", "HARD", "Take turns to play against the AI!"},
|
||||
@@ -929,8 +942,8 @@ C. Gamepad
|
||||
['survivor_u']= {"Survival", "ULTIMATE", "How long can you survive?"},
|
||||
['attacker_h']= {"Attacker", "HARD", "Practice your attacking skills!"},
|
||||
['attacker_u']= {"Attacker", "ULTIMATE", "Practice your attacking skills!"},
|
||||
['defender_n']= {"Defender", "NORMAL", "Practice your defensing skills!"},
|
||||
['defender_l']= {"Defender", "LUNATIC", "Practice your defensing skills!"},
|
||||
['defender_n']= {"Defender", "NORMAL", "Practice your defending skills!"},
|
||||
['defender_l']= {"Defender", "LUNATIC", "Practice your defending skills!"},
|
||||
['dig_h']= {"Driller", "HARD", "Digging practice!"},
|
||||
['dig_u']= {"Driller", "ULTIMATE", "Digging practice!"},
|
||||
['c4wtrain_n']= {"C4W Training", "NORMAL", "Infinite combos"},
|
||||
@@ -941,16 +954,14 @@ C. Gamepad
|
||||
['pc_h']= {"PC Challenge", "HARD", "Get PCs within 100 lines!"},
|
||||
['pc_l']= {"PC Challenge", "LUNATIC", "Get PCs within 100 lines!"},
|
||||
['pc_inf']= {"Inf. PC Challenge", "", "Get PCs as much as you can"},
|
||||
['tech_n']= {"Tech", "NORMAL", "Try to keep the\nBack-to-Back chain!"},
|
||||
['tech_n_plus']= {"Tech", "NORMAL+", "Spins & PCs only"},
|
||||
['tech_h']= {"Tech", "HARD", "Try to keep the\nBack-to-Back chain!"},
|
||||
['tech_h_plus']= {"Tech", "HARD+", "Spins & PCs only"},
|
||||
['tech_l']= {"Tech", "LUNATIC", "Try to keep the\nBack-to-Back chain!"},
|
||||
['tech_l_plus']= {"Tech", "LUNATIC+", "Spins & PCs only"},
|
||||
['tech_finesse']= {"Tech", "FINESSE", "No finesse errors!"},
|
||||
['tech_finesse_f']= {"Tech", "FINESSE+", "No normal clears and finesse errors!"},
|
||||
['tech_finesse_lock']= {"Tech", "FINESSE LOCK", "No finesse errors, combined with limited inputs!"},
|
||||
['tech_finesse_lock_f']= {"Tech", "FINESSE+ LOCK", "No normal clears or finesse errors combined with limited inputs!"},
|
||||
['tech_n']= {"Tech B2B", "NORMAL", "Try to keep the\nBack-to-Back chain!"},
|
||||
['tech_n_plus']= {"Tech B2B", "NORMAL+", "Spins & PCs only"},
|
||||
['tech_h']= {"Tech B2B", "HARD", "Try to keep the\nBack-to-Back chain!"},
|
||||
['tech_h_plus']= {"Tech B2B", "HARD+", "Spins & PCs only"},
|
||||
['tech_l']= {"Tech B2B", "LUNATIC", "Try to keep the\nBack-to-Back chain!"},
|
||||
['tech_l_plus']= {"Tech B2B", "LUNATIC+", "Spins & PCs only"},
|
||||
['tech_finesse']= {"Tech Finesse", "", "No finesse errors!"},
|
||||
['tech_finesse_f']= {"Tech Finesse", "PLUS", "No normal clears and finesse errors!"},
|
||||
['tsd_e']= {"TSD Challenge", "EASY", "T-Spin Doubles only!"},
|
||||
['tsd_h']= {"TSD Challenge", "HARD", "T-Spin Doubles only!"},
|
||||
['tsd_u']= {"TSD Challenge", "ULTIMATE", "T-Spin Doubles only!"},
|
||||
|
||||
@@ -27,7 +27,7 @@ return {
|
||||
clear={"Single","Doble","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
cleared="$1 líneas",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Half Clear",
|
||||
PC="Perfect Clear",HPC="Half PC",
|
||||
replaying="[Repetición]",
|
||||
tasUsing="[TAS]",
|
||||
|
||||
@@ -42,6 +42,7 @@ return {
|
||||
-- infHeightOn="Infinite Height ON",
|
||||
-- infHeightOff="Infinite Height OFF",
|
||||
-- infHeightHint="Toggle with Function 1 key",
|
||||
-- highestGrade="(highest: $1)",
|
||||
|
||||
speedLV="Veloc. de juego",
|
||||
piece="Piezas",line="Líneas",atk="Ataque",eff="Eficiencia",
|
||||
@@ -53,7 +54,7 @@ return {
|
||||
|
||||
win="¡Victoria!",
|
||||
lose="Derrota",
|
||||
|
||||
--torikan="Ended",
|
||||
finish="Finalizado",
|
||||
gamewin="Has ganado",
|
||||
gameover="Fin del Juego",
|
||||
@@ -65,10 +66,13 @@ return {
|
||||
|
||||
page="Página:",
|
||||
|
||||
-- ai_puzzle="AI is incompatible with puzzle game mode",
|
||||
ai_mission="La IA no es compatible con misiones personalizadas.",
|
||||
ai_badPiece="La IA no es compatible con piezas que no sean Tetrominos.",
|
||||
cc_fixed="CC no es compatible con piezas prefijadas",
|
||||
cc_swap="CC no es compatible con Swap Hold",
|
||||
ai_prebag="La IA no es compatible con piezas que no sean Tetrominos.",
|
||||
ai_mission="La IA no es compatible con misiones personalizadas.",
|
||||
-- cc_solid="CC is incompatible with filled line in the field.",
|
||||
-- cc_field_too_high="CC is incompatible with fields higher than 40.",
|
||||
switchSpawnSFX="Habilita los sonidos de aparición de las piezas ;)",
|
||||
needRestart="Reinicia para aplicar los cambios.",
|
||||
|
||||
@@ -90,6 +94,8 @@ return {
|
||||
dataCorrupted="Los datos están corruptos.",
|
||||
pasteWrongPlace="¿Pegaste en la carpeta correcta?",
|
||||
noFile="Archivo no encontrado",
|
||||
-- invalidSequence="Invalid sequence mode",
|
||||
-- tooHighField="Field data exceeded 126 lines discarded",
|
||||
|
||||
nowPlaying="Reproduciendo:",
|
||||
|
||||
@@ -232,7 +238,7 @@ return {
|
||||
"Piezas:",
|
||||
"Altura/Limpiado:",
|
||||
"Ataque Enviado:",
|
||||
"Ataque Recibido:",
|
||||
"Ataque Recibido:",-- "Rise(Receive-Offset):",
|
||||
"Líneas Limpiadas:",
|
||||
"Spins:",
|
||||
"B2B/B3B/PC/HPC:",
|
||||
@@ -246,7 +252,7 @@ return {
|
||||
"Tiempo de Juego:",
|
||||
"Tecla/Rot./Reserva:",
|
||||
"Bloq./Lín./Atq.:",
|
||||
"Rec./Off./Sub.:",
|
||||
"Rec./Off./Sub.:",-- "Receive/Offset/Rise:",
|
||||
"Limp./Atq. Limp.:",
|
||||
"Effic./Eff.Limp.:",
|
||||
"Slam/Gr.Slam:",
|
||||
@@ -326,6 +332,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -459,7 +466,7 @@ return {
|
||||
capacity="Capacidad",
|
||||
create="Crear",
|
||||
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-Spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="No Romper B2B ",
|
||||
lockout="Derrota al ocurrir Lock Out",
|
||||
@@ -542,6 +549,10 @@ return {
|
||||
bg_on="Fondo Normal",
|
||||
bg_off="Sin Fondo",
|
||||
bg_custom="Fondo Personalizado",
|
||||
-- defaultBG="Default B.G.",
|
||||
-- resetDbg="Reset to default",
|
||||
-- lockBG="Lock B.G.",
|
||||
-- noTheme="Disable theme",
|
||||
|
||||
blockSatur="Saturac. de los Bloques",
|
||||
fieldSatur="Saturac. del Tablero",
|
||||
@@ -676,7 +687,7 @@ return {
|
||||
|
||||
bufferLimit="Búfer Límite",
|
||||
heightLimit="Altura Límite",
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-Spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="No Romper B2B ",
|
||||
lockout="Derrota al ocurrir Lock Out",
|
||||
@@ -818,7 +829,9 @@ return {
|
||||
['sprintPenta']= {"Sprint", "Pentominos", "¡Limpia 40 líneas con los 18 pentominos distintos!"},
|
||||
['sprintMPH']= {"Sprint", "MPH", "Memoryless (sin memoria)\nPreviewless (sin pzas. siguientes)\nHoldless (sin reserva)."},
|
||||
['sprint123']= {"Sprint", "M123", "Limpia 40 líneas con monominos, biminos y triminos"},
|
||||
['secret_grade']= {"Secret Grade", "", "¡Arma dejando huecos en escalera, sigue la guía!"},
|
||||
['construct_sg']= {"Construir", "SECRET GRADE", "¡Arma dejando huecos en escalera, sigue la guía!"},
|
||||
-- ['construct_checker']= {"Construct", "CHECKERBOARD", "Build a checkerboard pattern!"},
|
||||
-- ['construct_invsg']= {"Construct", "INV. SG", "Build an inverted zigzag pattern!"},
|
||||
['dig_10l']= {"Dig", "10L", "¡Limpia 10 líneas de queso lo más rápido que puedas!"},
|
||||
['dig_40l']= {"Dig", "40L", "¡Limpia 40 líneas de queso lo más rápido que puedas!"},
|
||||
['dig_100l']= {"Dig", "100L", "¡Limpia 100 líneas de queso lo más rápido que puedas!"},
|
||||
@@ -837,12 +850,18 @@ return {
|
||||
['solo_h']= {"VS.", "Difícil", "¡Derrota a la CPU!"},
|
||||
['solo_l']= {"VS.", "Lunático", "¡Derrota a la CPU!"},
|
||||
['solo_u']= {"VS.", "Supremo", "¡Derrota a la CPU!"},
|
||||
['techmino49_e']= {"Tech 49", "Fácil", "Batalla de 49 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino49_h']= {"Tech 49", "Difícil", "Batalla de 49 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino49_u']= {"Tech 49", "Supremo", "Batalla de 49 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino99_e']= {"Tech 99", "Fácil", "Batalla de 99 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino99_h']= {"Tech 99", "Difícil", "Batalla de 99 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino99_u']= {"Tech 99", "Supremo", "Batalla de 99 jugadores.\n¡El último en pie gana!"},
|
||||
-- ['techmino49_e']= {"Tech VS 49", "EASY", "49-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino49_h']= {"Tech VS 49", "HARD", "49-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino49_u']= {"Tech VS 49", "ULTIMATE", "49-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino99_e']= {"Tech VS 99", "EASY", "99-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino99_h']= {"Tech VS 99", "HARD", "99-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino99_u']= {"Tech VS 99", "ULTIMATE", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino49_e']= {"Tech VS 49", "Fácil", "Batalla de 49 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino49_h']= {"Tech VS 49", "Difícil", "Batalla de 49 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino49_u']= {"Tech VS 49", "Supremo", "Batalla de 49 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino99_e']= {"Tech VS 99", "Fácil", "Batalla de 99 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino99_h']= {"Tech VS 99", "Difícil", "Batalla de 99 jugadores.\n¡El último en pie gana!"},
|
||||
['techmino99_u']= {"Tech VS 99", "Supremo", "Batalla de 99 jugadores.\n¡El último en pie gana!"},
|
||||
['round_e']= {"Por Turnos", "Fácil", "Modo ajedrez."},
|
||||
['round_n']= {"Por Turnos", "Normal", "Modo ajedrez."},
|
||||
['round_h']= {"Por Turnos", "Difícil", "Modo ajedrez."},
|
||||
@@ -869,7 +888,7 @@ return {
|
||||
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
||||
-- ['blind_l']= {"Invisible", "NO GHOST", "For professionals"},
|
||||
-- ['blind_u']= {"Invisible", "NO FIELD", "Are you ready?"},
|
||||
-- ['blind_wtf']= {"Invisible", "VOID", "You're not ready."},
|
||||
-- ['blind_wtf']= {"Invisible", "VOID", "You're not ready."},
|
||||
['blind_e']= {"A Ciegas", "Parcial", "Para novatos."},
|
||||
['blind_n']= {"A Ciegas", "Total", "Para jugadores intermedios."},
|
||||
['blind_h']= {"A Ciegas", "Inmediato", "Para jugadores experimentados."},
|
||||
@@ -899,16 +918,15 @@ return {
|
||||
['pc_h']= {"Desafío de PCs", "Difícil", "¡Consigue los PCs que puedas en 100 líneas!"},
|
||||
['pc_l']= {"Desafío de PCs", "Lunático", "¡Consigue los PCs que puedas en 100 líneas!"},
|
||||
['pc_inf']= {"Desafío de PCs Infinito", "", "Consigue todos los PCs que puedas."},
|
||||
['tech_n']= {"Tech", "Normal", "¡Mantén el B2B!"},
|
||||
['tech_n_plus']= {"Tech", "Normal+", "¡Sólo se permiten Spins y PCs!"},
|
||||
['tech_h']= {"Tech", "Difícil", "¡Mantén el B2B!"},
|
||||
['tech_h_plus']= {"Tech", "Difícil+", "¡Sólo se permiten Spins y PCs!"},
|
||||
['tech_l']= {"Tech", "Lunático", "¡Mantén el B2B!"},
|
||||
['tech_l_plus']= {"Tech", "Lunático+", "¡Sólo se permiten Spins y PCs!"},
|
||||
['tech_n']= {"Tech B2B", "Normal", "¡Mantén el B2B!"},
|
||||
['tech_n_plus']= {"Tech B2B", "Normal+", "¡Sólo se permiten Spins y PCs!"},
|
||||
['tech_h']= {"Tech B2B", "Difícil", "¡Mantén el B2B!"},
|
||||
['tech_h_plus']= {"Tech B2B", "Difícil+", "¡Sólo se permiten Spins y PCs!"},
|
||||
['tech_l']= {"Tech B2B", "Lunático", "¡Mantén el B2B!"},
|
||||
['tech_l_plus']= {"Tech B2B", "Lunático+", "¡Sólo se permiten Spins y PCs!"},
|
||||
['tech_finesse']= {"Tech", "Finesse", "¡No cometas errores de Finesse!"},
|
||||
-- ['tech_finesse_f']= {"Tech Finesse", "PLUS", "No normal clears and finesse errors!"},
|
||||
['tech_finesse_f']= {"Tech", "Finesse+", "Sin errores de finesse,\n¡pero tampoco clears normales!"},
|
||||
-- ['tech_finesse_lock']= {"Tech", "FINESSE LOCK", "No finesse errors, combined with limited inputs!"},
|
||||
-- ['tech_finesse_lock_f']= {"Tech", "FINESSE+ LOCK", "No normal clears or finesse errors combined with limited inputs!"},
|
||||
['tsd_e']= {"Desafío de TSD", "Fácil", "¡Sólo se permiten T-Spin Dobles!"},
|
||||
['tsd_h']= {"Desafío de TSD", "Difícil", "¡Sólo se permiten T-Spin Dobles!"},
|
||||
['tsd_u']= {"Desafío de TSD", "Supremo", "¡Sólo se permiten T-Spin Dobles!"},
|
||||
|
||||
@@ -27,7 +27,7 @@ return {
|
||||
clear={"Simple","Double","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
-- cleared="$1 lines",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Clear",
|
||||
PC="Perfect Clear",HPC="Half PC",
|
||||
replaying="[Replay]",
|
||||
-- tasUsing="[TAS]",
|
||||
|
||||
@@ -42,6 +42,7 @@ return {
|
||||
-- infHeightOn="Infinite Height ON",
|
||||
-- infHeightOff="Infinite Height OFF",
|
||||
-- infHeightHint="Toggle with Function 1 key",
|
||||
-- highestGrade="(highest: $1)",
|
||||
|
||||
speedLV="niveau de vitesse",
|
||||
piece="Pièce",line="Lignes",atk="Attaque",eff="Efficacité",
|
||||
@@ -54,7 +55,7 @@ return {
|
||||
|
||||
win="Victoire!",
|
||||
lose="Défaite",
|
||||
|
||||
--torikan="Ended",
|
||||
finish="Terminé",
|
||||
gamewin="Gagné !",
|
||||
gameover="Fin du jeu",
|
||||
@@ -66,10 +67,13 @@ return {
|
||||
|
||||
page="Page:",
|
||||
|
||||
-- ai_puzzle="AI is incompatible with puzzle game mode",
|
||||
ai_mission="L'IA est incompatible avec les missions personnalisées.",
|
||||
-- ai_badPiece="The AI is incompatible with custom sequences which have nontetromino.",'IA est incompatible avec les séquences personnalisées.",
|
||||
cc_fixed="CC est incompatible avec les séquences fixes",
|
||||
cc_swap="CC est incompatible avec le mode de maintien du swap",
|
||||
-- ai_prebag="The AI is incompatible with custom sequences which have nontetromino.",'IA est incompatible avec les séquences personnalisées.",
|
||||
ai_mission="L'IA est incompatible avec les missions personnalisées.",
|
||||
-- cc_solid="CC is incompatible with filled line in the field.",
|
||||
-- cc_field_too_high="CC is incompatible with fields higher than 40.",
|
||||
switchSpawnSFX="Activez les effets sonores d'apparition des pièces pour jouer.",
|
||||
needRestart="Redémarrez pour appliquer toutes les modifications.",
|
||||
|
||||
@@ -91,6 +95,8 @@ return {
|
||||
dataCorrupted="Données corrompues",
|
||||
-- pasteWrongPlace="Paste at wrong place?",
|
||||
noFile="Fichier non trouvé",
|
||||
-- invalidSequence="Invalid sequence mode",
|
||||
-- tooHighField="Field data exceeded 126 lines discarded",
|
||||
|
||||
nowPlaying="En train de jouer :",
|
||||
|
||||
@@ -211,7 +217,7 @@ return {
|
||||
"Pièce :",
|
||||
"Lignes/Creuser :",
|
||||
"Attaque/Attaque de creusage :",
|
||||
"Reçu :",
|
||||
"Reçu :",-- "Rise(Receive-Offset):",
|
||||
"Nettoyages :",
|
||||
"Spins :",
|
||||
"B2B/B3B/PC/HPC : ",
|
||||
@@ -225,7 +231,7 @@ return {
|
||||
"Temps de jeu :",
|
||||
"Touche/Rot./Réserve :",
|
||||
"Bloc/Ligne/Atq. :",
|
||||
"Reçu/Res./Asc. :",
|
||||
"Reçu/Res./Asc. :",-- "Receive/Offset/Rise:",
|
||||
"Attaque/Attaque de creusage :",
|
||||
"Eff./Eff. de creusage :",
|
||||
"B2B/B3B :",
|
||||
@@ -304,6 +310,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -434,7 +441,7 @@ return {
|
||||
-- capacity="Capacity",
|
||||
create="Créer",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="Sans perte de B2B",
|
||||
-- lockout="Fail when lock out",
|
||||
@@ -442,7 +449,7 @@ return {
|
||||
-- deepDrop="Deep Drop",
|
||||
bone="Crochets",
|
||||
|
||||
-- eventSet="Rule Set",
|
||||
-- eventSet="Ruleset",
|
||||
|
||||
-- holdMode="Hold Mode",
|
||||
nextCount="Prévisualisations de pièces",
|
||||
@@ -518,6 +525,10 @@ return {
|
||||
bg_on="Arrière-plan normal",
|
||||
bg_off="Pas d'arrière-plan.",
|
||||
bg_custom="Utiliser un arrière-plan personnalisé",
|
||||
-- defaultBG="Default B.G.",
|
||||
-- resetDbg="Reset to default",
|
||||
-- lockBG="Lock B.G.",
|
||||
-- noTheme="Disable theme",
|
||||
|
||||
-- blockSatur="Block Saturation",
|
||||
-- fieldSatur="Field Saturation",
|
||||
@@ -655,7 +666,7 @@ return {
|
||||
|
||||
-- bufferLimit="Buffer Limit",
|
||||
-- heightLimit="Height Limit",
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="Sans perte de B2B",
|
||||
-- lockout="Fail when lock out",
|
||||
@@ -796,6 +807,10 @@ return {
|
||||
['sprint_1000l']= {"Sprint", "1000L", "Nettoyez 1000 lignes !"},
|
||||
['sprintPenta']= {"Sprint", "Pentomino", "40 lignes avec 18 pentominos."},
|
||||
['sprintMPH']= {"Sprint", "MPH", "Memoryless\nPreviewless\nHoldless"},
|
||||
-- ['sprint123']= {"Sprint", "M123", "40L with only monominoes, dominoes, and triminoes"},
|
||||
-- ['construct_sg']= {"Construct", "SECRET GRADE", "Build a zigzag shape by following the guide!"},
|
||||
-- ['construct_checker']= {"Construct", "CHECKERBOARD", "Build a checkerboard pattern!"},
|
||||
-- ['construct_invsg']= {"Construct", "INV. SG", "Build an inverted zigzag pattern!"},
|
||||
['dig_10l']= {"Dig", "10L", "Creusez 10 lignes"},
|
||||
['dig_40l']= {"Dig", "40L", "Creusez 40 lignes"},
|
||||
['dig_100l']= {"Dig", "100L", "Creusez 100 lignes"},
|
||||
@@ -812,12 +827,18 @@ return {
|
||||
['solo_h']= {"Battle", "DIFFICILE", "Battez l'IA !"},
|
||||
['solo_l']= {"Battle", "LUNATIQUE", "Battez l'IA !"},
|
||||
['solo_u']= {"Battle", "ULTIME", "Battez l'IA !"},
|
||||
['techmino49_e']= {"Tech 49", "FACILE", "Bataille de 49 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino49_h']= {"Tech 49", "DIFFICILE", "Bataille de 49 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino49_u']= {"Tech 49", "ULTIME", "Bataille de 49 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino99_e']= {"Tech 99", "FACILE", "Bataille de 99 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino99_h']= {"Tech 99", "DIFFICILE", "Bataille de 99 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino99_u']= {"Tech 99", "ULTIME", "Bataille de 99 joueurs.\nLe dernier en vie gagne."},
|
||||
-- ['techmino49_e']= {"Tech VS 49", "EASY", "49-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino49_h']= {"Tech VS 49", "HARD", "49-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino49_u']= {"Tech VS 49", "ULTIMATE", "49-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino99_e']= {"Tech VS 99", "EASY", "99-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino99_h']= {"Tech VS 99", "HARD", "99-player battle.\nThe last one standing wins"},
|
||||
-- ['techmino99_u']= {"Tech VS 99", "ULTIMATE", "99-player battle.\nThe last one standing wins"},
|
||||
['techmino49_e']= {"Tech VS 49", "FACILE", "Bataille de 49 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino49_h']= {"Tech VS 49", "DIFFICILE", "Bataille de 49 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino49_u']= {"Tech VS 49", "ULTIME", "Bataille de 49 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino99_e']= {"Tech VS 99", "FACILE", "Bataille de 99 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino99_h']= {"Tech VS 99", "DIFFICILE", "Bataille de 99 joueurs.\nLe dernier en vie gagne."},
|
||||
['techmino99_u']= {"Tech VS 99", "ULTIME", "Bataille de 99 joueurs.\nLe dernier en vie gagne."},
|
||||
['round_e']= {"Tour à tour", "FACILE", "Mode échecs"},
|
||||
['round_n']= {"Tour à tour", "NORMAL", "Mode échecs"},
|
||||
['round_h']= {"Tour à tour", "DIFFICILE", "Mode échecs"},
|
||||
@@ -866,20 +887,20 @@ return {
|
||||
['c4wtrain_l']= {"Mode essai C4W", "LUNATIQUE", "Combos infinis."},
|
||||
['pctrain_n']= {"Mode essai PC", "NORMAL", "Mode Perfect Clear simple"},
|
||||
['pctrain_l']= {"Mode essai PC", "LUNATIQUE", "Mode Perfect Clear dur"},
|
||||
['pc_n']= {"Défi PC", "NORMAL", "Obtenez un PC dans les prochaines 100 lignes !"},
|
||||
['pc_h']= {"Défi PC", "DIFFICILE", "Obtenez un PC dans les prochaines 100 lignes !"},
|
||||
['pc_l']= {"Défi PC", "LUNATIQUE", "Obtenez un PC dans les prochaines 100 lignes !"},
|
||||
['pc_inf']= {"Défi PC infini","Infini", "Obtenez autant de PC que possible"},
|
||||
['tech_n']= {"Tech", "NORMAL", "Gardez le B2B !"},
|
||||
['tech_n_plus']= {"Tech", "NORMAL+", "Spin & PC uniquement"},
|
||||
['tech_h']= {"Tech", "DIFFICILE", "Gardez le B2B !"},
|
||||
['tech_h_plus']= {"Tech", "HARD+", "Spin & PC uniquement"},
|
||||
['tech_l']= {"Tech", "LUNATIQUE", "Gardez le B2B !"},
|
||||
['tech_l_plus']= {"Tech", "LUNATIQUE+", "Spin & PC uniquement"},
|
||||
['pc_n']= {"Défi PC", "NORMAL", "Obtenez un PC dans les prochaines 100 lignes !"},
|
||||
['pc_h']= {"Défi PC", "DIFFICILE", "Obtenez un PC dans les prochaines 100 lignes !"},
|
||||
['pc_l']= {"Défi PC", "LUNATIQUE", "Obtenez un PC dans les prochaines 100 lignes !"},
|
||||
['pc_inf']= {"Défi PC infini", "INFINI", "Obtenez autant de PC que possible"},
|
||||
['tech_n']= {"Tech B2B", "NORMAL", "Gardez le B2B !"},
|
||||
['tech_n_plus']= {"Tech B2B", "NORMAL+", "Spin & PC uniquement"},
|
||||
['tech_h']= {"Tech B2B", "DIFFICILE", "Gardez le B2B !"},
|
||||
['tech_h_plus']= {"Tech B2B", "HARD+", "Spin & PC uniquement"},
|
||||
['tech_l']= {"Tech B2B", "LUNATIQUE", "Gardez le B2B !"},
|
||||
['tech_l_plus']= {"Tech B2B", "LUNATIQUE+", "Spin & PC uniquement"},
|
||||
-- ['tech_finesse']= {"Tech Finesse", "", "No finesse errors!"},
|
||||
-- ['tech_finesse_f']= {"Tech Finesse", "PLUS", "No normal clears and finesse errors!"},
|
||||
['tech_finesse']= {"Tech", "FINESSE", "Pas d'erreurs de finesse !"},
|
||||
['tech_finesse_f']={"Tech", "FINESSE+", "Pas de nettoyages normaux,\nPas d'erreurs de finesse !"},
|
||||
--['tech_finesse_lock']= {"Tech", "FINESSE LOCK", "No finesse errors, combined with limited inputs!"},
|
||||
--['tech_finesse_lock_f']= {"Tech", "FINESSE+ LOCK", "No normal clears or finesse errors combined with limited inputs!"},
|
||||
['tsd_e']= {"TSD Challenge", "FACILE", "T-spin doubles uniquement !"},
|
||||
['tsd_h']= {"TSD Challenge", "DIFFICILE", "T-spin doubles uniquement !"},
|
||||
['tsd_u']= {"TSD Challenge", "ULTIME", "T-spin doubles uniquement !"},
|
||||
|
||||
@@ -44,6 +44,7 @@ return {
|
||||
infHeightOn="Ketinggian Tak Terhingga ON",
|
||||
infHeightOff="Ketinggian Tak Terhingga OFF",
|
||||
infHeightHint="Ubah dengan tombol Fungsi 1",
|
||||
highestGrade="(tertinggi: $1)",
|
||||
|
||||
speedLV="Kecptn lvl",
|
||||
piece="Blok",line="Baris",atk="Baris Terkirim",eff="Efisiensi",
|
||||
@@ -55,7 +56,7 @@ return {
|
||||
|
||||
win="Menang!",
|
||||
lose="Kalah",
|
||||
|
||||
torikan="Tamat",
|
||||
finish="Selesai",
|
||||
gamewin="Anda menang!",
|
||||
gameover="Tamat",
|
||||
@@ -67,10 +68,13 @@ return {
|
||||
|
||||
page="Halaman: ",
|
||||
|
||||
-- ai_puzzle="AI is incompatible with puzzle game mode",
|
||||
ai_mission="AI tidak cocok dengan misi terubah.",
|
||||
ai_badPiece="AI tidak cocok dengan urutan terubah yang memiliki non-tetromino.",
|
||||
cc_fixed="CC tidak cocok dengan urutan tetap.",
|
||||
cc_swap="CC tidak cocok dengan mode simpan tukar.",
|
||||
ai_prebag="AI tidak cocok dengan urutan terubah yang memiliki non-tetromino.",
|
||||
ai_mission="AI tidak cocok dengan misi terubah.",
|
||||
-- cc_solid="CC is incompatible with filled line in the field.",
|
||||
-- cc_field_too_high="CC is incompatible with fields higher than 40.",
|
||||
switchSpawnSFX="Nyalakan efek suara munculan blok!",
|
||||
needRestart="Ulangi untuk menerapkan perubahan.",
|
||||
|
||||
@@ -92,6 +96,8 @@ return {
|
||||
dataCorrupted="Data rusak",
|
||||
pasteWrongPlace="Apakah Anda menempelkannya di tempat yang salah?",
|
||||
noFile="File tidak ada",
|
||||
-- invalidSequence="Invalid sequence mode",
|
||||
-- tooHighField="Field data exceeded 126 lines discarded",
|
||||
|
||||
nowPlaying="Musik:",
|
||||
|
||||
@@ -233,7 +239,7 @@ return {
|
||||
"Blok:",
|
||||
"Baris/Baris Gali:",
|
||||
"Serangan/Serangan Gali:",
|
||||
"Diterima:",
|
||||
"Diterima:",-- "Rise(Receive-Offset):",
|
||||
"Baris:",
|
||||
"Spins:",
|
||||
"B2B/B3B/PC/Setengah PC:",
|
||||
@@ -247,7 +253,7 @@ return {
|
||||
"Jumlah Waktu Bermain:",
|
||||
"Tombol/Putar/Simpan:",
|
||||
"Blok/Baris/Serangan:",
|
||||
"Serangan Diterima/Ditolak/Muncul:",
|
||||
"Serangan Diterima/Ditolak/Muncul:",-- "Receive/Offset/Rise:",
|
||||
"Gali/Serangan Gali:",
|
||||
"Efisiensi/Efisiensi Gali:",
|
||||
"B2B/B2B2B:",
|
||||
@@ -327,6 +333,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -460,7 +467,7 @@ return {
|
||||
capacity="Kapasitas",
|
||||
create="Buat",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Efisiensi Tombol",
|
||||
b2bKill="Akhirkan Permainan Jika Tidak B2B",
|
||||
lockout="Akhirkan Permainan Jika Lock Out",
|
||||
@@ -543,6 +550,10 @@ return {
|
||||
bg_on="B.G. Normal",
|
||||
bg_off="Tidak Ada B.G.",
|
||||
bg_custom="Ubah B.G.",
|
||||
-- defaultBG="Default B.G.",
|
||||
-- resetDbg="Reset to default",
|
||||
-- lockBG="Lock B.G.",
|
||||
-- noTheme="Disable theme",
|
||||
|
||||
blockSatur="Kejenuhan Blok Aktif",
|
||||
fieldSatur="Kejenuhan Blok Terkunci",
|
||||
@@ -678,7 +689,7 @@ return {
|
||||
|
||||
bufferLimit="Batas Serangan",
|
||||
heightLimit="Batas Tinggi",
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="Maksimum Efisiensi Tombol",
|
||||
b2bKill="Akhirkan Permainan Jika Tidak B2B",
|
||||
lockout="Akhirkan Permainan Jika Lock Out",
|
||||
@@ -828,7 +839,9 @@ return {
|
||||
['sprintPenta']= {"Balapan", "PENTOMINO", "40L dengan pentomino!"},
|
||||
['sprintMPH']= {"Balapan", "MPH", "Tanpa ingatan\nTanpa pratinjau\nTanpa simpan"},
|
||||
['sprint123']= {"Balapan", "M123", "40L dengan hanya monomino, domino, dan trimino"},
|
||||
['secret_grade']= {"Secret Grade", "", "Buatlah formasi lubang zigzag, menuruti panduannya!"},
|
||||
['construct_sg']= {"Membangun", "SECRET GRADE", "Buatlah formasi lubang zigzag, menuruti panduannya!"},
|
||||
['construct_checker']= {"Membangun", "KOTAK-KOTAK", "Buatlah pola kotak-kotak!"},
|
||||
['construct_invsg']= {"Membangun", "SG TERBALIK", "Buatlah pola zigzag terbalik!"},
|
||||
['dig_10l']= {"Gali", "10L", "Gali 10 baris!"},
|
||||
['dig_40l']= {"Gali", "40L", "Gali 40 baris!"},
|
||||
['dig_100l']= {"Gali", "100L", "Gali 100 baris!"},
|
||||
@@ -847,12 +860,12 @@ return {
|
||||
['solo_h']= {"Tarung", "SULIT", "Kalahkan AInya!"},
|
||||
['solo_l']= {"Tarung", "GILA", "Kalahkan AInya!"},
|
||||
['solo_u']= {"Tarung", "TERAKHIR", "Kalahkan AInya!"},
|
||||
['techmino49_e']= {"Tech 49", "MUDAH", "Pertarungan dengan 49 pemain."},
|
||||
['techmino49_h']= {"Tech 49", "SULIT", "Pertarungan dengan 49 pemain."},
|
||||
['techmino49_u']= {"Tech 49", "TERAKHIR", "Pertarungan dengan 49 pemain."},
|
||||
['techmino99_e']= {"Tech 99", "MUDAH", "Pertarungan dengan 99 pemain."},
|
||||
['techmino99_h']= {"Tech 99", "SULIT", "Pertarungan dengan 99 pemain."},
|
||||
['techmino99_u']= {"Tech 99", "TERAKHIR", "Pertarungan dengan 99 pemain."},
|
||||
['techmino49_e']= {"Tech VS 49", "MUDAH", "Pertarungan dengan 49 pemain."},
|
||||
['techmino49_h']= {"Tech VS 49", "SULIT", "Pertarungan dengan 49 pemain."},
|
||||
['techmino49_u']= {"Tech VS 49", "TERAKHIR", "Pertarungan dengan 49 pemain."},
|
||||
['techmino99_e']= {"Tech VS 99", "MUDAH", "Pertarungan dengan 99 pemain."},
|
||||
['techmino99_h']= {"Tech VS 99", "SULIT", "Pertarungan dengan 99 pemain."},
|
||||
['techmino99_u']= {"Tech VS 99", "TERAKHIR", "Pertarungan dengan 99 pemain."},
|
||||
['round_e']= {"Giliran", "MUDAH", "Giliran main melawan AI!"},
|
||||
['round_n']= {"Giliran", "NORMAL", "Giliran main melawan AI!"},
|
||||
['round_h']= {"Giliran", "SULIT", "Giliran main melawan AI!"},
|
||||
@@ -903,16 +916,14 @@ return {
|
||||
['pc_h']= {"Tantangan PC", "SULIT", "Dapatkan PC sampai 100 baris!"},
|
||||
['pc_l']= {"Tantangan PC", "GILA", "Dapatkan PC sampai 100 baris!"},
|
||||
['pc_inf']= {"Tantangan PC", "TAK TERBATAS", "Dapatkan PC sebanyaknya!"},
|
||||
['tech_n']= {"Tech", "NORMAL", "Coba jaga deret Back-To-Back!"},
|
||||
['tech_n_plus']= {"Tech", "NORMAL+", "Hanya Spins & PCs dibolehkan"},
|
||||
['tech_h']= {"Tech", "SULIT", "Coba jaga deret Back-To-Back!"},
|
||||
['tech_h_plus']= {"Tech", "SULIT+", "Hanya Spins & PCs dibolehkan"},
|
||||
['tech_l']= {"Tech", "GILA", "Coba jaga deret Back-To-Back!"},
|
||||
['tech_l_plus']= {"Tech", "GILA+", "Hanya Spins & PCs dibolehkan"},
|
||||
['tech_n']= {"Tech B2B", "NORMAL", "Coba jaga deret Back-To-Back!"},
|
||||
['tech_n_plus']= {"Tech B2B", "NORMAL+", "Hanya Spins & PCs dibolehkan"},
|
||||
['tech_h']= {"Tech B2B", "SULIT", "Coba jaga deret Back-To-Back!"},
|
||||
['tech_h_plus']= {"Tech B2B", "SULIT+", "Hanya Spins & PCs dibolehkan"},
|
||||
['tech_l']= {"Tech B2B", "GILA", "Coba jaga deret Back-To-Back!"},
|
||||
['tech_l_plus']= {"Tech B2B", "GILA+", "Hanya Spins & PCs dibolehkan"},
|
||||
['tech_finesse']= {"Tech", "EF. TOMBOL", "Efisiensi tombol harus maksimal!"},
|
||||
['tech_finesse_f']= {"Tech", "EF. TOMBOL+", "Efisiensi tombol maksimal dan anda tidak boleh membuat baris normal!"},
|
||||
['tech_finesse_lock']= {"Tech", "EF. TBL. TERBATAS", "Jumlah pemencetan tombol terbatas, dan efisiensinya harus maksimal!"},
|
||||
['tech_finesse_lock_f']= {"Tech", "EF. TBL.+ TERBATAS", "Jumlah pemencetan tombol terbatas, efisiensi tombol harus maksimal, dan anda tidak boleh membuat baris normal!"},
|
||||
['tsd_e']= {"Tantangan TSD", "MUDAH", "Hanya T-Spin Double dibolehkan!"},
|
||||
['tsd_h']= {"Tantangan TSD", "SULIT", "Hanya T-Spin Double dibolehkan!"},
|
||||
['tsd_u']= {"Tantangan TSD", "TERAKHIR", "Hanya T-Spin Double dibolehkan!"},
|
||||
|
||||
@@ -44,6 +44,7 @@ return {
|
||||
infHeightOn="高度無限!",
|
||||
infHeightOff="高度制限あり",
|
||||
infHeightHint="“ファンクション 1”キー",
|
||||
highestGrade="(最高ランク: $1)",
|
||||
|
||||
speedLV="レベル",
|
||||
piece="ミノ数",line="line数",atk="火力",eff="効率",
|
||||
@@ -55,9 +56,9 @@ return {
|
||||
|
||||
win="Win!",
|
||||
lose="Lose",
|
||||
|
||||
finish="Finished",
|
||||
gamewin="You Won",
|
||||
torikan="Ended",
|
||||
finish="Finished!",
|
||||
gamewin="You Win!",
|
||||
gameover="Game Over",
|
||||
|
||||
pause="ポーズ",
|
||||
@@ -67,10 +68,13 @@ return {
|
||||
|
||||
page="ページ:",
|
||||
|
||||
ai_puzzle="AIはパズルゲームモードに非対応です!",
|
||||
ai_mission="AIはカスタムミッションに非対応です!",
|
||||
ai_badPiece="AIは通常のテトロミノ以外やミノ順指定に非対応です!",
|
||||
cc_fixed="CCはミノ順の指定に非対応です!",
|
||||
cc_swap="CCはホールドモード、Swapに非対応です!",
|
||||
ai_prebag="AIは通常のテトロミノ以外やミノ順指定に非対応です!",
|
||||
ai_mission="AIはカスタムミッションに非対応です!",
|
||||
cc_solid="CCはLineが揃っている盤面に非対応です!",
|
||||
cc_field_too_high="CCは高さ40以上の盤面に非対応です!",
|
||||
switchSpawnSFX="ブロック出現時の効果音をONにしてください!",
|
||||
needRestart="すべての変更を適用する為にリスタートしてください!",
|
||||
|
||||
@@ -92,6 +96,8 @@ return {
|
||||
dataCorrupted="データが破損してます",
|
||||
pasteWrongPlace="貼り付ける位置を間違っていませんか?",
|
||||
noFile="ファイルが見つかりません",
|
||||
invalidSequence="無効な出現法則です",
|
||||
tooHighField="フィールドの高さは126段までです",
|
||||
|
||||
nowPlaying="再生中:",
|
||||
|
||||
@@ -259,11 +265,12 @@ return {
|
||||
"これは“ただの”落ちものパズルゲームです。本当ですよ",
|
||||
"C2/IO/JS/WWC/KOS等からアイデアを得ました",
|
||||
"",
|
||||
"「LÖVE」搭載",
|
||||
"powered by LÖVE",
|
||||
"ご意見、ご感想、バグ報告など、全て大歓迎です!",
|
||||
"ゲームは、必ず公式から入手してください",
|
||||
"他から入手した場合は、安全性を保証しません",
|
||||
"同時に制作者は、責任を負いません",
|
||||
"Techminoは振動とインターネット接続の許可しか求めません",
|
||||
"また制作者は、責任を負いません",
|
||||
FNNS and "/" or "ゲームは無料ですが寄付してくださると嬉しいです!",
|
||||
FNNS and "/" or "詳しくはZictionaryをご覧ください",
|
||||
},
|
||||
@@ -328,6 +335,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -416,7 +424,7 @@ B. キーボード
|
||||
|
||||
C. ゲームパッド
|
||||
- $10でヘルプを表示
|
||||
- $5または、$6でテキストをスクロール($11を押しながらだとスクロールが速くなります)
|
||||
- $5または、$6でテキストをスクロール
|
||||
- $7または、$8で項目をスクロール($11を押しながらだとスクロールが速くなります)
|
||||
- $11を押しながら$6または、$5でフォントサイズ変更
|
||||
]]
|
||||
@@ -503,7 +511,7 @@ C. ゲームパッド
|
||||
capacity="試合人数",
|
||||
create="作成",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="最適化のみ",
|
||||
b2bKill="B2B継続",
|
||||
lockout="盤面外設置禁止",
|
||||
@@ -586,6 +594,10 @@ C. ゲームパッド
|
||||
bg_on="通常背景",
|
||||
bg_off="背景なし ",
|
||||
bg_custom="カスタム背景",
|
||||
defaultBG="デフォルト背景",
|
||||
resetDbg="背景リセット",
|
||||
lockBG="背景固定",
|
||||
noTheme="テーマ無効化",
|
||||
|
||||
blockSatur="ブロックデザイン",
|
||||
fieldSatur="設置ブロックデザイン",
|
||||
@@ -721,7 +733,7 @@ C. ゲームパッド
|
||||
|
||||
bufferLimit="ダメージの保持上限",
|
||||
heightLimit="致死ラインの高さ",
|
||||
ospin="Oスピン",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="最適化のみ",
|
||||
b2bKill="B2B継続",
|
||||
lockout="盤面外設置禁止",
|
||||
@@ -862,117 +874,117 @@ C. ゲームパッド
|
||||
},
|
||||
},
|
||||
modes={
|
||||
['sprint_10l']= {"スプリント", "10L", "10line消せ!"},
|
||||
['sprint_20l']= {"スプリント", "20L", "20line消せ!"},
|
||||
['sprint_40l']= {"スプリント", "40L", "40line消せ!"},
|
||||
['sprint_100l']= {"スプリント", "100L", "100line消せ!"},
|
||||
['sprint_400l']= {"スプリント", "400L", "400line消せ!"},
|
||||
['sprint_1000l']= {"スプリント", "1,000L", "1,000line消せ!"},
|
||||
['sprintPenta']= {"スプリント", "PENTOMINO", "ペントミノで40line"},
|
||||
['sprintMPH']= {"スプリント", "MPH", "ミノ順なし\nネクストなし\nホールドなし!"},
|
||||
['sprint123']= {"スプリント", "M123", "モノミノ、ドミノ、トリミノで40line"},
|
||||
['secret_grade']= {"裏GM", "", "ガイドに従ってジグザグに穴を作れ!"},
|
||||
['dig_10l']= {"掘り", "10L", "10line下穴を掘れ!"},
|
||||
['dig_40l']= {"掘り", "40L", "40line下穴を掘れ!"},
|
||||
['dig_100l']= {"掘り", "100L", "100line下穴を掘れ!"},
|
||||
['dig_400l']= {"掘り", "400L", "400line下穴を掘れ!"},
|
||||
['dig_eff_10l']= {"掘り", "EFFICIENCY 10L", "最小のミノ数で10line掘れ!"},
|
||||
['dig_eff_40l']= {"掘り", "EFFICIENCY 40L", "最小のミノ数で40line掘れ!"},
|
||||
['dig_eff_100l']= {"掘り", "EFFICIENCY 100L","最小のミノ数で100line掘れ!"},
|
||||
['dig_eff_400l']= {"掘り", "EFFICIENCY 400L","最小のミノ数で400line掘れ!"},
|
||||
['dig_quad_10l']= {"掘り", "TECHRASH 10L", "techrashだけで10line下穴を掘れ!"},
|
||||
['drought_n']= {"ドラウト", "100L", "Iミノ一切無し!"},
|
||||
['drought_l']= {"ドラウト+", "100L", "わったーふ◯っく!"},
|
||||
['marathon_n']= {"マラソン", "NORMAL", "加速する中で200lineマラソン!"},
|
||||
['marathon_h']= {"マラソン", "HARD", "高速の中で200lineマラソン!"},
|
||||
['solo_e']= {"バトル", "EASY", "低レベルのAIに勝て!"},
|
||||
['solo_n']= {"バトル", "NORMAL", "通常レベルのAIに勝て!"},
|
||||
['solo_h']= {"バトル", "HARD", "高レベルのAIに勝て!"},
|
||||
['solo_l']= {"バトル", "LUNATIC", "プロレベルのAIに勝て!"},
|
||||
['solo_u']= {"バトル", "ULTIMATE", "神レベルのAIに勝て!"},
|
||||
['techmino49_e']= {"テック 49", "EASY", "低レベルAIと49人で勝負\n最後の1人まで生き残れ!"},
|
||||
['techmino49_h']= {"テック 49", "HARD", "高レベルAIと49人で勝負\n最後の1人まで生き残れ!"},
|
||||
['techmino49_u']= {"テック 49", "ULTIMATE", "神レベルAIと49人で勝負\n最後の1人まで生き残れ!"},
|
||||
['techmino99_e']= {"テック 99", "EASY", "低レベルAIと99人で勝負\n最後の1人まで生き残れ!"},
|
||||
['techmino99_h']= {"テック 99", "HARD", "高レベルAIと99人で勝負\n最後の1人まで生き残れ!"},
|
||||
['techmino99_u']= {"テック 99", "ULTIMATE", "神レベルAIと99人で勝負\n最後の1人まで生き残れ!"},
|
||||
['round_e']= {"ターン制", "EASY", "ターン制で低レベルAIと勝負!"},
|
||||
['round_n']= {"ターン制", "NORMAL", "ターン制で通常レベルAIと勝負!"},
|
||||
['round_h']= {"ターン制", "HARD", "ターン制で高レベルAIと勝負!"},
|
||||
['round_l']= {"ターン制", "LUNATIC", "ターン制でプロレベルAIと勝負!"},
|
||||
['round_u']= {"ターン制", "ULTIMATE", "ターン制で神レベルAIと勝負!"},
|
||||
['big_n']= {"ビッグ", "NORMAL", "小さい盤面でプレイ!"},
|
||||
['big_h']= {"ビッグ", "HARD", "小さい盤面でプレイ!"},
|
||||
['master_n']= {"マスター", "NORMAL", "20G 初心者方へ"},
|
||||
['master_h']= {"マスター", "HARD", "20G 中級者の方へ"},
|
||||
['master_m']= {"マスター", "M21", "20G 上級者の方へ"},
|
||||
['master_final']= {"マスター", "FINAL", "20G その先へ"},
|
||||
['master_ph']= {"マスター", "PHANTASM", "???"},
|
||||
['master_g']= {"マスター", "GRADED", "最高段位を取れ!"},
|
||||
['master_ex']= {"グランドマスター", "EXTRA", "一瞬よりも短い永遠"},
|
||||
['master_instinct']={"マスター", "INSTINCT", "もしミノが一切見えなくなったら?"},
|
||||
['strategy_e']= {"ストラテジー", "EASY", "20Gでの素早い判断"},
|
||||
['strategy_h']= {"ストラテジー", "HARD", "20Gでの素早い判断"},
|
||||
['strategy_u']= {"ストラテジー", "ULTIMATE", "20Gでの素早い判断"},
|
||||
['strategy_e_plus']={"ストラテジー", "EASY+", "20Gでの素早い判断"},
|
||||
['strategy_h_plus']={"ストラテジー", "HARD+", "20Gでの素早い判断"},
|
||||
['strategy_u_plus']={"ストラテジー", "ULTIMATE+", "20Gでの素早い判断"},
|
||||
['blind_e']= {"インビジブル", "HALF", "初心者用"},
|
||||
['blind_n']= {"インビジブル", "ALL", "中級者用"},
|
||||
['blind_h']= {"インビジブル", "SUDDEN", "上級者用"},
|
||||
['blind_l']= {"インビジブル", "SUDDEN+", "プロフェッショナル用"},
|
||||
['blind_u']= {"インビジブル", "?", "覚悟は良いかい?"},
|
||||
['blind_wtf']= {"インビジブル", "WTF", "まだ覚悟が足りない"},
|
||||
['classic_e']= {"クラシック", "EASY", "低速クラシック"},
|
||||
['classic_h']= {"クラシック", "HARD", "通常速度クラシック"},
|
||||
['classic_l']= {"クラシック", "LUNATIC", "中高速度クラシック"},
|
||||
['classic_u']= {"クラシック", "ULTIMATE", "高速クラシック"},
|
||||
['survivor_e']= {"サバイバル", "EASY", "どれだけ生き残れるかな?"},
|
||||
['survivor_n']= {"サバイバル", "NORMAL", "どれだけ生き残れるかな?"},
|
||||
['survivor_h']= {"サバイバル", "HARD", "どれだけ生き残れるかな?"},
|
||||
['survivor_l']= {"サバイバル", "LUNATIC", "どれだけ生き残れるかな?"},
|
||||
['survivor_u']= {"サバイバル", "ULTIMATE", "どれだけ生き残れるかな?"},
|
||||
['attacker_h']= {"火力王", "HARD", "攻撃力を磨け!"},
|
||||
['attacker_u']= {"火力王", "ULTIMATE", "攻撃力を磨け!"},
|
||||
['defender_n']= {"相殺王", "NORMAL", "防御力を磨け!"},
|
||||
['defender_l']= {"相殺王", "LUNATIC", "防御力を磨け!"},
|
||||
['dig_h']= {"掘王", "HARD", "掘りを磨け"},
|
||||
['dig_u']= {"掘王", "ULTIMATE", "掘りを磨け"},
|
||||
['c4wtrain_n']= {"C4Wトレーニング", "NORMAL", "無限中開け"},
|
||||
['c4wtrain_l']= {"C4Wトレーニング", "LUNATIC", "無限中開け"},
|
||||
['pctrain_n']= {"パフェトレーニング", "NORMAL", "パフェの練習!"},
|
||||
['pctrain_l']= {"パフェトレーニング", "LUNATIC", "もっと難しいパフェの練習!"},
|
||||
['pc_n']= {"パフェチャレンジ", "NORMAL", "100Line以内で パフェをできるだけたくさん取れ!"},
|
||||
['pc_h']= {"パフェチャレンジ", "HARD", "100Line以内で パフェをできるだけたくさん取れ!"},
|
||||
['pc_l']= {"パフェチャレンジ", "LUNATIC", "100Line以内で パフェをできるだけたくさん取れ!"},
|
||||
['pc_inf']= {"無限パフェチャレンジ", "", "できる限りたくさんのパフェを取れ!"},
|
||||
['tech_n']= {"テクニック", "NORMAL", "B2Bを繋げ続けよう!"},
|
||||
['tech_n_plus']= {"テクニック", "NORMAL+", "回転入れとパフェだけ!"},
|
||||
['tech_h']= {"テクニック", "HARD", "B2Bを繋げ続けよう!"},
|
||||
['tech_h_plus']= {"テクニック", "HARD+", "回転入れとパフェだけ!"},
|
||||
['tech_l']= {"テクニック", "LUNATIC", "回転入れとパフェだけ!"},
|
||||
['tech_l_plus']= {"テクニック", "LUNATIC+", "回転入れとパフェだけ!"},
|
||||
['tech_finesse']= {"テクニック", "FINESSE", "最適化!"},
|
||||
['tech_finesse_f']= {"テクニック", "FINESSE+", "最適化はそのまま、普通のline消去禁止!"},
|
||||
['tech_finesse_lock']= {"テクニック", "FINESSE LOCK","限られた入力数で最適化!"},
|
||||
['tech_finesse_lock_f']= {"Tech", "FINESSE+ LOCK","限られた入力数で最適化、ただし普通のline消去禁止!"},
|
||||
['tsd_e']= {"TSDチャレンジ", "EASY", "TSDだけ!"},
|
||||
['tsd_h']= {"TSDチャレンジ", "HARD", "TSDだけ!"},
|
||||
['tsd_u']= {"TSDチャレンジ", "ULTIMATE", "TSDだけ!"},
|
||||
['backfire_n']= {"バックファイヤー", "NORMAL", "撃った火力が戻ってくる!"},
|
||||
['backfire_h']= {"バックファイヤー", "HARD", "撃った火力が戻ってくる!"},
|
||||
['backfire_l']= {"バックファイヤー", "LUNATIC", "撃った火力が戻ってくる!"},
|
||||
['backfire_u']= {"バックファイヤー", "ULTIMATE", "撃った火力が戻ってくる!"},
|
||||
['sprintAtk']= {"スプリント", "100 Attack", "100line送れ!"},
|
||||
['sprintEff']= {"スプリント", "Efficiency", "40lineの間にできるだけ火力を出せ!"},
|
||||
['zen']= {'zen', "200", "時間制限なしで200line消去"},
|
||||
['ultra']= {'ウルトラ', "EXTRA", "2分以内にできるだけ多くの点数を取る"},
|
||||
['infinite']= {"無限", "", "サンドボックス"},
|
||||
['infinite_dig']= {"無限: 掘り", "", "掘れ掘れ掘れ"},
|
||||
['marathon_inf']= {"マラソン", "INFINITE", "ずっとマラソン"},
|
||||
['sprint_10l']= {"スプリント", "10L", "10line消せ!"},
|
||||
['sprint_20l']= {"スプリント", "20L", "20line消せ!"},
|
||||
['sprint_40l']= {"スプリント", "40L", "40line消せ!"},
|
||||
['sprint_100l']= {"スプリント", "100L", "100line消せ!"},
|
||||
['sprint_400l']= {"スプリント", "400L", "400line消せ!"},
|
||||
['sprint_1000l']= {"スプリント", "1,000L", "1,000line消せ!"},
|
||||
['sprintPenta']= {"スプリント", "PENTOMINO", "ペントミノで40line"},
|
||||
['sprintMPH']= {"スプリント", "MPH", "ミノ順なし\nネクストなし\nホールドなし!"},
|
||||
['sprint123']= {"スプリント", "M123", "モノミノ、ドミノ、トリミノで40line"},
|
||||
['construct_sg']= {"アート", "裏GM", "ガイドに従ってジグザグに穴を作れ!"},
|
||||
['construct_checker']= {"アート", "市松模様", "Build a checkerboard pattern!"},
|
||||
['construct_invsg']= {"アート", "反転裏GM", "Build an inverted zigzag pattern!"},
|
||||
['dig_10l']= {"掘り", "10L", "10line下穴を掘れ!"},
|
||||
['dig_40l']= {"掘り", "40L", "40line下穴を掘れ!"},
|
||||
['dig_100l']= {"掘り", "100L", "100line下穴を掘れ!"},
|
||||
['dig_400l']= {"掘り", "400L", "400line下穴を掘れ!"},
|
||||
['dig_eff_10l']= {"掘り", "EFFICIENCY 10L", "少ないミノで10line掘れ!"},
|
||||
['dig_eff_40l']= {"掘り", "EFFICIENCY 40L", "少ないミノで40line掘れ!"},
|
||||
['dig_eff_100l']= {"掘り", "EFFICIENCY 100L","少ないミノで100line掘れ!"},
|
||||
['dig_eff_400l']= {"掘り", "EFFICIENCY 400L","少ないミノで400line掘れ!"},
|
||||
['dig_quad_10l']= {"掘り", "TECHRASH 10L", "techrashだけで10line下穴を掘れ!"},
|
||||
['drought_n']= {"ドラウト", "100L", "Iミノ禁止!"},
|
||||
['drought_l']= {"ドラウト+", "100L", "WTF!!!"},
|
||||
['marathon_n']= {"マラソン", "NORMAL", "加速する中で200lineマラソン!"},
|
||||
['marathon_h']= {"マラソン", "HARD", "ハイスピード200lineマラソン!"},
|
||||
['solo_e']= {"バトル", "EASY", "低レベルAIに勝て!"},
|
||||
['solo_n']= {"バトル", "NORMAL", "通常レベルAIに勝て!"},
|
||||
['solo_h']= {"バトル", "HARD", "高レベルAIに勝て!"},
|
||||
['solo_l']= {"バトル", "LUNATIC", "プロレベルAIに勝て!"},
|
||||
['solo_u']= {"バトル", "ULTIMATE", "神レベルAIに勝て!"},
|
||||
['techmino49_e']= {"テック VS 49", "EASY", "49人対戦\n最後まで生き残れ!"},
|
||||
['techmino49_h']= {"テック VS 49", "HARD", "49人対戦\n最後まで生き残れ!"},
|
||||
['techmino49_u']= {"テック VS 49", "ULTIMATE", "49人対戦\n最後まで生き残れ!"},
|
||||
['techmino99_e']= {"テック VS 99", "EASY", "99人対戦\n最後まで生き残れ!"},
|
||||
['techmino99_h']= {"テック VS 99", "HARD", "99人対戦\n最後まで生き残れ!"},
|
||||
['techmino99_u']= {"テック VS 99", "ULTIMATE", "99人対戦\n最後まで生き残れ!"},
|
||||
['round_e']= {"ターン制", "EASY", "低レベルAIとターン制バトル!"},
|
||||
['round_n']= {"ターン制", "NORMAL", "通常レベルAIとターン制バトル!"},
|
||||
['round_h']= {"ターン制", "HARD", "高レベルAIとターン制バトル!"},
|
||||
['round_l']= {"ターン制", "LUNATIC", "プロレベルAIとターン制バトル!"},
|
||||
['round_u']= {"ターン制", "ULTIMATE", "神レベルAIとターン制バトル!"},
|
||||
['big_n']= {"ビッグ", "NORMAL", "5×10の盤面でプレイ!"},
|
||||
['big_h']= {"ビッグ", "HARD", "5×10の盤面でプレイ!"},
|
||||
['master_n']= {"マスター", "NORMAL", "初心者のための20G"},
|
||||
['master_h']= {"マスター", "HARD", "中級者のための20G"},
|
||||
['master_m']= {"マスター", "M21", "上級者のための20G"},
|
||||
['master_final']= {"マスター", "FINAL", "20G その先へ"},
|
||||
['master_ph']= {"マスター", "PHANTASM", "???"},
|
||||
['master_g']= {"マスター", "GRADED", "最高段位を取れ!"},
|
||||
['master_ex']= {"グランドマスター", "EXTRA", "一瞬にも満たない永遠"},
|
||||
['master_instinct']= {"マスター", "INSTINCT", "もしミノが見えなくなったら?"},
|
||||
['strategy_e']= {"ストラテジー", "EASY", "20Gでの素早い判断"},
|
||||
['strategy_h']= {"ストラテジー", "HARD", "20Gでの素早い判断"},
|
||||
['strategy_u']= {"ストラテジー", "ULTIMATE", "20Gでの素早い判断"},
|
||||
['strategy_e_plus']= {"ストラテジー", "EASY+", "20Gでの素早い判断"},
|
||||
['strategy_h_plus']= {"ストラテジー", "HARD+", "20Gでの素早い判断"},
|
||||
['strategy_u_plus']= {"ストラテジー", "ULTIMATE+", "20Gでの素早い判断"},
|
||||
['blind_e']= {"インビジブル", "HALF", "初心者用"},
|
||||
['blind_n']= {"インビジブル", "ALL", "中級者用"},
|
||||
['blind_h']= {"インビジブル", "SUDDEN", "上級者用"},
|
||||
['blind_l']= {"インビジブル", "SUDDEN+", "プロフェッショナル用"},
|
||||
['blind_u']= {"インビジブル", "?", "覚悟は良いかい?"},
|
||||
['blind_wtf']= {"インビジブル", "WTF", "まだ覚悟が足りない"},
|
||||
['classic_e']= {"クラシック", "EASY", "低速ゲーム(1980年版)"},
|
||||
['classic_h']= {"クラシック", "HARD", "中速ゲーム(1980年版)"},
|
||||
['classic_l']= {"クラシック", "LUNATIC", "高速ゲーム(1980年版)"},
|
||||
['classic_u']= {"クラシック", "ULTIMATE", "超高速ゲーム(1980年版)"},
|
||||
['survivor_e']= {"サバイバル", "EASY", "どれだけ生き残れるかな?"},
|
||||
['survivor_n']= {"サバイバル", "NORMAL", "どれだけ生き残れるかな?"},
|
||||
['survivor_h']= {"サバイバル", "HARD", "どれだけ生き残れるかな?"},
|
||||
['survivor_l']= {"サバイバル", "LUNATIC", "どれだけ生き残れるかな?"},
|
||||
['survivor_u']= {"サバイバル", "ULTIMATE", "どれだけ生き残れるかな?"},
|
||||
['attacker_h']= {"火力王", "HARD", "攻撃力を磨け!"},
|
||||
['attacker_u']= {"火力王", "ULTIMATE", "攻撃力を磨け!"},
|
||||
['defender_n']= {"相殺王", "NORMAL", "防御力を磨け!"},
|
||||
['defender_l']= {"相殺王", "LUNATIC", "防御力を磨け!"},
|
||||
['dig_h']= {"掘王", "HARD", "掘りを磨け"},
|
||||
['dig_u']= {"掘王", "ULTIMATE", "掘りを磨け"},
|
||||
['c4wtrain_n']= {"C4Wトレーニング", "NORMAL", "無限中開け"},
|
||||
['c4wtrain_l']= {"C4Wトレーニング", "LUNATIC", "無限中開け"},
|
||||
['pctrain_n']= {"パフェトレーニング", "NORMAL", "パフェの練習!"},
|
||||
['pctrain_l']= {"パフェトレーニング", "LUNATIC", "もっと難しいパフェの練習!"},
|
||||
['pc_n']= {"パフェチャレンジ", "NORMAL", "100Line以内で パフェをたくさん取れ!"},
|
||||
['pc_h']= {"パフェチャレンジ", "HARD", "100Line以内で パフェをたくさん取れ!"},
|
||||
['pc_l']= {"パフェチャレンジ", "LUNATIC", "100Line以内で パフェをたくさん取れ!"},
|
||||
['pc_inf']= {"無限パフェチャレンジ", "", "たくさんのパフェを取れ!"},
|
||||
['tech_n']= {"テクニック B2B", "NORMAL", "B2Bを繋げ続けよう!"},
|
||||
['tech_n_plus']= {"テクニック B2B", "NORMAL+", "回転入れとパフェだけ!"},
|
||||
['tech_h']= {"テクニック B2B", "HARD", "B2Bを繋げ続けよう!"},
|
||||
['tech_h_plus']= {"テクニック B2B", "HARD+", "回転入れとパフェだけ!"},
|
||||
['tech_l']= {"テクニック B2B", "LUNATIC", "B2Bを繋げ続けよう!"},
|
||||
['tech_l_plus']= {"テクニック B2B", "LUNATIC+", "回転入れとパフェだけ!"},
|
||||
['tech_finesse']= {"テクニック 最適化", "", "最適化!"},
|
||||
['tech_finesse_f']= {"テクニック 最適化", "PLUS", "通常Line消去抜きで最適化!"},
|
||||
['tsd_e']= {"TSDチャレンジ", "EASY", "TSDだけ!"},
|
||||
['tsd_h']= {"TSDチャレンジ", "HARD", "TSDだけ!"},
|
||||
['tsd_u']= {"TSDチャレンジ", "ULTIMATE", "TSDだけ!"},
|
||||
['backfire_n']= {"バックファイヤー", "NORMAL", "撃った火力が戻ってくる!"},
|
||||
['backfire_h']= {"バックファイヤー", "HARD", "撃った火力が戻ってくる!"},
|
||||
['backfire_l']= {"バックファイヤー", "LUNATIC", "撃った火力が戻ってくる!"},
|
||||
['backfire_u']= {"バックファイヤー", "ULTIMATE", "撃った火力が戻ってくる!"},
|
||||
['sprintAtk']= {"スプリント", "100 Attack", "100line送れ!"},
|
||||
['sprintEff']= {"スプリント", "Efficiency", "40lineの間に高火力を出せ!"},
|
||||
['zen']= {'zen', "200", "時間制限なしで200line消去"},
|
||||
['ultra']= {'ウルトラ', "EXTRA", "2分間でスコアアタック"},
|
||||
['infinite']= {"無限", "", "サンドボックス"},
|
||||
['infinite_dig']= {"無限: 掘り", "", "掘れ掘れ掘れ掘れ掘れ掘・・・"},
|
||||
['marathon_inf']= {"マラソン", "INFINITE", "ずっと走れるね"},
|
||||
|
||||
['custom_clear']= {"カスタム", "NORMAL"},
|
||||
['custom_puzzle']= {"カスタム", "PUZZLE"},
|
||||
['custom_clear']= {"カスタム", "NORMAL"},
|
||||
['custom_puzzle']= {"カスタム", "PUZZLE"},
|
||||
},
|
||||
getTip={refuseCopy=true,
|
||||
":pog:",
|
||||
|
||||
@@ -18,7 +18,7 @@ return {
|
||||
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
-- cleared="$1 lines",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Clear",
|
||||
PC="Perfect Clear",HPC="Meio PC",
|
||||
replaying="[Replay]",
|
||||
-- tasUsing="[TAS]",
|
||||
|
||||
@@ -33,6 +33,7 @@ return {
|
||||
-- infHeightOn="Infinite Height ON",
|
||||
-- infHeightOff="Infinite Height OFF",
|
||||
-- infHeightHint="Toggle with Function 1 key",
|
||||
-- highestGrade="(highest: $1)",
|
||||
|
||||
speedLV="Nível de velocidade",
|
||||
piece="Peça",line="Linhas",atk="Ataque",eff="Eficiência",
|
||||
@@ -44,7 +45,7 @@ return {
|
||||
|
||||
-- win="Win",
|
||||
-- lose="Lose",
|
||||
|
||||
--torikan="Ended",
|
||||
finish="Terminou",
|
||||
gamewin="Você venceu!",
|
||||
gameover="Fim de jogo",
|
||||
@@ -56,10 +57,13 @@ return {
|
||||
|
||||
page="Página:",
|
||||
|
||||
-- ai_puzzle="AI is incompatible with puzzle game mode",
|
||||
ai_mission="A inteligência é incompatível com missões costumizadas.",
|
||||
-- ai_badPiece="The AI is incompatible with custom sequences which have nontetromino.", inteligência é incompatível com sequências fixas.",
|
||||
-- cc_fixed="CC is incompatible with fixed sequences",
|
||||
-- cc_swap="CC is incompatible with swap holdmode",
|
||||
-- ai_prebag="The AI is incompatible with custom sequences which have nontetromino.", inteligência é incompatível com sequências fixas.",
|
||||
ai_mission="A inteligência é incompatível com missões costumizadas.",
|
||||
-- cc_solid="CC is incompatible with filled line in the field.",
|
||||
-- cc_field_too_high="CC is incompatible with fields higher than 40.",
|
||||
switchSpawnSFX="Switch on spawn SFX to play",
|
||||
needRestart="Funciona após reiniciar",
|
||||
|
||||
@@ -81,6 +85,8 @@ return {
|
||||
dataCorrupted="Data corrompida",
|
||||
-- pasteWrongPlace="Paste at wrong place?",
|
||||
-- noFile="File not found",
|
||||
-- invalidSequence="Invalid sequence mode",
|
||||
-- tooHighField="Field data exceeded 126 lines discarded",
|
||||
|
||||
VKTchW="Peso de toque",
|
||||
VKOrgW="Peso da origem",
|
||||
@@ -221,7 +227,7 @@ return {
|
||||
"Peça:",
|
||||
"Linha/Dig:",
|
||||
"Ataque/DigAtk:",
|
||||
"Recebido:",
|
||||
"Recebido:",-- "Rise(Receive-Offset):",
|
||||
"Limpas:",
|
||||
"Giros:",
|
||||
"B2B/B3B/PC/HPC:",
|
||||
@@ -235,7 +241,7 @@ return {
|
||||
"Tempo jogado:",
|
||||
"Tecla/Rot./Segurar:",
|
||||
"Blocos/Linhas/Ataque:",
|
||||
"Recv./Res./Asc.:",
|
||||
"Recv./Res./Asc.:",-- "Receive/Offset/Rise:",
|
||||
"Dig/Dig Atk.:",
|
||||
"Eff./Dig Eff.:",
|
||||
"B2B/B3B:",
|
||||
@@ -315,6 +321,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -448,7 +455,7 @@ return {
|
||||
-- capacity="Capacity",
|
||||
-- create="Create",
|
||||
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="Sem Quebrar B2B",
|
||||
-- lockout="Fail when lock out",
|
||||
@@ -456,7 +463,7 @@ return {
|
||||
-- deepDrop="Deep Drop",
|
||||
bone="Bone Blocks",
|
||||
|
||||
-- eventSet="Rule Set",
|
||||
-- eventSet="Ruleset",
|
||||
|
||||
-- holdMode="Hold Mode",
|
||||
nextCount="Prox.",
|
||||
@@ -531,6 +538,10 @@ return {
|
||||
-- bg_on="Normal B.G.",
|
||||
-- bg_off="No B.G.",
|
||||
-- bg_custom="Use Custom B.G.",
|
||||
-- defaultBG="Default B.G.",
|
||||
-- resetDbg="Reset to default",
|
||||
-- lockBG="Lock B.G.",
|
||||
-- noTheme="Disable theme",
|
||||
|
||||
-- blockSatur="Block Saturation",
|
||||
-- fieldSatur="Field Saturation",
|
||||
@@ -648,7 +659,7 @@ return {
|
||||
sequence="Editar Sequência (S)",
|
||||
mission="Editar Missão (M)",
|
||||
|
||||
-- eventSet="Rule Set",
|
||||
-- eventSet="Ruleset",
|
||||
|
||||
-- holdMode="Hold Mode",
|
||||
nextCount="Prox.",
|
||||
@@ -666,7 +677,7 @@ return {
|
||||
|
||||
-- bufferLimit="Buffer Limit",
|
||||
-- heightLimit="Height Limit",
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="Sem Quebrar B2B",
|
||||
-- lockout="Fail when lock out",
|
||||
@@ -815,6 +826,10 @@ return {
|
||||
['sprint_1000l']= {"Sprint", "1000L", "Limpe 1000 linhas!"},
|
||||
['sprintPenta']= {"Sprint", "PENTOMINO", "Limpe 40 linhas com 18 pentominoes."},
|
||||
['sprintMPH']= {"Sprint", "MPH", "SemMem.\nSemPrévia\nSemSegurar"},
|
||||
-- ['sprint123']= {"Sprint", "M123", "40L with only monominoes, dominoes, and triminoes"},
|
||||
-- ['construct_sg']= {"Construct", "SECRET GRADE", "Build a zigzag shape by following the guide!"},
|
||||
-- ['construct_checker']= {"Construct", "CHECKERBOARD", "Build a checkerboard pattern!"},
|
||||
-- ['construct_invsg']= {"Construct", "INV. SG", "Build an inverted zigzag pattern!"},
|
||||
['dig_10l']= {"Cave", "10L", "Cave 10 linhas de lixo."},
|
||||
['dig_40l']= {"Cave", "40L", "Cave 40 linhas de lixo."},
|
||||
['dig_100l']= {"Cave", "100L", "Cave 100 linhas de lixo."},
|
||||
@@ -829,14 +844,14 @@ return {
|
||||
['solo_e']= {"Batalha", "FÁCIL", "Derrote a inteligência!"},
|
||||
['solo_n']= {"Batalha", "NORMAL", "Derrote a inteligência!"},
|
||||
['solo_h']= {"Batalha", "DIFÍCIL", "Derrote a inteligência!"},
|
||||
['solo_l']= {"Batalha", "LUNÁTICO", "Defeat the AI!"},
|
||||
['solo_u']= {"Batalha", "ULTIMATE", "Defeat the AI!"},
|
||||
['techmino49_e']= {"Tech 49", "FÁCIL", "Batalha de 49 jogadores.\nO último vence"},
|
||||
['techmino49_h']= {"Tech 49", "DIFÍCIL", "Batalha de 49 jogadores.\nO último vence."},
|
||||
['techmino49_u']= {"Tech 49", "ULTIMATE", "Batalha de 49 jogadores.\nO último vence."},
|
||||
['techmino99_e']= {"Tech 99", "FÁCIL", "Batalha de 99 jogadores.\nO último vence."},
|
||||
['techmino99_h']= {"Tech 99", "DIFÍCIL", "Batalha de 99 jogadores.\nO último vence."},
|
||||
['techmino99_u']= {"Tech 99", "ULTIMATE", "Batalha de 99 jogadores.\nO último vence."},
|
||||
['solo_l']= {"Batalha", "LUNÁTICO", "Derrote a inteligência!"},
|
||||
['solo_u']= {"Batalha", "ULTIMATE", "Derrote a inteligência!"},
|
||||
['techmino49_e']= {"Tech VS 49", "FÁCIL", "Batalha de 49 jogadores.\nO último vence"},
|
||||
['techmino49_h']= {"Tech VS 49", "DIFÍCIL", "Batalha de 49 jogadores.\nO último vence."},
|
||||
['techmino49_u']= {"Tech VS 49", "ULTIMATE", "Batalha de 49 jogadores.\nO último vence."},
|
||||
['techmino99_e']= {"Tech VS 99", "FÁCIL", "Batalha de 99 jogadores.\nO último vence."},
|
||||
['techmino99_h']= {"Tech VS 99", "DIFÍCIL", "Batalha de 99 jogadores.\nO último vence."},
|
||||
['techmino99_u']= {"Tech VS 99", "ULTIMATE", "Batalha de 99 jogadores.\nO último vence."},
|
||||
['round_e']= {"Baseado Turnos", "FÁCIL", "Modo xadrez"},
|
||||
['round_n']= {"Baseado Turnos", "NORMAL", "Modo xadrez"},
|
||||
['round_h']= {"Baseado Turnos", "DIFÍCIL", "Modo xadrez"},
|
||||
@@ -889,16 +904,16 @@ return {
|
||||
['pc_h']= {"Desafio PC", "DIFÍCIL", "Obtenha PCs em 100 linhas!"},
|
||||
['pc_l']= {"Desafio PC", "LUNÁTICO", "Obteha PCs em 100 linhas!"},
|
||||
-- ['pc_inf']= {"Inf. PC Challenge","", "Get PCs as much as you can"},
|
||||
['tech_n']= {"Tech", "NORMAL", "Não quebre o B2B!"},
|
||||
['tech_n_plus']= {"Tech", "NORMAL+", "Apenas spins e PC"},
|
||||
['tech_h']= {"Tech", "HARD", "Keep the B2B chain!"},
|
||||
['tech_h_plus']= {"Tech", "HARD+", "Apenas spins e PC"},
|
||||
['tech_l']= {"Tech", "LUNÁTICO", "Não quebre o B2B!"},
|
||||
['tech_l_plus']= {"Tech", "LUNÁTICO+", "Apenas spins e PC"},
|
||||
['tech_n']= {"Tech B2B", "NORMAL", "Não quebre o B2B!"},
|
||||
['tech_n_plus']= {"Tech B2B", "NORMAL+", "Apenas spins e PC"},
|
||||
['tech_h']= {"Tech B2B", "HARD", "Keep the B2B chain!"},
|
||||
['tech_h_plus']= {"Tech B2B", "HARD+", "Apenas spins e PC"},
|
||||
['tech_l']= {"Tech B2B", "LUNÁTICO", "Não quebre o B2B!"},
|
||||
['tech_l_plus']= {"Tech B2B", "LUNÁTICO+", "Apenas spins e PC"},
|
||||
-- ['tech_finesse']= {"Tech Finesse", "", "No finesse errors!"},
|
||||
-- ['tech_finesse_f']= {"Tech Finesse", "PLUS", "No normal clears and finesse errors!"},
|
||||
['tech_finesse']= {"Tech", "FINESSE", "Não erre a destreza!"},
|
||||
['tech_finesse_f']= {"Tech", "FINESSE+", "Sem limpas normais,\nnão erre a destreza!"},
|
||||
--['tech_finesse_lock']= {"Tech", "FINESSE LOCK", "No finesse errors, combined with limited inputs!"},
|
||||
--['tech_finesse_lock_f']= {"Tech", "FINESSE+ LOCK", "No normal clears or finesse errors combined with limited inputs!"},
|
||||
['tsd_e']= {"Desafio TSD", "FÁCIL", "Apenas T-spin-doubles!"},
|
||||
['tsd_h']= {"Desafio TSD", "DIFÍCIL", "Apenas T-spin-doubles!"},
|
||||
['tsd_u']= {"Desafio TSD", "ULTIMATE", "Apenas T-spin-doubles!"},
|
||||
|
||||
@@ -41,10 +41,11 @@ return {
|
||||
infHeightOn="∞↑ "..CHAR.icon.checkMark,
|
||||
infHeightOff="∞↑ "..CHAR.icon.crossMark,
|
||||
infHeightHint=CHAR.icon.checkMark.."/"..CHAR.icon.crossMark..": F₁",
|
||||
highestGrade="(↑: $1)",
|
||||
|
||||
win=": )",
|
||||
lose=": (",
|
||||
|
||||
torikan=": /",
|
||||
finish="&",
|
||||
gamewin=">>",
|
||||
gameover="x",
|
||||
@@ -56,10 +57,13 @@ return {
|
||||
|
||||
page=":",
|
||||
|
||||
ai_puzzle="X!!!",
|
||||
ai_mission="X!!!",
|
||||
ai_badPiece="X!!!",
|
||||
cc_fixed="CC X!!!",
|
||||
cc_swap="CC X!!!",
|
||||
ai_prebag="X!!!",
|
||||
ai_mission="X!!!",
|
||||
cc_solid="CC X!!!",
|
||||
cc_field_too_high="CC X!!!",
|
||||
needRestart="!!*#R#*!!",
|
||||
|
||||
loadError_errorMode="'$1' ↑x!: no load mode '$2'",
|
||||
@@ -80,6 +84,8 @@ return {
|
||||
dataCorrupted="XXXXX",
|
||||
pasteWrongPlace="_?X.",
|
||||
-- noFile="File not found",
|
||||
-- invalidSequence="Invalid sequence mode",
|
||||
-- tooHighField="Field data exceeded 126 lines discarded",
|
||||
|
||||
nowPlaying="~:",
|
||||
|
||||
@@ -103,7 +109,7 @@ return {
|
||||
"□:",
|
||||
"-/↓:",
|
||||
"→/↓→:",
|
||||
"←:",
|
||||
"↑(←-↓):",
|
||||
"□↓:",
|
||||
"~↓:",
|
||||
"^^/^^^/#<>#/<>:",
|
||||
@@ -216,7 +222,7 @@ return {
|
||||
deepDrop="\\↓↓/",
|
||||
bone="[]",
|
||||
|
||||
eventSet="Rule Set",
|
||||
eventSet="Ruleset",
|
||||
|
||||
holdMode="? [ ]",
|
||||
nextCount="→",
|
||||
@@ -291,6 +297,10 @@ return {
|
||||
bg_on="__?__",
|
||||
bg_off="__.__",
|
||||
bg_custom="__!__",
|
||||
defaultBG="__$0__",
|
||||
resetDbg="R$0",
|
||||
lockBG="__↓__",
|
||||
noTheme="\\^_^/ "..CHAR.icon.crossMark,
|
||||
|
||||
blockSatur="==#0x",
|
||||
fieldSatur="[]#0x",
|
||||
@@ -406,7 +416,7 @@ return {
|
||||
sequence="Edit Sequence (S)",
|
||||
mission="Edit Mission (M)",
|
||||
|
||||
eventSet="Rule Set",
|
||||
eventSet="Ruleset",
|
||||
|
||||
holdMode="? [ ]",
|
||||
nextCount="→",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
local C=COLOR
|
||||
local all_month={"T01","T02","T03","T04","T05","T06","T07","T08","T09","T10","T11","T12"}
|
||||
|
||||
-- There are some strings, due to game's history, temproary be commented just in case
|
||||
-- If it is not used anymore, it will be removed, in one day…
|
||||
@@ -20,7 +19,7 @@ return {
|
||||
sureReset="Nhấn thêm một lần nữa để đặt lại",
|
||||
sureDelete="Nhấn thêm một lần nữa để xoá",
|
||||
newDay="Một ngày mới, một khởi đầu mới!",
|
||||
playedLong="Bạn chơi cũng lâu rồi. Hãy dành chút thời gian nghỉ ngơi đi",
|
||||
playedLong="Bạn chơi hơi lâu rồi đó. Hãy dành chút thời gian nghỉ ngơi đi.",
|
||||
playedTooMuch="Có lẽ bạn chơi quá nhiều rồi! Đặt máy xuống và nghỉ ngơi đi bạn!",
|
||||
settingWarn="CẨN THẬN - Bạn vừa sửa một cài đặt quan trọng của game!",
|
||||
settingWarn2="Cài đặt này sẽ có hiệu lực sau khi khởi động lại",
|
||||
@@ -34,7 +33,7 @@ return {
|
||||
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash","Heptacrash","Octacrash","Nonacrash","Decacrash","Undecacrash","Dodecacrash","Tridecacrash","Tetradecacrash","Pentadecacrash","Hexadecacrash","Heptadecacrash","Octadecacrash","Nonadecacrash","Ultracrash","Impossicrash"},
|
||||
cleared="$1 hàng",
|
||||
mini="Mini",b2b="B2B ",b3b="B2B2B ",
|
||||
PC="Perfect Clear",HPC="Hemi-Perfect Clear",
|
||||
PC="Perfect Clear",HPC="Half PC",
|
||||
replaying="[Đang phát lại]",
|
||||
tasUsing="[TAS]",
|
||||
|
||||
@@ -46,9 +45,10 @@ return {
|
||||
maxspeed="TỐC ĐỘ TỐI ĐA!",
|
||||
speedup="Tăng tốc nào!",
|
||||
missionFailed="Nhiệm vụ thất bại",
|
||||
infHeightOn="Infinite Height ON",
|
||||
infHeightOff="Infinite Height OFF",
|
||||
infHeightHint="Toggle with Function 1 key",
|
||||
infHeightOn="Bảng cao vô tận: BẬT",
|
||||
infHeightOff="Bảng cao vô tận: TẮT",
|
||||
infHeightHint="Nhấn phím Chức năng 1 để bật/tắt",
|
||||
highestGrade="(cao nhất: $1)",
|
||||
|
||||
speedLV="Tốc độ rơi",
|
||||
piece="Gạch",line="Hàng",atk="Attack",eff="Efficiency",
|
||||
@@ -60,7 +60,7 @@ return {
|
||||
|
||||
win="Thắng!",
|
||||
lose="Thua",
|
||||
|
||||
torikan="Torikan!",
|
||||
finish="Hoàn thành",
|
||||
gamewin="Bạn đã thắng",
|
||||
gameover="Kết thúc",
|
||||
@@ -72,10 +72,13 @@ return {
|
||||
|
||||
page="Trang ",
|
||||
|
||||
ai_puzzle="AI không tương thích với chế độ Puzzle",
|
||||
ai_mission="AI không tương thích với nhiệm vụ tuỳ chọn.",
|
||||
ai_badPiece="AI không tương thích với trình xáo gạch chứa gạch không phải là tetromino.",
|
||||
cc_fixed="CC không tương thích với trình xáo gạch cố định",
|
||||
cc_swap="CC không tương thích với chế độ Hold là Chuyển",
|
||||
ai_prebag="AI không tương thích với trình xáo gạch chứa gạch không phải là tetromino.",
|
||||
ai_mission="AI không tương thích với nhiệm vụ tuỳ chọn.",
|
||||
cc_solid="CC không tương thích với bảng có hàng đã lấp đầy.",
|
||||
cc_field_too_high="CC không tương thích với bảng cao hơn 40 hàng!",
|
||||
switchSpawnSFX="Vui lòng bật Spawn SFX để chơi!",
|
||||
needRestart="Khởi động lại để áp dụng mọi thay đổi.",
|
||||
|
||||
@@ -97,6 +100,8 @@ return {
|
||||
dataCorrupted="Dữ liệu bị hỏng",
|
||||
pasteWrongPlace="Bạn có dán đúng nơi không đấy?",
|
||||
noFile="Thiếu tệp",
|
||||
invalidSequence="Tên trình xáo gạch không hợp lệ!",
|
||||
tooHighField="BẢNG QUÁ CAO! Phần bảng cao hơn hàng 126 sẽ bị bỏ qua",
|
||||
|
||||
nowPlaying="Đang phát:",
|
||||
|
||||
@@ -212,9 +217,9 @@ return {
|
||||
|
||||
modInstruction="Hãy chọn modifier bạn muốn.\nMod cho phép bạn có thể tùy biến game, nhưng cũng có thể làm game sập.\nKể cả thế, hãy thoải mái và chơi theo cách của bạn!\nBạn có thể dùng bàn phím để chọn mod (giữ Shift để chọn lùi)\nĐiểm sẽ không được lưu lại khi dùng mod.",
|
||||
modInfo={
|
||||
next="NEXT\nGhi đè số gạch hiển thị ở cột NEXT",
|
||||
next="NEXT\nGhi đè số gạch hiển thị ở hàng NEXT",
|
||||
hold="HOLD\nGhi đè số lượng gạch được giữ ở cột HOLD",
|
||||
hideNext="Hidden NEXT\nẨn số lượng gạch ở cột NEXT (Tính từ ô đầu tiên)",
|
||||
hideNext="Hidden NEXT\nẨn số lượng gạch ở hàng NEXT (Tính từ ô đầu tiên)",
|
||||
infHold="InfiniHold\nCho phép bạn HOLD vô số lần",
|
||||
hideBlock="Hide Current Piece\nGạch đang rơi trong bảng sẽ bị tàng hình",
|
||||
hideGhost="No Ghost\nBóng gạch sẽ bị tắt",
|
||||
@@ -241,7 +246,7 @@ return {
|
||||
"Số gạch:",
|
||||
"Hàng/Đào:",
|
||||
"Gửi/Gửi khi đào:",
|
||||
"Nhận:",
|
||||
"Chịu (Nhận-Phản):",
|
||||
"Xóa:",
|
||||
"Spin:",
|
||||
"B2B/B3B/PC/HPC:",
|
||||
@@ -250,12 +255,12 @@ return {
|
||||
radar={"DEF","OFF","ATK","SEND","SPD","DIG"},
|
||||
radarData={"D’PM","ADPM","APM","SPM","L'PM","DPM"},
|
||||
stat={
|
||||
"Số lần bật trò chơi:",
|
||||
"Số lần bật game:",
|
||||
"Số ván đã chơi:",
|
||||
"Thời gian chơi:",
|
||||
"Phím/Xoay/Giữ:",
|
||||
"Gạch/Hàng/Gửi:",
|
||||
"Nhận/Phản/Đẩy:",
|
||||
"Nhận/Phản/Chịu:",
|
||||
"Đào/Gửi khi đào:",
|
||||
"H.quả/H.quả khi Đào:",
|
||||
"B2B/B3B:",
|
||||
@@ -338,6 +343,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -420,8 +426,8 @@ B. Bàn phím: Nhấn…
|
||||
|
||||
C. Tay cầm chơi game (Gamepad):
|
||||
- Nhấn $10 để hiển thị trợ giúp
|
||||
- Nhấn $5 hoặc $6 để cuộn văn bản, giữ $11 để cuộn nhanh hơn
|
||||
- Nhấn $7 để mở mục trước và $8 để mở mục tiếp theo
|
||||
- Nhấn $5 hoặc $6 để cuộn văn bản
|
||||
- Nhấn $7 để mở mục trước và $8 để mở mục tiếp theo, giữ $11 để lướt nhanh hơn
|
||||
- Giữ $11 và nhấn $6 để giảm cỡ chữ hoặc $5 để tăng lên
|
||||
]]
|
||||
-- 1-4: Up, Down, Left, Right
|
||||
@@ -506,7 +512,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
capacity="Giới hạn số người",
|
||||
create="Tạo phòng",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="Không phá B2B",
|
||||
lockout="Thua khi Lock Out",
|
||||
@@ -514,7 +520,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
deepDrop="Thả rơi sâu",
|
||||
bone="Dùng skin []",
|
||||
|
||||
eventSet="Rule Set",
|
||||
eventSet="Ruleset",
|
||||
|
||||
holdMode="Chế độ Hold",
|
||||
nextCount="Next",
|
||||
@@ -565,13 +571,13 @@ C. Tay cầm chơi game (Gamepad):
|
||||
grid="Lưới",
|
||||
lineNum="# hàng",
|
||||
|
||||
lockFX="H.ứng Khóa gạch",
|
||||
dropFX="H.ứng Thả nhẹ",
|
||||
moveFX="H.ứng Di chuyển",
|
||||
clearFX="H.ứng Xóa hàng",
|
||||
splashFX="H.ứng Gạch \"rụng\"",
|
||||
lockFX="Hiệu ứng Khóa gạch",
|
||||
dropFX="Hiệu ứng Thả nhẹ",
|
||||
moveFX="Hiệu ứng Di chuyển",
|
||||
clearFX="Hiệu ứng Xóa hàng 1",
|
||||
splashFX="Hiệu ứng Xóa hàng 2",
|
||||
shakeFX="Độ nảy bảng",
|
||||
atkFX="H.ứng Tấn công",
|
||||
atkFX="Hiệu ứng Tấn công",
|
||||
|
||||
frame="Tần suất cập nhật khung hình (%)",
|
||||
|
||||
@@ -583,7 +589,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
highCam="Trượt bảng",
|
||||
warn="Cảnh báo nguy hiểm",
|
||||
|
||||
clickFX="Click FX",
|
||||
clickFX="Hiệu ứng nhấp chuột",
|
||||
power="Hiện thanh pin",
|
||||
clean="Vẽ nhanh",
|
||||
fullscreen="Toàn màn hình",
|
||||
@@ -593,6 +599,10 @@ C. Tay cầm chơi game (Gamepad):
|
||||
bg_on="Ảnh nền thường",
|
||||
bg_off="Không ảnh nền",
|
||||
bg_custom="Ảnh nền tự chọn",
|
||||
defaultBG="Nền mặc định",
|
||||
resetDbg='Đặt lại',
|
||||
lockBG="Khóa ảnh nền",
|
||||
noTheme="Tắt theme",
|
||||
|
||||
blockSatur="Độ đậm gạch",
|
||||
fieldSatur="Độ đậm bảng",
|
||||
@@ -620,7 +630,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
},
|
||||
setting_control={
|
||||
-- title="Cài đặt Điều khiển",
|
||||
title="Đ.chỉnh thg. số",
|
||||
title="Điều chỉnh thông số",
|
||||
preview="Xem trước",
|
||||
|
||||
das="DAS",arr="ARR",
|
||||
@@ -726,7 +736,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
sequence="C. đặt Trình xáo gạch (S)",
|
||||
mission="Cài đặt Nhiệm vụ (M)",
|
||||
|
||||
eventSet="Rule Set",
|
||||
eventSet="Ruleset",
|
||||
|
||||
holdMode="Chế độ Hold",
|
||||
nextCount="Next",
|
||||
@@ -744,7 +754,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
|
||||
bufferLimit="Giới hạn nhận rác",
|
||||
heightLimit="Giới hạn độ cao",
|
||||
ospin="O-Spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% Finesse",
|
||||
b2bKill="Không phá B2B",
|
||||
lockout="Thua khi Lock Out",
|
||||
@@ -890,11 +900,13 @@ C. Tay cầm chơi game (Gamepad):
|
||||
['sprint_40l']= {"Sprint", "40L", "Xoá 40 hàng!"},
|
||||
['sprint_100l']= {"Sprint", "100L", "Xoá 100 hàng!"},
|
||||
['sprint_400l']= {"Sprint", "400L", "Xoá 400 hàng!"},
|
||||
['sprint_1000l']= {"Sprint", "1000L", "Xoá 1000 hàng!"},
|
||||
['sprint_1000l']= {"Sprint", "1000L", "Xoá 1000 hàng!"},
|
||||
['sprintPenta']= {"Sprint", "PENTOMINO", "Xoá 40 hàng với 18 pentomino"},
|
||||
['sprintMPH']= {"Sprint", "MPH", "Memoryless\nPreviewless\nHoldless"},
|
||||
['sprint123']= {"Sprint", "M123", "Xoá 40 hàng chỉ với monomino, domino, và trimino"},
|
||||
['secret_grade']= {"Secret Grade", "", "Xây một đường lỗ theo hình dích dắc!"},
|
||||
['construct_sg']= {"Construct", "SECRET GRADE", "Xây một đường lỗ theo hình dích dắc!"},
|
||||
['construct_checker']= {"Construct", "CHECKERBOARD", "Xây tường theo kiểu xen kẽ!"},
|
||||
['construct_invsg']= {"Construct", "SG ĐẢO NGƯỢC", "Xây một đường thẳng theo hình dích dắc!"},
|
||||
['dig_10l']= {"Dig", "10L", "Đào 10 hàng rác càng nhanh càng tốt"},
|
||||
['dig_40l']= {"Dig", "40L", "Đào 40 hàng rác càng nhanh càng tốt!"},
|
||||
['dig_100l']= {"Dig", "100L", "Đào 100 hàng rác càng nhanh càng tốt!"},
|
||||
@@ -905,7 +917,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
['dig_eff_400l']= {"Dig", "EFFICIENCY 400L","Đào 400 hàng rác càng ít gạch càng tốt!"},
|
||||
['dig_quad_10l']= {"Dig", "TECHRASH 10L", "Đào 10 hàng rác nhưng chỉ dùng techrash!"},
|
||||
['drought_n']= {"Drought", "100L", "Không có thanh dài"},
|
||||
['drought_l']= {"Drought+", "100L", "C L G T"},
|
||||
['drought_l']= {"Drought+", "100L", "C L G T ? !"},
|
||||
['marathon_n']= {"Marathon", "THƯỜNG", "Xoá 200 hàng với tốc độ nhanh dần"},
|
||||
['marathon_h']= {"Marathon", "KHÓ", "Xoá 200 hàng với tốc độ cao"},
|
||||
['solo_e']= {"Battle", "DỄ", "Đánh bại AI!"},
|
||||
@@ -913,12 +925,12 @@ C. Tay cầm chơi game (Gamepad):
|
||||
['solo_h']= {"Battle", "KHÓ", "Đánh bại AI!"},
|
||||
['solo_l']= {"Battle", "RẤT KHÓ", "Đánh bại AI!"},
|
||||
['solo_u']= {"Battle", "THÁCH ĐẤU", "Đánh bại AI!"},
|
||||
['techmino49_e']= {"Tech 49", "DỄ", "Cuộc chiến 49 người.\nNgười trụ lại cuối cùng giành chiến thắng"},
|
||||
['techmino49_h']= {"Tech 49", "KHÓ", "Cuộc chiến 49 người.\nNgười trụ lại cuối cùng giành chiến thắng"},
|
||||
['techmino49_u']= {"Tech 49", "THÁCH ĐẤU", "Cuộc chiến 49 người.\nNgười trụ lại cuối cùng giành chiến thắng"},
|
||||
['techmino99_e']= {"Tech 99", "DỄ", "Cuộc chiến 99 người.\nNgười trụ lại cuối cùng giành chiến thắng"},
|
||||
['techmino99_h']= {"Tech 99", "KHÓ", "Cuộc chiến 99 người.\nNgười trụ lại cuối cùng giành chiến thắng"},
|
||||
['techmino99_u']= {"Tech 99", "THÁCH ĐẤU", "Cuộc chiến 99 người.\nNgười trụ lại cuối cùng giành chiến thắng"},
|
||||
['techmino49_e']= {"Tech VS 49", "DỄ", "Cuộc chiến 49 người.\nNgười trụ lại cuối cùng sẽ giành chiến thắng"},
|
||||
['techmino49_h']= {"Tech VS 49", "KHÓ", "Cuộc chiến 49 người.\nNgười trụ lại cuối cùng sẽ giành chiến thắng"},
|
||||
['techmino49_u']= {"Tech VS 49", "THÁCH ĐẤU", "Cuộc chiến 49 người.\nNgười trụ lại cuối cùng sẽ giành chiến thắng"},
|
||||
['techmino99_e']= {"Tech VS 99", "DỄ", "Cuộc chiến 99 người.\nNgười trụ lại cuối cùng sẽ giành chiến thắng"},
|
||||
['techmino99_h']= {"Tech VS 99", "KHÓ", "Cuộc chiến 99 người.\nNgười trụ lại cuối cùng sẽ giành chiến thắng"},
|
||||
['techmino99_u']= {"Tech VS 99", "THÁCH ĐẤU", "Cuộc chiến 99 người.\nNgười trụ lại cuối cùng sẽ giành chiến thắng"},
|
||||
['round_e']= {"Turn-Based", "DỄ", "Chơi theo lượt và đánh bại AI!"},
|
||||
['round_n']= {"Turn-Based", "THƯỜNG", "Chơi theo lượt và đánh bại AI!"},
|
||||
['round_h']= {"Turn-Based", "KHÓ", "Chơi theo lượt và đánh bại AI!"},
|
||||
@@ -969,17 +981,15 @@ C. Tay cầm chơi game (Gamepad):
|
||||
['pc_h']= {"PC Challenge", "KHÓ", "Lấy càng nhiều PC càng tốt trong 100 hàng!"},
|
||||
['pc_l']= {"PC Challenge", "RẤT KHÓ", "Lấy càng nhiều PC càng tốt trong 100 hàng!"},
|
||||
['pc_inf']= {"Inf. PC Challenge", "", "Lấy càng nhiều PC càng tốt"},
|
||||
['tech_n']= {"Tech", "THƯỜNG", "Cố gắng không phá B2B!"},
|
||||
['tech_n_plus']= {"Tech", "THƯỜNG+", "Chỉ được clear Spin hoặc PC"},
|
||||
['tech_h']= {"Tech", "KHÓ", "Cố gắng không phá B2B!"},
|
||||
['tech_h_plus']= {"Tech", "KHÓ+", "Chỉ được clear Spin hoặc PC"},
|
||||
['tech_l']= {"Tech", "RẤT KHÓ", "Cố gắng không phá B2B!"},
|
||||
['tech_l_plus']= {"Tech", "RẤT KHÓ+", "Chỉ được clear Spin hoặc PC"},
|
||||
['tech_finesse']= {"Tech", "HOÀN HẢO", "Không được phép có lỗi di chuyển!"},
|
||||
['tech_finesse_f']= {"Tech", "HOÀN HẢO+", "Không được phép có lỗi di chuyển hoặc loại Xoá hàng thường!"},
|
||||
['tech_finesse_lock']= {"Tech", "FINESSE LOCK", "Không được mắc lỗi di chuyển hoặc bạn không thể điều khiển gạch!"},
|
||||
['tech_finesse_lock_f']= {"Tech", "FINESSE+ LOCK", "Không được mắc lỗi di chuyển hoặc bạn không thể điều khiển gạch! Và không thể dùng kiểu xóa thường!"},
|
||||
['tsd_e']= {"TSD Challenge", "DỄ", "Chỉ được làm T-Spin Double!"}, -- Chỉ được clear…
|
||||
['tech_n']= {"Tech B2B", "THƯỜNG", "Cố gắng không phá B2B!"},
|
||||
['tech_n_plus']= {"Tech B2B", "THƯỜNG+", "Chỉ được clear Spin hoặc PC"},
|
||||
['tech_h']= {"Tech B2B", "KHÓ", "Cố gắng không phá B2B!"},
|
||||
['tech_h_plus']= {"Tech B2B", "KHÓ+", "Chỉ được clear Spin hoặc PC"},
|
||||
['tech_l']= {"Tech B2B", "RẤT KHÓ", "Cố gắng không phá B2B!"},
|
||||
['tech_l_plus']= {"Tech B2B", "RẤT KHÓ+", "Chỉ được clear Spin hoặc PC"},
|
||||
['tech_finesse']= {"Kỹ thuật di chuyển","", "Không được phép có lỗi di chuyển!"},
|
||||
['tech_finesse_f']= {"Kỹ thuật di chuyển","Khg ĐƠN/ĐÔI/TAM","Không được phép có lỗi di chuyển hoặc kiểu Xoá hàng thường!"},
|
||||
['tsd_e']= {"TSD Challenge", "DỄ", "Chỉ được làm T-Spin Double!"},
|
||||
['tsd_h']= {"TSD Challenge", "KHÓ", "Chỉ được làm T-Spin Double!"},
|
||||
['tsd_u']= {"TSD Challenge", "THÁCH ĐẤU", "Chỉ được làm T-Spin Double!"},
|
||||
['backfire_n']= {"Backfire", "THƯỜNG", "Sống sót những hàng rác do chính bạn gửi"},
|
||||
@@ -1034,7 +1044,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
"B2B2B2B tồn tại hả?",
|
||||
"Đừng để những thứ nhỏ nhặt làm bạn nản chí!",
|
||||
"Đây không phải là lỗi, đây là tính năng!",
|
||||
"Hệ thống xoay gạch của Techmino rất đẹp trai!",
|
||||
"Hệ thống xoay gạch của Techmino rất là đẹp trai!",
|
||||
"Em rất tốt nhưng anh rất tiếc…", -- EXCELLENT! But… let's go better next time
|
||||
"Đừng quên xem qua phần cài đặt!",
|
||||
"Nếu bạn thấy có vấn đề gì, hãy lên trang GitHub báo lại cho chúng tôi!",
|
||||
@@ -1054,7 +1064,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
"Hãy tham gia Discord của chúng tôi!",
|
||||
"l-=-1",
|
||||
"Nổi lửa lên em, NỔI LỬA LÊN EM!",
|
||||
"Việc giảm tần số khung hình sẽ mang trải nghiệm tệ hơn cho bạn",
|
||||
"Việc giảm tần số khung hình sẽ mang đến trải nghiệm tệ hơn cho bạn",
|
||||
"LrL RlR LLr RRl RRR LLL FFF RfR RRf rFF",
|
||||
"Mix clear sắp ra mắt!",
|
||||
"Hầu hết các biểu tượng của các nút được vẽ tay vào trong bảng Unicode Private Use Area",
|
||||
@@ -1117,7 +1127,6 @@ C. Tay cầm chơi game (Gamepad):
|
||||
{C.lP,"Con số bí mật: 626"},
|
||||
{C.lR,"Z ",C.lG,"S ",C.lS,"J ",C.lO,"L ",C.lP,"T ",C.lY,"O ",C.lC,"I"},
|
||||
{C.lY,"MÁT QUÁ!!"},
|
||||
{C.N,"Lua",C.Z," No.1"},
|
||||
{C.P,"T-spin!"},
|
||||
{C.R,"DMCA là gì?"},
|
||||
{C.R,"\"Luật sở hữu trí tuệ\""},
|
||||
@@ -1128,7 +1137,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
{C.Z,"Gì? ",C.lC,"Xspin?"},
|
||||
|
||||
|
||||
|
||||
-- Bắt đầu từ đoạn này là mình phải lấy từ bản tiếng Trung nhờ cả Bard lẫn GPT3.5 dịch hộ :|
|
||||
-- TECHMINO FUN FACT
|
||||
-- How do you pronounce Techmino?
|
||||
"Phát âm từ Techmino như thế nào mới đúng?",
|
||||
@@ -1141,14 +1150,13 @@ C. Tay cầm chơi game (Gamepad):
|
||||
-- Techmino's birthday
|
||||
"Ngày sinh nhật của Techmino? Hiện tại (đang giả định) là 26/T6.",
|
||||
-- How to O-spin: Rotate 626 times in one second (mistaken)
|
||||
"Cách O-spin? Nhấn phím xoay 626 lần (ĐÙA ĐẤY ĐỪNG TIN!)",
|
||||
"Cách O-spin? Nhấn phím xoay 626 lần trong 1 giây (ĐÙA ĐẤY ĐỪNG TIN!)",
|
||||
-- Hope you all like Z... Oh no, like Techmino
|
||||
{"Mình mong các bạn sẽ thích ",C.W,"Z",C.Z,"… Ối! Không phải, thích ",C.G,"Techmino",C.Z," cơ! Nhầm nhầm nhầm!"},
|
||||
-- 2021 was the year of Techmino's online debut.
|
||||
"2021 là năm ra mắt chế độ trực tuyến của Techmino.",
|
||||
-- The Chinese name of this game is 'Block Research Institute'.
|
||||
"Tên chính thức của game là \"方块研究所\" (Block Research Institute).",
|
||||
"Một tên khác của game này là \"Tiehu Minuo\"",
|
||||
"Tên chính thức của game là \"方块研究所\"",
|
||||
-- This game is not called Teachmino
|
||||
"Tên game không phải là Teachmino!",
|
||||
--
|
||||
@@ -1171,37 +1179,37 @@ C. Tay cầm chơi game (Gamepad):
|
||||
-- Don't play with your phone if your homework isn't finished.
|
||||
"Đừng chơi điện thoại khi bài tập về nhà còn chưa hoàn thành.",
|
||||
-- Enabling vibration on some mobile systems may cause severe lag."
|
||||
"Bật rung trên điện thoại có thể khiến máy phải thở oxy.",
|
||||
"Bật rung trên một số điện thoại có thể làm cho chúng… phải thở oxy!",
|
||||
-- Eat the button? Really? I suggest you play it back to see if you pressed it and how long it took you to press it"
|
||||
"Phím không ăn? Đùa à? Xem lại replay để chắc rằng ông đã nhấn và xem thử mất bao nhiêu thời gian để ông nhấn phím đó.",
|
||||
"Phím không ăn? Hãy thử kiểm tra lại phím đi!",
|
||||
-- Probably someone will read the tip
|
||||
"Chắc chắn có người đang đọc cái dòng chữ nhỏ đang chạy ở dưới này.",
|
||||
-- It seems like no one has reached a high level by playing with their feet yet.
|
||||
"Hình như tới giờ chưa ai chơi xếp gạch giỏi bằng chân…",
|
||||
-- Moderate gaming is good for the brain. Addiction to games is harmful. Plan your time
|
||||
"Chơi game vừa phải có thể tốt cho bộ não. Nhưng nếu nghiện thì toeng! Nhớ quản lý thời gian nhé!",
|
||||
"Chơi game vừa phải có thể tốt cho bộ não. Nhưng nếu nghiện thì toeng! Nhớ lập th!ời gian biểu nhé!",
|
||||
-- The ability to dig is extremely important in battles!!!
|
||||
"Khả năng đào xuống (downstacking) của bạn là RẤT QUAN TRỌNG trong chiến đấu!!!",
|
||||
-- Skilled players of the Classic Tetris game are also formidable; don't underestimate them
|
||||
"Xếp gạch cổ điển cũng không đơn giản gì như xếp gạch hiện đại đâu. Đừng có mà xem thường những người chơi hệ cổ điển!",
|
||||
"Đừng có mà xem thường những người chơi xếp gạch cổ điển! Chơi cái đó cũng khó không khác gì chơi xếp gạch hiện đại đâu.",
|
||||
-- Classic Tetris and Modern Tetris are two different games; being skilled in one doesn't mean you'll be skilled in the other. You have to start from scratch.
|
||||
"Xếp gạch cổ điển và xếp gạch hiện đại là hai thể loại game khác nhau đấy! Giỏi một trong hai chưa chắc bạn giỏi cả bên còn lại đâu. Bạn phải học lại từ đầu đấy",
|
||||
-- To protect the players' well-being, the game has a temporary and simplified anti-addiction system! (But you probably won't trigger it, haha)
|
||||
"Để tránh việc người chơi nào đó chơi quá lâu, game đã có hệ thống chống nghiện đơn giản tạm thời (Nhưng bạn có lẽ sẽ không bao giờ kích hoạt chúng đâu, haha)",
|
||||
-- Basic stacking and digging skills are crucial; those who neglect these two aspects often regret it (trust me)
|
||||
{"Kỹ năng xếp lên vào đào xuống là 2 kỹ năng RẤT quan trọng; những ai (đã/từng) coi thường/bỏ bê hai khía cạnh này thường hay bị bón hành súp mặt lờ (tin ",C.W,"MrZ",C.Z," đi!)"},
|
||||
{"Kỹ năng xếp lên vào đào xuống là 2 kỹ năng RẤT quan trọng; những ai (đã/từng) coi thường hay bỏ bê hai khía cạnh này thường hay bị bón hành súp mặt lờ (tin ",C.W,"MrZ",C.Z," đi!)"},
|
||||
-- Even if you're topped out, don't give up; every line of garbage can potentially become your weapon.
|
||||
"Ngay cả khi bạn sắp bị top out, đừng bỏ cuộc; vì từng hàng rác có tiềm năng trở thành vũ khí của bạn!",
|
||||
"Đừng bỏ cuộc khi đống hàng rác đang làm bạn sắp bị top out, bởi bạn có thể biến chúng trở thành đòn phản công.",
|
||||
-- The video shown above is not a recording; it's the robot playing in real-time.
|
||||
"Cái ở trên là replay hả? Không, là AI đang chơi trong thời gian thực đấy!",
|
||||
"Cái ở trên là bản ghi sẵn hả? Không, là AI đang chơi trong thời gian thực đấy!",
|
||||
-- Extended gaming sessions will gradually deteriorate your performance! Remember to take breaks when playing for a long time~
|
||||
"THường xuyên chơi game lâu có thể khiến bạn có thể bị đuối sức (cả thể chất và tinh thần, tệ nhất có thể bị stall). Hãy nhớ nghỉ giải lao sau khi chơi lâu nhé!",
|
||||
"Thường xuyên chơi game lâu có thể khiến bạn có thể bị đuối sức (cả thể chất và tinh thần, tệ nhất có thể bị stall). Hãy nhớ nghỉ giải lao sau khi chơi lâu nhé!",
|
||||
-- Be careful of tenosynovitis!
|
||||
{C.R,"CẢNH BÁO! ",C.Z,"Bệnh viêm bao gân cổ tay!"},
|
||||
-- The button with a question mark in the bottom-right corner is the game manual (assuming you haven't enabled the concise mode).
|
||||
-- The button with a question mark in the bottom-right corner is the game manual (assuming you haven't enabled the Simple mode).
|
||||
"Cái nút "..CHAR.icon.help.." ở góc phải dưới cùng trong menu (không bật chế độ Đơn giản) đấy hả? Nó là manual (hướng dẫn sử dụng) của game đấy!",
|
||||
-- If you're new to blocks, just play more games; there isn't much specific targeted practice beyond 40 lines in two minutes
|
||||
"Bạn mới tập chơi xếp gạch à? Nếu vậy cứ chơi nhiều lên. Không có nhiều mục tiêu luyện tập cụ thể ngoài xóa 40 hàng trong 2 phút.",
|
||||
"Bạn mới tập chơi xếp gạch à? Nếu vậy cứ chơi nhiều lên. Không có nhiều mục tiêu luyện tập cụ thể ngoài xóa 40 hàng trong 2 phút đâu!",
|
||||
--
|
||||
"Hãy ra ngoài và chạm cỏ đi!",
|
||||
--
|
||||
@@ -1211,7 +1219,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
--
|
||||
-- Z SAID
|
||||
-- I can't write cool music (crying)
|
||||
{C.W,"Z: ",C.Z,"Tôi không thể nào viết một bản nhạc nào trông ngầu cả (sadge)."},
|
||||
{C.W,"Z: ",C.Z,"Tôi không tài nào viết nổi một bản nhạc nào trông ngầu cả (sadge)."},
|
||||
-- I haven't studied music composition. I just composed it myself. If you really think it's good, that's great!
|
||||
{C.W,"Z: ",C.Z,"Tôi chưa từng học sáng tác nhạc, và tôi chỉ tự sáng tác chúng. Nếu bạn thấy những bản nhạc này hay, thật tuyệt!"},
|
||||
-- What else can I write for tips?
|
||||
@@ -1222,6 +1230,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
{C.W,"Z: ",C.Z,"Tôi tự hỏi là có bao nhiêu người chơi game thực sự quan tâm ai viết ra nó."},
|
||||
--
|
||||
-- IT JOKES
|
||||
{C.N,"Lua",C.Z," No.1"},
|
||||
"git clone --recursive https://github.com/26F-Studio/Techmino.git",
|
||||
"git commit -m \".\"",
|
||||
"git pull = git fetch + git merge",
|
||||
@@ -1232,10 +1241,9 @@ C. Tay cầm chơi game (Gamepad):
|
||||
"git submodule update",
|
||||
"git merge --rebase",
|
||||
"git merge --squash",
|
||||
"Lua No.1",
|
||||
"sudo rm -rf /*",
|
||||
"shutdown /s /t 0", -- Turn off computer completely (no Fast Boot)
|
||||
"shutdown /s /t 0 /hybrid", -- Turn off computer with Fast Boot still activated
|
||||
"shutdown /s /t 0 /hybrid", -- Turn off computer with Fast Boot
|
||||
-- Techmino has reached the limit.
|
||||
"Không thể mở Techmino vì bạn đã quá nghiện game này rồi :>",
|
||||
-- Techmino.exe has stopped working.
|
||||
@@ -1246,26 +1254,25 @@ C. Tay cầm chơi game (Gamepad):
|
||||
--
|
||||
-- CHANGELOG
|
||||
{C.lW, "V0.0.091726",": ",C.Z, "Đã thêm hệ thống xoay TRS"},
|
||||
{C.lW, "V0.7.9 " ,": ",C.Z, "Đã thêm ",C.yellow,"O-spin"},
|
||||
{C.lW, "V0.7.9" ,": ",C.Z, "Đã thêm ",C.yellow,"O-spin"},
|
||||
{C.lW, "V0.7.19" ,": ",C.Z, "Đã thêm hệ thống voice"},
|
||||
{C.lW, "V0.7.22" ,": ",C.Z, "Đã thêm hiệu ứng rơi mượt"},
|
||||
{C.lW, "V0.8.5 " ,": ",C.Z, "Đã thêm map và sắp xếp lại các chế độ"},
|
||||
{C.lW, "V0.8.5" ,": ",C.Z, "Đã thêm map và sắp xếp lại các chế độ"},
|
||||
{C.lW, "V0.8.19" ,": ",C.Z, "Đã thêm Pentomino"},
|
||||
{C.lW, "V0.9.0 " ,": ",C.Z, "Đã thêm chế độ tự do và khả năng tùy biến chuỗi gạch"},
|
||||
{C.lW, "V0.9.0" ,": ",C.Z, "Đã thêm chế độ tự do và khả năng tùy biến chuỗi gạch"},
|
||||
{C.lW, "V0.10.0" ,": ",C.Z, "Đã thêm hệ thống replay"},
|
||||
{C.lW, "V0.11.1" ,": ",C.Z, "Đã thêm Little Z Dictionary (Zictionary)"},
|
||||
{C.lW, "V0.12.2" ,": ",C.Z, "Đã thêm hệ thống mod"},
|
||||
{C.lW, "V0.13.0" ,": ",C.Z, "Thử nghiệm chế độ trực tuyến"},
|
||||
{C.lW, "V0.13.2" ,": ",C.Z, "Đã thêm khả năng tùy biến chiều cao bảng"},
|
||||
{C.lW, "V0.13.3" ,": ",C.Z, "Đã thêm console"},
|
||||
{C.lW, "V0.14.5" ,": ",C.Z, "Đã thêm BGM đầu tiên được làm bởi cộng đồng"},
|
||||
{C.lW, "V0.14.5" ,": ",C.Z, "Đã thêm BGM đầu tiên được remix bởi cộng đồng"},
|
||||
{C.lW, "V0.15.5" ,": ",C.Z, "Đã thêm menu replay"},
|
||||
{C.lW, "V0.16.0" ,": ",C.Z, "Đã thêm hệ thống xoay BiRS"},
|
||||
{C.lW, "V0.16.2" ,": ",C.Z, "Đã thêm studio SFX với phong cách hit pad"},
|
||||
{C.lW, "V0.17.0" ,": ",C.Z, "Đã thêm hõ trợ điều khiển bằng joystick"},
|
||||
{C.lW, "V0.17.3" ,": ",C.Z, "Dừng phát triển Techmino, tập trung phát triển game mới"},
|
||||
{C.lW, "V0.17.12" ,": ",C.Z, "Đã thêm ngôn ngữ tiếng Việt"},
|
||||
{C.lW, "V0.17.15" ,": ",C.Z, "Hoàn thiện bản dịch tiếng Việt?"},
|
||||
--
|
||||
-- MATH FORMULAS
|
||||
"(a+b)²=a²+2ab+b²",
|
||||
@@ -1289,19 +1296,22 @@ C. Tay cầm chơi game (Gamepad):
|
||||
"sin²α-sin²β=S(α+β)S(α-β)",
|
||||
"sin2α=2SαCα",
|
||||
--
|
||||
-- FROM SEA
|
||||
-- SEA'S JOKE
|
||||
{C.W,"MrZ",C.Z," còn có một biệt danh dễ thương hơn, đó là ",C.W,"Z-Chan"},
|
||||
"Có hơn 400 mẹo bạn có thể nhìn thấy ở đây, là cái dòng chữ này, nếu bạn đang chơi Techmino tiếng Trung",
|
||||
|
||||
{C.lSea,"Sea: ",C.Z,"Tui không có đủ mặn để viết joke. Nên một số câu đùa đang chạy ở đây được viết bởi ",C.yellow,"Shard Nguyễn",C.Z,". \"Em cảm ơn anh!\""},
|
||||
{C.lSea,"Sea: ",C.Z,"Tui đang tự hỏi liệu còn bao nhiêu lỗi tui bỏ sót lúc dịch game không? Tính ra tui đã cập nhật đi cập nhật lại cũng 4-5 lần rồi."},
|
||||
|
||||
{"Cộng đồng Tetris ",C.R,"Việt ",C.lY,"Nam ",C.Z,": https://discord.gg/jX7BX9g"}, -- Tetris Vietnam
|
||||
{"Cộng đồng Tetris ",C.R,"Việt ",C.lY,"Nam ",C.Z,": https://discord.gg/hoiphuhovietnam"}, -- Tetris Vietnam (TVN)
|
||||
{"\"Tetris Việt Nam\"? Không, đó là \"Hội phụ hồ Việt Nam\""},
|
||||
{C.W,"MrZ ",C.Z,"vẫn chưa biết chọn tên nào để đặt cho từ điển của Techmino. Hiện có 3 tên: \"Zictionary\", \"TetroDictionary\" và \"Little Z Dictionary\""},
|
||||
"Ủa tao nhớ game này tên là xếp hình mà? Ừ thì đúng nhưng để giữ độ đồng nhất và tránh bị cấn mồm thì nên gọi game này là game xếp gạch.",
|
||||
"Mình xin phép ủng hộ cho player này. Ủng hộ càng nhiều tỉ lệ thắng càng cao!",
|
||||
{"Aiiiii mua cần phô mai ủng hộ ",C.yellow,"Chủ tiệm phô mai",C.Z," không?"}, -- A joke
|
||||
{"Hôm nay là ngày ",os.date("%d"),"/",all_month[tonumber(os.date("%m"))],"/",os.date("%Y")}, -- inspired from Nokia 1280, activating talking clock by holding * key at main menu
|
||||
{"Aiiiii mua cần phô mai ủng hộ ",C.yellow,"Chủ tiệm phô mai",C.Z," không?"}, -- A joke in TVN
|
||||
-- Who will you choose? A girl that can break up to you and make you sad
|
||||
-- Or choose Katyusha that can warm your heart and 40ha land of enemy.
|
||||
"Bạn sẽ chọn ai? Một em gái có thể chia tay và làm bạn buồn? Hay là chọn em Katyusha có thể làm ấm lòng bạn và 40ha đất kẻ thù?", -- Based on a comment in https://www.youtube.com/watch?v=nczdLwTyWmY
|
||||
},
|
||||
pumpkin="Tôi là một quả bí ngô",
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ return {
|
||||
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="Half Clear",
|
||||
PC="Perfect Clear",HPC="Half PC",
|
||||
replaying="[回放]",
|
||||
tasUsing="[TAS]",
|
||||
|
||||
@@ -43,6 +43,7 @@ return {
|
||||
infHeightOn="无限高度 开",
|
||||
infHeightOff="无限高度 关",
|
||||
infHeightHint="用功能键1切换",
|
||||
-- highestGrade="(highest: $1)",
|
||||
|
||||
speedLV="速度等级",
|
||||
piece="块数",line="行数",atk="攻击",eff="效率",
|
||||
@@ -54,7 +55,7 @@ return {
|
||||
|
||||
win="胜利",
|
||||
lose="失败",
|
||||
|
||||
torikan="未达标",
|
||||
finish="完成",
|
||||
gamewin="胜利",
|
||||
gameover="游戏结束",
|
||||
@@ -66,10 +67,13 @@ return {
|
||||
|
||||
page="页面:",
|
||||
|
||||
ai_puzzle="不能同时开启AI和拼图模式",
|
||||
ai_mission="不能同时开启AI和自定义任务",
|
||||
ai_badPiece="不能同时开启AI和含有非四连块的自定义序列",
|
||||
cc_fixed="不能同时开启CC和固定序列",
|
||||
cc_swap="不能同时开启CC和swap的暂存模式",
|
||||
ai_prebag="不能同时开启AI和含有非四连块的自定义序列",
|
||||
ai_mission="不能同时开启AI和自定义任务",
|
||||
cc_solid="开启CC时不能存在预先填满的行",
|
||||
cc_field_too_high="开启CC时最高出块高度不能超过40",
|
||||
switchSpawnSFX="请开启方块生成音效",
|
||||
needRestart="重新开始以生效",
|
||||
|
||||
@@ -91,6 +95,8 @@ return {
|
||||
dataCorrupted="数据损坏",
|
||||
pasteWrongPlace="提醒:可能粘贴错地方了",
|
||||
noFile="找不到文件",
|
||||
invalidSequence="无效序列模式",
|
||||
tooHighField="超过126行的场地数据已被丢弃",
|
||||
|
||||
nowPlaying="正在播放:",
|
||||
|
||||
@@ -233,7 +239,7 @@ return {
|
||||
"落块:",
|
||||
"消行/挖掘:",
|
||||
"攻击/挖掘攻击:",
|
||||
"上涨/接收/抵消:",
|
||||
"上涨(接收-抵消):",
|
||||
"消除:",
|
||||
"Spin:",
|
||||
"B2B/B3B/PC/HPC:",
|
||||
@@ -297,7 +303,7 @@ return {
|
||||
"LawrenceLiu",
|
||||
"Gompyn",
|
||||
"flaribbit",
|
||||
"schh",
|
||||
"scdhh",
|
||||
"",
|
||||
"视觉设计、UI和UX",
|
||||
"MrZ",
|
||||
@@ -327,6 +333,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -404,7 +411,7 @@ return {
|
||||
|
||||
手柄:
|
||||
按 $10 to 显示帮助
|
||||
按 $5 或 $6 滚动文本, 按 $11 加速
|
||||
按 $5 或 $6 滚动文本
|
||||
按 $7 打开上一词条,按 $8 打开下一词条。按住 $11 加速
|
||||
按住 $11 并按 $6 缩小字号,或 $5 增大字号]]
|
||||
-- 1-4: Up, Down, Left, Right
|
||||
@@ -489,7 +496,7 @@ return {
|
||||
capacity="房间容量",
|
||||
create="创建",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="强制极简",
|
||||
b2bKill="强制B2B",
|
||||
lockout="锁定在外时失败",
|
||||
@@ -572,6 +579,10 @@ return {
|
||||
bg_on="普通背景",
|
||||
bg_off="关闭背景",
|
||||
bg_custom="应用自定义背景",
|
||||
defaultBG="默认背景",
|
||||
resetDbg="改回默认",
|
||||
lockBG="锁定背景",
|
||||
noTheme="关闭节日主题",
|
||||
|
||||
blockSatur="方块饱和度",
|
||||
fieldSatur="场地饱和度",
|
||||
@@ -706,7 +717,7 @@ return {
|
||||
|
||||
bufferLimit="缓冲上限",
|
||||
heightLimit="高度上限",
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="强制极简",
|
||||
b2bKill="强制B2B",
|
||||
lockout="锁定在外时失败",
|
||||
@@ -853,7 +864,9 @@ return {
|
||||
['sprint_100l']= {"竞速", "100L", "消除100行"},
|
||||
['sprint_400l']= {"竞速", "400L", "消除400行"},
|
||||
['sprint_1000l']= {"竞速", "1000L", "消除1000行"},
|
||||
['secret_grade']= {"秘密段位", "", "按照提示完成经典的“大于号”拼图"},
|
||||
['construct_sg']= {"拼花", "秘密段位", "按照提示完成经典的“大于号”拼图"},
|
||||
['construct_checker']={"拼花", "棋盘", "按照提示搭建棋盘的图案"},
|
||||
['construct_invsg']= {"拼花", "折线", "按照提示搭建折线图案"},
|
||||
['sprintPenta']= {"竞速", "五连块", "伤脑筋十八块"},
|
||||
['sprintMPH']= {"竞速", "MPH", "纯随机\n无预览\n无暂存"},
|
||||
['sprint123']= {"竞速", "M123", "40L,但只有1~3连块"},
|
||||
@@ -886,8 +899,8 @@ return {
|
||||
['round_h']= {"回合制", "困难", "下棋模式"},
|
||||
['round_l']= {"回合制", "疯狂", "下棋模式"},
|
||||
['round_u']= {"回合制", "极限", "下棋模式"},
|
||||
['big_n']= {"大方块", "普通", "模拟5×10场地的玩法(标准尺寸的一半)"},
|
||||
['big_h']= {"大方块", "困难", "模拟5×10场地的玩法(标准尺寸的一半)"},
|
||||
['big_n']= {"大方块", "普通", "模拟5×10场地(标准尺寸的一半)"},
|
||||
['big_h']= {"大方块", "困难", "模拟5×10场地(标准尺寸的一半)"},
|
||||
['master_n']= {"大师", "普通", "20G初心者练习"},
|
||||
['master_h']= {"大师", "困难", "上级者20G挑战"},
|
||||
['master_m']= {"大师", "大师", "大师20G"},
|
||||
@@ -939,8 +952,6 @@ return {
|
||||
['tech_l_plus']= {"科研", "疯狂+", "仅允许spin与PC"},
|
||||
['tech_finesse']= {"科研", "极简", "强制最简操作"},
|
||||
['tech_finesse_f']= {"科研", "极简+", "禁止普通消除,强制最简操作"},
|
||||
['tech_finesse_lock']= {"科研", "极简限制", "限制操作次数"},
|
||||
['tech_finesse_lock_f']={"科研", "极简限制+", "限制操作次数,禁止断B2B"},
|
||||
['tsd_e']= {"TSD挑战", "简单", "你能连续做几个TSD?"},
|
||||
['tsd_h']= {"TSD挑战", "困难", "你能连续做几个TSD?"},
|
||||
['tsd_u']= {"TSD挑战", "极限", "你能连续做几个TSD?"},
|
||||
|
||||
@@ -42,6 +42,7 @@ return {
|
||||
infHeightOn="infHeight=true",
|
||||
infHeightOff="infHeight=false",
|
||||
infHeightHint="F1:!infHeight",
|
||||
highestGrade="(max=$1)",
|
||||
|
||||
speedLV="P.SpeedLV",
|
||||
piece="P.Piece",line="P.Line",atk="P.ATK",eff="P.EFF",
|
||||
@@ -53,7 +54,7 @@ return {
|
||||
|
||||
win="Win();",
|
||||
lose="Lose();",
|
||||
|
||||
torikan="Torikan();",
|
||||
finish="Result=Finish",
|
||||
gamewin="Result=Win",
|
||||
gameover="Result=GameOver",
|
||||
@@ -65,10 +66,13 @@ return {
|
||||
|
||||
page="Page=",
|
||||
|
||||
cc_fixed=" if (AI==CC and Sequence==Fixed) then Error(); end",
|
||||
cc_swap=" if (AI==CC and Hold.Mode==Swap) then Error(); end",
|
||||
ai_prebag=" if (AI==true and Ctm.Seq~=Tetromino) then Error(); end",
|
||||
ai_mission=" if (AI==true and Ctm.Mission~=true) then Error(); end",
|
||||
ai_puzzle="assert(AI==true and Ctm.Mission~=true)",
|
||||
ai_mission="assert(AI==true and Ctm.Mission~=true)",
|
||||
ai_badPiece="assert(AI==true and Ctm.Seq~=Tetromino)",
|
||||
cc_fixed="assert(AI==CC and Sequence==Fixed)",
|
||||
cc_swap="assert(AI==CC and Hold.Mode==Swap)",
|
||||
cc_solid="assert(AI==CC and filledLine in Field)",
|
||||
cc_field_too_high="assert(AI==CC and Field.Height>=40)",
|
||||
switchSpawnSFX="SpawnSFX=false",
|
||||
needRestart="NeedRestart=true",
|
||||
|
||||
@@ -90,6 +94,8 @@ return {
|
||||
dataCorrupted="Error.DataCorrupted();",
|
||||
pasteWrongPlace="Error.PasteWrongPlace();",
|
||||
noFile="Error.NoFile();",
|
||||
invalidSequence="Error.InvalidSequenceMode();",
|
||||
tooHighField="Error.TooHighField();",
|
||||
|
||||
nowPlaying="NowPlaying=",
|
||||
|
||||
@@ -99,7 +105,7 @@ return {
|
||||
|
||||
noScore="NoScore=true",
|
||||
modeLocked="Locked=true",
|
||||
unlockHint=" if (PreviousMode<=B) then Unlock();",
|
||||
unlockHint="if (PreviousMode<=B) then Unlock();",
|
||||
highScore="HighScore",
|
||||
newRecord="NewRecord=true",
|
||||
|
||||
@@ -181,7 +187,7 @@ return {
|
||||
"P.Pieces",
|
||||
"P.Row/Dig",
|
||||
"P.Atk/DAtk",
|
||||
"P.Receive",
|
||||
"P.Rise(P.Receive-P.Offset)",
|
||||
"P.Clear",
|
||||
"P.Spin",
|
||||
"P.B2B/B3B;P.PC/HPC",
|
||||
@@ -195,7 +201,7 @@ return {
|
||||
"Stat.Time = ",
|
||||
"Stat.Key/Rot/Hold = ",
|
||||
"Stat.Block/Row/Atk = ",
|
||||
"Stat.Recv/Res/Asc = ",
|
||||
"Stat.Recv/Offset/Rise = ",
|
||||
"Stat.Dig/DAtk = ",
|
||||
"Stat.Eff/DEff = ",
|
||||
"Stat.B2B/B3B = ",
|
||||
@@ -245,7 +251,7 @@ return {
|
||||
"LawrenceLiu",
|
||||
"Gompyn",
|
||||
"flaribbit",
|
||||
"schh",
|
||||
"scdhh",
|
||||
"",
|
||||
"视觉设计、UI和UX",
|
||||
"MrZ",
|
||||
@@ -275,6 +281,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -491,6 +498,10 @@ return {
|
||||
bg_on="Set.BG(Normal);",
|
||||
bg_off="Set.BG(Off);",
|
||||
bg_custom="Set.BG(Ctm);",
|
||||
-- defaultBG="Default B.G.",
|
||||
-- resetDbg="Reset to default",
|
||||
-- lockBG="Lock B.G.",
|
||||
-- noTheme="Disable theme",
|
||||
|
||||
blockSatur="Set.BlockSatur",
|
||||
fieldSatur="Set.FieldSatur",
|
||||
@@ -766,116 +777,116 @@ return {
|
||||
},
|
||||
},
|
||||
modes={
|
||||
['sprint_10l']= {"Sprint(10L);", "", "消除10行"},
|
||||
['sprint_20l']= {"Sprint(20L);", "", "消除20行"},
|
||||
['sprint_40l']= {"Sprint(40L);", "", "消除40行"},
|
||||
['sprint_100l']= {"Sprint(100L);", "", "消除100行"},
|
||||
['sprint_400l']= {"Sprint(400L);", "", "消除400行"},
|
||||
['sprint_1000l']= {"Sprint(1000L);", "", "消除1000行"},
|
||||
['secret_grade']= {"SecretGrade();", "", "按照提示完成经典的“大于号”拼图"},
|
||||
['sprintPenta']= {"Sprint(Penta);", "", "伤脑筋十八块"},
|
||||
['sprintMPH']= {"Sprint(MPH);", "", "纯随机\n无预览\n无暂存"},
|
||||
['sprint123']= {"Sprint(M123);", "", "40L,但只有1~3连块"},
|
||||
['dig_10l']= {"Dig(10L);", "", "挖掘10行"},
|
||||
['dig_40l']= {"Dig(40L);", "", "挖掘40行"},
|
||||
['dig_100l']= {"Dig(100L);", "", "挖掘100行"},
|
||||
['dig_400l']= {"Dig(400L);", "", "挖掘400行"},
|
||||
['dig_eff_10l']= {"DigEff(10L);", "", "用尽量少的块数挖掘10行"},
|
||||
['dig_eff_40l']= {"DigEff(40L);", "", "用尽量少的块数挖掘40行"},
|
||||
['dig_eff_100l']= {"DigEff(100L);", "", "用尽量少的块数挖掘100行"},
|
||||
['dig_eff_400l']= {"DigEff(400L);", "", "用尽量少的块数挖掘400行"},
|
||||
['dig_quad_10l']= {"DigQuad(10L);", "", "挖掘10行,但只能消四"},
|
||||
['drought_n']= {"Drought(100L);", "", "你I没了"},
|
||||
['drought_l']= {"DroughtP(100L);", "", "后 妈 发 牌"},
|
||||
['marathon_n']= {"Marathon(Normal);", "", "200行加速马拉松"},
|
||||
['marathon_h']= {"Marathon(Hard);", "", "200行高速马拉松"},
|
||||
['solo_e']= {"Solo(Easy);", "", "打败AI"},
|
||||
['solo_n']= {"Solo(Normal);", "", "打败AI"},
|
||||
['solo_h']= {"Solo(Hard);", "", "打败AI"},
|
||||
['solo_l']= {"Solo(Lunatic);", "", "打败AI"},
|
||||
['solo_u']= {"Solo(Ultimate);", "", "打败AI"},
|
||||
['techmino49_e']= {"Tech49(Easy);", "", "49人混战,活到最后"},
|
||||
['techmino49_h']= {"Tech49(Hard);", "", "49人混战,活到最后"},
|
||||
['techmino49_u']= {"Tech49(Ultimate);", "", "49人混战,活到最后"},
|
||||
['techmino99_e']= {"Tech99(Easy);", "", "99人混战,活到最后"},
|
||||
['techmino99_h']= {"Tech99(Hard);", "", "99人混战,活到最后"},
|
||||
['techmino99_u']= {"Tech99(Ultimate);", "", "99人混战,活到最后"},
|
||||
['round_e']= {"Round(Easy);", "", "下棋模式"},
|
||||
['round_n']= {"Round(Normal);", "", "下棋模式"},
|
||||
['round_h']= {"Round(Hard);", "", "下棋模式"},
|
||||
['round_l']= {"Round(Lunatic);", "", "下棋模式"},
|
||||
['round_u']= {"Round(Ultimate);", "", "下棋模式"},
|
||||
['big_n']= {"Big(Normal);", "", "模拟10*5场地的玩法(标准尺寸的一半)"},
|
||||
['big_h']= {"Big(Hard);", "", "模拟10*5场地的玩法(标准尺寸的一半)"},
|
||||
['master_n']= {"Master(Normal);", "", "20G初心者练习"},
|
||||
['master_h']= {"Master(Hard);", "", "上级者20G挑战"},
|
||||
['master_m']= {"Master(M21);", "", "大师20G"},
|
||||
['master_final']= {"Master(Final);", "", "究极20G:无法触及的终点"},
|
||||
['master_ph']= {"Master(Phantasm);", "", "虚幻20G:???"},
|
||||
['master_g']= {"Master(Graded);", "", "20G段位考试"},
|
||||
['master_ex']= {"Master(EX);", "", "成为方块大师"},
|
||||
['master_instinct']={"Master(Instinct);", "", "当前块在出现后一小会后会隐形"},
|
||||
['strategy_e']= {"Strategy(Easy);", "", "20G堆叠中速决策练习"},
|
||||
['strategy_h']= {"Strategy(Hard);", "", "20G堆叠快速决策练习"},
|
||||
['strategy_u']= {"Strategy(Ultimate);", "", "20G堆叠极速决策练习"},
|
||||
['strategy_e_plus']={"Strategy(EasyP);", "", "20G堆叠中速决策练习\n无Hold"},
|
||||
['strategy_h_plus']={"Strategy(HardP);", "", "20G堆叠快速决策练习\n无Hold"},
|
||||
['strategy_u_plus']={"Strategy(UltimateP);","", "20G堆叠极速决策练习\n无Hold"},
|
||||
['blind_e']= {"Blind(Slow);", "", "不强大脑"},
|
||||
['blind_n']= {"Blind(Fast);", "", "挺强大脑"},
|
||||
['blind_h']= {"Blind(Instant);", "", "很强大脑"},
|
||||
['blind_l']= {"Blind(NoGhost);", "", "最强大脑"},
|
||||
['blind_u']= {"Blind(NoField);", "", "你准备好了吗"},
|
||||
['blind_wtf']= {"Blind(Voie);" , "", "还没准备好"},
|
||||
['classic_e']= {"Classic(Easy);", "", "高速经典"},
|
||||
['classic_h']= {"Classic(Hard);", "", "飞速经典"},
|
||||
['classic_l']= {"Classic(Lunatic);", "", "极速经典"},
|
||||
['classic_u']= {"Classic(Ultimate);", "", "光速经典"},
|
||||
['survivor_e']= {"Surviver(Easy);", "", "你能存活多久?"},
|
||||
['survivor_n']= {"Surviver(Normal);", "", "你能存活多久?"},
|
||||
['survivor_h']= {"Surviver(Hard);", "", "你能存活多久?"},
|
||||
['survivor_l']= {"Surviver(Lunatic);", "", "你能存活多久?"},
|
||||
['survivor_u']= {"Surviver(Ultimate);", "", "你能存活多久?"},
|
||||
['attacker_h']= {"Attacker(Hard);", "", "进攻练习"},
|
||||
['attacker_u']= {"Attacker(Ultimate);", "", "进攻练习"},
|
||||
['defender_n']= {"Defender(Normal);", "", "防守练习"},
|
||||
['defender_l']= {"Defender(Lunatic);", "", "防守练习"},
|
||||
['dig_h']= {"Dig(Hard);", "", "挖掘练习"},
|
||||
['dig_u']= {"Dig(Ultimate);", "", "挖掘练习"},
|
||||
['c4wtrain_n']= {"C4WTrain(Normal);", "", "无 限 连 击"},
|
||||
['c4wtrain_l']= {"C4WTrain(Lunatic);", "", "无 限 连 击"},
|
||||
['pctrain_n']= {"PCTrain(Normal);", "", "简易PC题库,熟悉全清定式的组合"},
|
||||
['pctrain_l']= {"PCTrain(Lunatic);", "", "困难PC题库,强算力者进"},
|
||||
['pc_n']= {"PC(Normal);", "", "100行内刷PC"},
|
||||
['pc_h']= {"PC(Hard);", "", "100行内刷PC"},
|
||||
['pc_l']= {"PC(Lunatic);", "", "100行内刷PC"},
|
||||
['pc_inf']= {"PC(Inf);", "", "你能连续做多少PC?"},
|
||||
['tech_n']= {"Tech(Normal);", "", "禁止断B2B"},
|
||||
['tech_n_plus']= {"Tech(NormalP);", "", "仅允许spin与PC"},
|
||||
['tech_h']= {"Tech(Hard);", "", "禁止断B2B"},
|
||||
['tech_h_plus']= {"Tech(HardP);", "", "仅允许spin与PC"},
|
||||
['tech_l']= {"Tech(Lunatic);", "", "禁止断B2B"},
|
||||
['tech_l_plus']= {"Tech(LunaticP);", "", "仅允许spin与PC"},
|
||||
['tech_finesse']= {"Tech(Finesse);", "", "强制最简操作"},
|
||||
['tech_finesse_f']= {"Tech(FinesseF);", "", "禁止普通消除,强制最简操作"},
|
||||
['tech_finesse_lock']= {"Tech(FineeseLock);","", "限制操作次数"},
|
||||
['tech_finesse_lock_f']={"Tech(FineeseLockF);","", "限制操作次数,禁止断B2B"},
|
||||
['tsd_e']= {"TSD(Easy);", "", "你能连续做几个TSD?"},
|
||||
['tsd_h']= {"TSD(Hard);", "", "你能连续做几个TSD?"},
|
||||
['tsd_u']= {"TSD(Ultimate);", "", "你能连续做几个TSD?"},
|
||||
['backfire_n']= {"Backfire(Normal);", "", "打出100攻击"},
|
||||
['backfire_h']= {"Backfire(Hard);", "", "打出100攻击"},
|
||||
['backfire_l']= {"Backfire(Lunatic);", "", "打出100攻击"},
|
||||
['backfire_u']= {"Backfire(Ultimate);", "", "打出100攻击"},
|
||||
['sprintAtk']= {"Sprint(100ATK);", "", "打出100攻击"},
|
||||
['sprintEff']= {"Sprint(EFF);", "", "40行内打出更高的攻击"},
|
||||
['zen']= {"Zen(200L);", "", "不限时200行"},
|
||||
['ultra']= {"Ultra(EXTRA);", "", "在两分钟内尽可能拿到最多的分数"},
|
||||
['infinite']= {"Infinite();", "", "沙盒"},
|
||||
['infinite_dig']= {"InfDig();", "", "挖呀挖呀挖"},
|
||||
['marathon_inf']= {"Marathon(Inf);", "", "无尽马拉松"},
|
||||
['sprint_10l']= {"Sprint(10L);", "", "消除10行"},
|
||||
['sprint_20l']= {"Sprint(20L);", "", "消除20行"},
|
||||
['sprint_40l']= {"Sprint(40L);", "", "消除40行"},
|
||||
['sprint_100l']= {"Sprint(100L);", "", "消除100行"},
|
||||
['sprint_400l']= {"Sprint(400L);", "", "消除400行"},
|
||||
['sprint_1000l']= {"Sprint(1000L);", "", "消除1000行"},
|
||||
['construct_sg']= {"Construct(SecretGrade);", "", "按照提示完成经典的“大于号”拼图"},
|
||||
['construct_checker']= {"Construct", "", "按照提示搭建棋盘的图案"},
|
||||
['construct_invsg']= {"Construct", "", "按照提示搭建折线图案"},
|
||||
['sprintPenta']= {"Sprint(Penta);", "", "伤脑筋十八块"},
|
||||
['sprintMPH']= {"Sprint(MPH);", "", "纯随机\n无预览\n无暂存"},
|
||||
['sprint123']= {"Sprint(M123);", "", "40L,但只有1~3连块"},
|
||||
['dig_10l']= {"Dig(10L);", "", "挖掘10行"},
|
||||
['dig_40l']= {"Dig(40L);", "", "挖掘40行"},
|
||||
['dig_100l']= {"Dig(100L);", "", "挖掘100行"},
|
||||
['dig_400l']= {"Dig(400L);", "", "挖掘400行"},
|
||||
['dig_eff_10l']= {"DigEff(10L);", "", "用尽量少的块数挖掘10行"},
|
||||
['dig_eff_40l']= {"DigEff(40L);", "", "用尽量少的块数挖掘40行"},
|
||||
['dig_eff_100l']= {"DigEff(100L);", "", "用尽量少的块数挖掘100行"},
|
||||
['dig_eff_400l']= {"DigEff(400L);", "", "用尽量少的块数挖掘400行"},
|
||||
['dig_quad_10l']= {"DigQuad(10L);", "", "挖掘10行,但只能消四"},
|
||||
['drought_n']= {"Drought(100L);", "", "你I没了"},
|
||||
['drought_l']= {"DroughtP(100L);", "", "后 妈 发 牌"},
|
||||
['marathon_n']= {"Marathon(Normal);", "", "200行加速马拉松"},
|
||||
['marathon_h']= {"Marathon(Hard);", "", "200行高速马拉松"},
|
||||
['solo_e']= {"Solo(Easy);", "", "打败AI"},
|
||||
['solo_n']= {"Solo(Normal);", "", "打败AI"},
|
||||
['solo_h']= {"Solo(Hard);", "", "打败AI"},
|
||||
['solo_l']= {"Solo(Lunatic);", "", "打败AI"},
|
||||
['solo_u']= {"Solo(Ultimate);", "", "打败AI"},
|
||||
['techmino49_e']= {"Tech49(Easy);", "", "49人混战,活到最后"},
|
||||
['techmino49_h']= {"Tech49(Hard);", "", "49人混战,活到最后"},
|
||||
['techmino49_u']= {"Tech49(Ultimate);", "", "49人混战,活到最后"},
|
||||
['techmino99_e']= {"Tech99(Easy);", "", "99人混战,活到最后"},
|
||||
['techmino99_h']= {"Tech99(Hard);", "", "99人混战,活到最后"},
|
||||
['techmino99_u']= {"Tech99(Ultimate);", "", "99人混战,活到最后"},
|
||||
['round_e']= {"Round(Easy);", "", "下棋模式"},
|
||||
['round_n']= {"Round(Normal);", "", "下棋模式"},
|
||||
['round_h']= {"Round(Hard);", "", "下棋模式"},
|
||||
['round_l']= {"Round(Lunatic);", "", "下棋模式"},
|
||||
['round_u']= {"Round(Ultimate);", "", "下棋模式"},
|
||||
['big_n']= {"Big(Normal);", "", "模拟5x10场地(标准尺寸的一半)"},
|
||||
['big_h']= {"Big(Hard);", "", "模拟5x10场地(标准尺寸的一半)"},
|
||||
['master_n']= {"Master(Normal);", "", "20G初心者练习"},
|
||||
['master_h']= {"Master(Hard);", "", "上级者20G挑战"},
|
||||
['master_m']= {"Master(M21);", "", "大师20G"},
|
||||
['master_final']= {"Master(Final);", "", "究极20G:无法触及的终点"},
|
||||
['master_ph']= {"Master(Phantasm);", "", "虚幻20G:???"},
|
||||
['master_g']= {"Master(Graded);", "", "20G段位考试"},
|
||||
['master_ex']= {"Master(EX);", "", "成为方块大师"},
|
||||
['master_instinct']= {"Master(Instinct);", "", "当前块在出现后一小会后会隐形"},
|
||||
['strategy_e']= {"Strategy(Easy);", "", "20G堆叠中速决策练习"},
|
||||
['strategy_h']= {"Strategy(Hard);", "", "20G堆叠快速决策练习"},
|
||||
['strategy_u']= {"Strategy(Ultimate);", "", "20G堆叠极速决策练习"},
|
||||
['strategy_e_plus']= {"Strategy(EasyP);", "", "20G堆叠中速决策练习\n无Hold"},
|
||||
['strategy_h_plus']= {"Strategy(HardP);", "", "20G堆叠快速决策练习\n无Hold"},
|
||||
['strategy_u_plus']= {"Strategy(UltimateP);", "", "20G堆叠极速决策练习\n无Hold"},
|
||||
['blind_e']= {"Blind(Slow);", "", "不强大脑"},
|
||||
['blind_n']= {"Blind(Fast);", "", "挺强大脑"},
|
||||
['blind_h']= {"Blind(Instant);", "", "很强大脑"},
|
||||
['blind_l']= {"Blind(NoGhost);", "", "最强大脑"},
|
||||
['blind_u']= {"Blind(NoField);", "", "你准备好了吗"},
|
||||
['blind_wtf']= {"Blind(Voie);" , "", "还没准备好"},
|
||||
['classic_e']= {"Classic(Easy);", "", "高速经典"},
|
||||
['classic_h']= {"Classic(Hard);", "", "飞速经典"},
|
||||
['classic_l']= {"Classic(Lunatic);", "", "极速经典"},
|
||||
['classic_u']= {"Classic(Ultimate);", "", "光速经典"},
|
||||
['survivor_e']= {"Survivor(Easy);", "", "你能存活多久?"},
|
||||
['survivor_n']= {"Survivor(Normal);", "", "你能存活多久?"},
|
||||
['survivor_h']= {"Survivor(Hard);", "", "你能存活多久?"},
|
||||
['survivor_l']= {"Survivor(Lunatic);", "", "你能存活多久?"},
|
||||
['survivor_u']= {"Survivor(Ultimate);", "", "你能存活多久?"},
|
||||
['attacker_h']= {"Attacker(Hard);", "", "进攻练习"},
|
||||
['attacker_u']= {"Attacker(Ultimate);", "", "进攻练习"},
|
||||
['defender_n']= {"Defender(Normal);", "", "防守练习"},
|
||||
['defender_l']= {"Defender(Lunatic);", "", "防守练习"},
|
||||
['dig_h']= {"Dig(Hard);", "", "挖掘练习"},
|
||||
['dig_u']= {"Dig(Ultimate);", "", "挖掘练习"},
|
||||
['c4wtrain_n']= {"C4WTrain(Normal);", "", "无 限 连 击"},
|
||||
['c4wtrain_l']= {"C4WTrain(Lunatic);", "", "无 限 连 击"},
|
||||
['pctrain_n']= {"PCTrain(Normal);", "", "简易PC题库,熟悉全清定式的组合"},
|
||||
['pctrain_l']= {"PCTrain(Lunatic);", "", "困难PC题库,强算力者进"},
|
||||
['pc_n']= {"PC(Normal);", "", "100行内刷PC"},
|
||||
['pc_h']= {"PC(Hard);", "", "100行内刷PC"},
|
||||
['pc_l']= {"PC(Lunatic);", "", "100行内刷PC"},
|
||||
['pc_inf']= {"PC(Inf);", "", "你能连续做多少PC?"},
|
||||
['tech_n']= {"Tech(Normal);", "", "禁止断B2B"},
|
||||
['tech_n_plus']= {"Tech(NormalP);", "", "仅允许spin与PC"},
|
||||
['tech_h']= {"Tech(Hard);", "", "禁止断B2B"},
|
||||
['tech_h_plus']= {"Tech(HardP);", "", "仅允许spin与PC"},
|
||||
['tech_l']= {"Tech(Lunatic);", "", "禁止断B2B"},
|
||||
['tech_l_plus']= {"Tech(LunaticP);", "", "仅允许spin与PC"},
|
||||
['tech_finesse']= {"Tech(Finesse);", "", "强制最简操作"},
|
||||
['tech_finesse_f']= {"Tech(FinesseF);", "", "禁止普通消除,强制最简操作"},
|
||||
['tsd_e']= {"TSD(Easy);", "", "你能连续做几个TSD?"},
|
||||
['tsd_h']= {"TSD(Hard);", "", "你能连续做几个TSD?"},
|
||||
['tsd_u']= {"TSD(Ultimate);", "", "你能连续做几个TSD?"},
|
||||
['backfire_n']= {"Backfire(Normal);", "", "打出100攻击"},
|
||||
['backfire_h']= {"Backfire(Hard);", "", "打出100攻击"},
|
||||
['backfire_l']= {"Backfire(Lunatic);", "", "打出100攻击"},
|
||||
['backfire_u']= {"Backfire(Ultimate);", "", "打出100攻击"},
|
||||
['sprintAtk']= {"Sprint(100ATK);", "", "打出100攻击"},
|
||||
['sprintEff']= {"Sprint(EFF);", "", "40行内打出更高的攻击"},
|
||||
['zen']= {"Zen(200L);", "", "不限时200行"},
|
||||
['ultra']= {"Ultra(EXTRA);", "", "在两分钟内尽可能拿到最多的分数"},
|
||||
['infinite']= {"Infinite();", "", "沙盒"},
|
||||
['infinite_dig']= {"InfDig();", "", "挖呀挖呀挖"},
|
||||
['marathon_inf']= {"Marathon(Inf);", "", "无尽马拉松"},
|
||||
|
||||
['custom_clear']= {"Ctm(Clear);", ""},
|
||||
['custom_puzzle']= {"Ctm(Puzzle);", ""},
|
||||
['custom_clear']= {"Custom(Clear);", ""},
|
||||
['custom_puzzle']= {"Custom(Puzzle);", ""},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ return {
|
||||
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="Half Clear",
|
||||
PC="Perfect Clear",HPC="Half PC",
|
||||
replaying="[重播]",
|
||||
tasUsing="[TAS]",
|
||||
|
||||
@@ -43,6 +43,7 @@ return {
|
||||
infHeightOn="無限高度 開",
|
||||
infHeightOff="無限高度 關",
|
||||
infHeightHint="用功能鍵1切換",
|
||||
-- highestGrade="(highest: $1)",
|
||||
|
||||
speedLV="速度等級",
|
||||
piece="塊數",line="行數",atk="攻擊",eff="效率",
|
||||
@@ -54,7 +55,7 @@ return {
|
||||
|
||||
win="勝利",
|
||||
lose="失敗",
|
||||
|
||||
torikan="未達標",
|
||||
finish="完成",
|
||||
gamewin="勝利",
|
||||
gameover="遊戲結束",
|
||||
@@ -66,10 +67,13 @@ return {
|
||||
|
||||
page="頁面:",
|
||||
|
||||
ai_puzzle="不能同時開啟AI和拼圖模式",
|
||||
ai_mission="不能同時開啟AI和自定義任務",
|
||||
ai_badPiece="不能同時開啟AI和含有非四連方塊的自定義序列",
|
||||
cc_fixed="不能同時開啟CC和固定序列",
|
||||
cc_swap="不能同時開啟CC和swap的暫存模式",
|
||||
ai_prebag="不能同時開啟AI和含有非四連方塊的自定義序列",
|
||||
ai_mission="不能同時開啟AI和自定義任務",
|
||||
cc_solid="開啟CC時不能存在預先填滿的行",
|
||||
cc_field_too_high="開啓CC時最高出塊高度不能超過40",
|
||||
switchSpawnSFX="請開啟方塊生成音效",
|
||||
needRestart="重新啟動以應用所有更改",
|
||||
|
||||
@@ -91,6 +95,8 @@ return {
|
||||
dataCorrupted="數據損壞",
|
||||
pasteWrongPlace="提醒:可能黏貼錯地方了",
|
||||
noFile="文件未找到",
|
||||
invalidSequence="無效序列模式",
|
||||
tooHighField="超過126行的場地數據已被丟棄",
|
||||
|
||||
nowPlaying="正在播放:",
|
||||
|
||||
@@ -195,7 +201,7 @@ return {
|
||||
|
||||
|
||||
|
||||
keySettingInstruction="點擊來設置鍵位\n按esc來取消選中\n按退格鍵來清除選中",
|
||||
keySettingInstruction="點擊來設定鍵位\n按esc來取消選中\n按退格鍵來清除選中",
|
||||
customBGhelp="把圖片檔案拖到這個視窗裏使用自定義背景",
|
||||
customBGloadFailed="自定義背景的圖片檔案格式不支持",
|
||||
|
||||
@@ -233,7 +239,7 @@ return {
|
||||
"塊數:",
|
||||
"行清除/挖掘:",
|
||||
"攻擊/挖掘攻擊:",
|
||||
"上漲/接收/抵消:",
|
||||
"上漲(接收-抵消):",
|
||||
"清除:",
|
||||
"Spin:",
|
||||
"B2B/B3B/PC/HPC:",
|
||||
@@ -261,7 +267,7 @@ return {
|
||||
"使用LÖVE引擎",
|
||||
"錯誤或者建議請附帶截圖發送到內測群或者作者電郵~",
|
||||
"僅透過內測QQ群/discord伺服器進行免費下載/更新",
|
||||
"從其他渠道獲得遊戲皆有被修改/加入廣告/植入病毒的風險,程序只申請了振動&網路權限!",
|
||||
"從其他渠道獲得遊戲皆有被修改/加入廣告/植入病毒的風險,程式只申請了振動&網路權限!",
|
||||
"若由於被修改的本遊戲產生的各種損失作者概不負責(我怎麼負責啊跟我有什麼關係)",
|
||||
FNNS and "/" or "請從正規途徑獲得最新版,遊戲現為免費,不過有打賞當然感謝啦~",
|
||||
FNNS and "/" or "更多資訊見小z詞典"
|
||||
@@ -270,7 +276,7 @@ return {
|
||||
"原作者 MrZ",
|
||||
"電郵: 1046101471@qq.com",
|
||||
"",
|
||||
"程序, 開發和設計",
|
||||
"程式, 開發和設計",
|
||||
"MrZ",
|
||||
"",
|
||||
"音樂製作使用",
|
||||
@@ -281,7 +287,7 @@ return {
|
||||
"",
|
||||
"[POWERED BY LÖVE]",
|
||||
"",
|
||||
"程序",
|
||||
"程式",
|
||||
"MrZ",
|
||||
"ParticleG",
|
||||
"Gompyn",
|
||||
@@ -327,6 +333,7 @@ return {
|
||||
"Miya",
|
||||
"Xiaoya",
|
||||
"Mono",
|
||||
"Flore",
|
||||
"MrZ",
|
||||
"Trebor",
|
||||
"",
|
||||
@@ -389,7 +396,7 @@ return {
|
||||
qplay="快速開始: ",
|
||||
online="網路遊戲",
|
||||
custom="自定義",
|
||||
setting="設置",
|
||||
setting="設定",
|
||||
stat="統計數據",
|
||||
dict="小Z辭典",
|
||||
replays="錄影回放",
|
||||
@@ -408,7 +415,7 @@ return {
|
||||
unranked="成績無效",
|
||||
},
|
||||
pause={
|
||||
setting="設置(S)",
|
||||
setting="設定(S)",
|
||||
replay="回放(P)",
|
||||
save="保存(O)",
|
||||
resume="繼續(esc)",
|
||||
@@ -460,7 +467,7 @@ return {
|
||||
capacity="房間容量",
|
||||
create="創建",
|
||||
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="100% finesse",
|
||||
b2bKill="強制B2B",
|
||||
lockout="鎖定在外時失敗",
|
||||
@@ -482,14 +489,14 @@ return {
|
||||
cancel="取消準備",
|
||||
},
|
||||
setting_game={
|
||||
title="遊戲設置",
|
||||
title="遊戲設定",
|
||||
graphic="←畫面",
|
||||
sound="音頻→",
|
||||
style="風格",
|
||||
|
||||
ctrl="控制設置",
|
||||
key="鍵位設置",
|
||||
touch="觸控設置",
|
||||
ctrl="控制設定",
|
||||
key="鍵位設定",
|
||||
touch="觸控設定",
|
||||
showVK="顯示虛擬擊鍵",
|
||||
reTime="開局等待時間",
|
||||
RS="旋轉系統",
|
||||
@@ -500,7 +507,7 @@ return {
|
||||
simpMode="簡潔模式",
|
||||
},
|
||||
setting_video={
|
||||
title="畫面設置",
|
||||
title="畫面設定",
|
||||
sound="←音頻",
|
||||
game="遊戲→",
|
||||
|
||||
@@ -543,12 +550,16 @@ return {
|
||||
bg_on="普通背景",
|
||||
bg_off="無背景",
|
||||
bg_custom="應用自定義背景",
|
||||
defaultBG="默認背景",
|
||||
resetDbg="改回默認",
|
||||
lockBG="鎖定背景",
|
||||
noTheme="關閉節日主題",
|
||||
|
||||
blockSatur="方塊飽和",
|
||||
fieldSatur="場地飽和",
|
||||
},
|
||||
setting_sound={
|
||||
title="音頻設置",
|
||||
title="音頻設定",
|
||||
game="←遊戲",
|
||||
graphic="畫面→",
|
||||
|
||||
@@ -568,7 +579,7 @@ return {
|
||||
apply="應用",
|
||||
},
|
||||
setting_control={
|
||||
title="控制設置",
|
||||
title="控制設定",
|
||||
preview="預覽",
|
||||
|
||||
das="DAS",arr="ARR",
|
||||
@@ -605,7 +616,7 @@ return {
|
||||
},
|
||||
setting_skin={
|
||||
skinSet="方塊皮膚",
|
||||
title="外觀設置",
|
||||
title="外觀設定",
|
||||
skinR="重置顏色",
|
||||
faceR="重置方向",
|
||||
},
|
||||
@@ -653,7 +664,7 @@ return {
|
||||
play_puzzle="開始-拼圖",
|
||||
|
||||
reset="重設所有(del)",
|
||||
advance="更多設置(A)",
|
||||
advance="更多設定(A)",
|
||||
mod="Mods (F1)",
|
||||
field="場地編輯(F)",
|
||||
sequence="序列編輯(S)",
|
||||
@@ -677,7 +688,7 @@ return {
|
||||
|
||||
bufferLimit="緩衝上限",
|
||||
heightLimit="高度上限",
|
||||
ospin="O-spin",
|
||||
ospin="TRS O-spin",
|
||||
fineKill="強制finesse",
|
||||
b2bKill="強制B2B",
|
||||
lockout="鎖定在外時失敗",
|
||||
@@ -690,7 +701,7 @@ return {
|
||||
subTitle="場地",
|
||||
|
||||
any="不定",
|
||||
smart="智能",
|
||||
smart="智慧",
|
||||
|
||||
push="增加一行(K)",
|
||||
del="清除行(L)",
|
||||
@@ -761,7 +772,7 @@ return {
|
||||
code="驗證碼",
|
||||
password="密碼",
|
||||
password2="確認密碼",
|
||||
setPW="設置密碼",
|
||||
setPW="設定密碼",
|
||||
},
|
||||
account={
|
||||
title="賬戶",
|
||||
@@ -808,7 +819,7 @@ return {
|
||||
import="從剪貼板導入",
|
||||
unlock="地圖進度",
|
||||
data="統計數據",
|
||||
setting="設置",
|
||||
setting="設定",
|
||||
vk="虛擬按鍵佈局",
|
||||
|
||||
couldSave="雲儲存(測試功能,謹慎使用)",
|
||||
@@ -824,7 +835,9 @@ return {
|
||||
['sprint_100l']= {"競速", "100L", "清除100行"},
|
||||
['sprint_400l']= {"競速", "400L", "清除400行"},
|
||||
['sprint_1000l']= {"競速", "1000L", "清除1000行"},
|
||||
['secret_grade']= {"秘密段位", "", "按照提示完成經典的“大於號”拼圖"},
|
||||
['construct_sg']= {"建設", "秘密段位", "按照提示完成經典的“大於號”拼圖"},
|
||||
-- ['construct_checker']= {"Construct", "CHECKERBOARD", "Build a checkerboard pattern!"},
|
||||
-- ['construct_invsg']= {"Construct", "INV. SG", "Build an inverted zigzag pattern!"},
|
||||
['sprintPenta']= {"競速", "五連塊", "傷腦筋十八塊"},
|
||||
['sprintMPH']= {"競速", "MPH", "純隨機\n無Next\n無Hold"},
|
||||
['sprint123']= {"競速", "M123", "清除40行,但只有一至三連塊"},
|
||||
@@ -857,8 +870,8 @@ return {
|
||||
['round_h']= {"回合制", "困難", "下棋模式"},
|
||||
['round_l']= {"回合制", "瘋狂", "下棋模式"},
|
||||
['round_u']= {"回合制", "極限", "下棋模式"},
|
||||
['big_n']= {"大方塊", "普通", "類比10*5場地的玩法(標準尺寸的一半)"},
|
||||
['big_h']= {"大方塊", "困難", "類比10*5場地的玩法(標準尺寸的一半)"},
|
||||
['big_n']= {"大方塊", "普通", "類比5x10場地(標準尺寸的一半)"},
|
||||
['big_h']= {"大方塊", "困難", "類比5x10場地(標準尺寸的一半)"},
|
||||
['master_n']= {"大師", "普通", "20G初心者練習"},
|
||||
['master_h']= {"大師", "困難", "上級者20G挑戰"},
|
||||
['master_m']= {"大師", "大師", "大師20G"},
|
||||
@@ -911,8 +924,6 @@ return {
|
||||
['tech_l_plus']= {"科研", "瘋狂+", "僅允許spin與PC"},
|
||||
['tech_finesse']= {"科研", "finesse", "強制finesse"},
|
||||
['tech_finesse_f']= {"科研", "finesse+", "禁止普通清除,強制finesse"},
|
||||
['tech_finesse_lock']= {"科研", "finesse限制", "限制操作次數"},
|
||||
['tech_finesse_lock_f']={"科研", "finesse限制+","限制操作次數,禁止斷B2B"},
|
||||
['tsd_e']= {"TSD挑戰", "簡單", "你能連續做幾個TSD?"},
|
||||
['tsd_h']= {"TSD挑戰", "困難", "你能連續做幾個TSD?"},
|
||||
['tsd_u']= {"TSD挑戰", "極限", "你能連續做幾個TSD?"},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Lối chơi:
|
||||
Cách chơi:
|
||||
Hệ thống sẽ cấp cho người chơi 7 loại tetromino (gạch 4 ô) bao gồm: Z, S, J, L, I, O, T;
|
||||
và người chơi cần điều khiển chúng (di chuyển sang trái và phải; xoay 90 / 180 / 270 độ).
|
||||
Cứ mỗi hàng được lấp đầy trong bảng bởi các viên gạch, chúng sẽ bị xóa ra khỏi bảng.
|
||||
@@ -16,7 +16,7 @@ Cách phát hiện spin: bằng cách sử dụng hệ thống điểm.
|
||||
+2 điểm nếu thỏa mãn quy tắc "bất động"
|
||||
+1 điểm nếu chưa kiểm tra vị trí kick thứ hai trong bảng kick
|
||||
|
||||
* Chỉ cần điều kiện 1 hay điều kiện 2 thỏa mãn thì cú xoay đó được tính là Spin *
|
||||
* Chỉ cần thỏa mãn quy tắc "3 góc" hoặc quy tắc "bất động" thì cú xoay đó được tính luôn là Spin *
|
||||
|
||||
— Spin sẽ là Mini nếu xảy ra 1 trong 3 điều kiện sau:
|
||||
Tổng điểm sau khi kiểm tra các quy tắc chỉ được 2 điểm,
|
||||
@@ -25,23 +25,23 @@ Cách phát hiện spin: bằng cách sử dụng hệ thống điểm.
|
||||
|
||||
|
||||
Hệ thống tấn công:
|
||||
Kiểu xóa Đặc biệt (Special clear):
|
||||
Kiểu xóa Đặc biệt chỉ trường hợp bạn thực hiện Spin, Techrash, Techrash+ — xóa 5 hàng hoặc hơn, PC, HPC.
|
||||
Kiểu xóa Đặc biệt có thể sạc đầy thanh B2B.
|
||||
Kiểu xóa nâng cao (Special clear):
|
||||
Kiểu xóa nâng cao chỉ trường hợp bạn thực hiện Spin, Techrash, Techrash+ — xóa 5 hàng hoặc hơn, PC, HPC.
|
||||
Kiểu xóa nâng cao có thể sạc đầy thanh B2B.
|
||||
|
||||
Kiểu xóa Siêu cấp (Super clear):
|
||||
Là Kiểu xóa Đặc biệt nhưng được thực hiện với B2B hoặc B3B
|
||||
Là Kiểu xóa nâng cao nhưng được thực hiện với B2B hoặc B3B
|
||||
|
||||
Kiểu xóa Đặc biệt (spin): Gửi gấp đôi số hàng vừa xóa.
|
||||
Kiểu xóa nâng cao (spin): Gửi gấp đôi số hàng vừa xóa.
|
||||
— B2B gửi thêm 1/1/2/4/8 cho Spin Đơn/Spin Đôi/Spin Tam/Techrash/Techrash+
|
||||
— B2B2B gửi thêm (số hàng xóa × 0.5) trên B2B và +1 hàng để đánh chặn
|
||||
— Mini sẽ bị cắt chỉ còn ¼ so với giá trị ban đầu
|
||||
|
||||
Kiểu xóa Đặc biệt (Techrash/Techrash+ nhưng không spin):
|
||||
Kiểu xóa nâng cao (Techrash/Techrash+ nhưng không spin):
|
||||
— B2B gửi thêm 1 hàng
|
||||
— B3B boost 50% tấn công và +1 hàng để đánh chặn
|
||||
|
||||
Kiểu xóa không Đặc biệt:
|
||||
Kiểu xóa thường:
|
||||
Single/Double/Triple (Đơn/Đôi/Tam) gửi 0/1/2 hàng
|
||||
|
||||
Combo (REN):
|
||||
@@ -49,7 +49,7 @@ Hệ thống tấn công:
|
||||
Hệ số này có giá trị là 25% (hoặc 10% nếu bạn vừa xóa duy nhất 1 hàng) của tổng combo bạn có (tối đa là 12).
|
||||
Lưu ý: Combo chỉ được bắt đầu tính từ lần xóa thứ 2 liên tiếp, không phải lần xóa đầu.
|
||||
|
||||
Hemi Perfect Clear (xem trong Zictionary)
|
||||
Half Perfect Clear (xem trong Zictionary)
|
||||
+4 hàng để tấn công, +2 hàng để đánh chặn
|
||||
|
||||
Perfect Clear (All Clear): Gửi 8 → 16 hàng rác
|
||||
@@ -64,7 +64,7 @@ Thanh Back to Back (B2B):
|
||||
Một người chơi đang ở trang thái B3B khi thanh có hơn 800 điểm.
|
||||
|
||||
Nếu có hàng được xóa:
|
||||
Kiểu xóa đặc biệt:
|
||||
Kiểu xóa nâng cao:
|
||||
— Spin Đơn/Đôi/Tam/Techrash/Techrash+ lần lượt cộng thêm 50/100/180/800/1000 (×50% nếu là Mini)
|
||||
— Techrash +150 điểm, nếu xóa hơn 4 hàng cùng lúc, mỗi hàng từ hàng thứ 5 trở đi cộng thêm 50 điểm.
|
||||
— PC từ thứ 4 trở đi có giá trị 800 điểm
|
||||
@@ -84,7 +84,7 @@ Hệ thống tính điểm:
|
||||
|
||||
Khoảng thời gian chờ trước khi tấn công:
|
||||
Một đòn sát thương sẽ không có hiệu lực ngay lập tức để người chơi có chút thời gian phản ứng trước khi tràn vào bảng.
|
||||
Thời gian chờ của các đòn tấn công như sau, sắp xếp từ nhanh nhất tới lâu nhất:
|
||||
Thời gian chờ của các đòn tấn công như sau, sắp xếp từ nhanh nhất tới lâu nhất:
|
||||
— Double và Triple (Đôi và Tam) là nhanh nhất
|
||||
— Theo sau là Techrash, Techrash+, spin; Mini, B2B và B3B có thêm thêm chút thời gian chờ nữa.
|
||||
— Sát thương từ combo có thời gian chờ lâu nhất..
|
||||
@@ -107,16 +107,24 @@ Chế độ Battle Royale:
|
||||
3. K.O.s: Nhắm vào bot “đang thở máy, đang hấp hối”. Tự động nhắm lại sau mỗi giây.
|
||||
4. Phản công: tấn công tất cả bot đang nhắm vào bạn. Bạn sẽ gửi tấn công đến tất cả bọn chúng.
|
||||
Nếu bạn không nhắm vào mục tiêu nào, thì bạn sẽ tấn công một bot ngẫu nhiên (không nhắm)
|
||||
|
||||
|
||||
Người cuối cùng trụ lại thành công sẽ là người chiến thắng sau khi đã loại được toàn bộ đối thủ.
|
||||
|
||||
|
||||
Chế độ Tự do:
|
||||
Bạn có thể tự do tùy chỉnh nhiều thông số (nhưng không bao gồm các hiệu ứng đặc biệt từ các chế độ khác).
|
||||
Bạn có thể vẽ một cái bảng để tập xóa (Clear mode) hoặc tập xây theo mẫu (Puzzle mode)
|
||||
|
||||
Ở chế độ Puzzle, bạn có thể nhấn F1 để chọn có hiện mẫu hay không. Để thắng được thì toàn bộ…
|
||||
|
||||
Ở chế độ Puzzle, bạn có thể nhấn F1 để chọn có hiện bảng mẫu hay không.
|
||||
Để thắng được game ở chế độ Puzzle thì toàn bộ…
|
||||
ô có X thì không được có gạch;
|
||||
ô trống thì có thể ở bất kỳ tình trạng nào;
|
||||
ô có màu thì gạch đặt vào ô phải khớp màu;
|
||||
ô có màu của hàng rác thì có thể là bất kỳ gạch nào (không phân biệt kiểu gạch) nhưng không thể là không khí.
|
||||
Ở chế độ Clear: bạn chỉ cần xóa sạch toàn bộ gạch của bảng mẫu là được.
|
||||
|
||||
Chế độ Construct:
|
||||
Ở chế độ này, bạn sẽ phải xây theo đúng mẫu: Secret Grade, họa tiết xen kẽ, hoặc Secret Grade đảo ngược
|
||||
Điều kiện để thắng game ở chế độ Construct cũng tương tự như chế độ Puzzle trong chế độ Tự do.
|
||||
|
||||
Nhấn F1 để tắt/bật mẫu, F2 để lật dọc mẫu.
|
||||
215
parts/modes.lua
215
parts/modes.lua
@@ -1,137 +1,138 @@
|
||||
return {
|
||||
{name='sprint_10l', x=0, y=0, size=40,shape=1,icon="sprint1", unlock={'sprint_20l','sprint_40l'}},
|
||||
{name='sprint_20l', x=-200, y=200, size=50,shape=1,icon="sprint1"},
|
||||
{name='sprint_40l', x=0, y=-300, size=40,shape=1,icon="sprint2", unlock={'dig_10l','sprint_100l','marathon_n','sprintPenta','sprintMPH','sprint123','secret_grade'}},
|
||||
{name='sprint_100l', x=-400, y=200, size=50,shape=1,icon="sprint2", unlock={'sprint_400l','drought_n'}},
|
||||
{name='sprint_400l', x=-600, y=200, size=40,shape=1,icon="sprint3", unlock={'sprint_1000l'}},
|
||||
{name='sprint_1000l', x=-800, y=200, size=40,shape=1,icon="sprint3"},
|
||||
{name='sprint_10l', x=0, y=0, size=40,shape=1,icon="sprint1", unlock={'sprint_20l','sprint_40l'}},
|
||||
{name='sprint_20l', x=-200, y=200, size=50,shape=1,icon="sprint1"},
|
||||
{name='sprint_40l', x=0, y=-300, size=40,shape=1,icon="sprint2", unlock={'dig_10l','sprint_100l','marathon_n','sprintPenta','sprintMPH','sprint123'}},
|
||||
{name='sprint_100l', x=-400, y=200, size=50,shape=1,icon="sprint2", unlock={'sprint_400l','drought_n'}},
|
||||
{name='sprint_400l', x=-600, y=200, size=40,shape=1,icon="sprint3", unlock={'sprint_1000l'}},
|
||||
{name='sprint_1000l', x=-800, y=200, size=40,shape=1,icon="sprint3"},
|
||||
|
||||
{name='sprint123', x=160, y=-400, size=40,shape=1,icon="sprint_tri"},
|
||||
{name='sprintMPH', x=200, y=-260, size=40,shape=3,icon="sprint2"},
|
||||
{name='sprintPenta', x=130, y=-140, size=40,shape=3,icon="sprint_pento"},
|
||||
{name='sprint123', x=160, y=-400, size=40,shape=1,icon="sprint_tri"},
|
||||
{name='sprintMPH', x=200, y=-260, size=40,shape=3,icon="sprint2"},
|
||||
{name='sprintPenta', x=130, y=-140, size=40,shape=3,icon="sprint_pento"},
|
||||
|
||||
{name='secret_grade', x=-200, y=-400, size=40,shape=1,icon="secret_grade"},
|
||||
{name='construct_sg', x=-500, y=-520, size=40,shape=1,icon="secret_grade",unlock={'construct_checker'}},
|
||||
{name='construct_checker', x=-700, y=-520, size=40,shape=3,icon="secret_grade",unlock={'construct_invsg'}},
|
||||
{name='construct_invsg', x=-900, y=-520, size=40,shape=2,icon="secret_grade"},
|
||||
|
||||
{name='drought_n', x=-600, y=400, size=40,shape=1,icon="drought", unlock={'drought_l'}},
|
||||
{name='drought_l', x=-800, y=400, size=40,shape=1,icon="drought"},
|
||||
{name='drought_n', x=-600, y=400, size=40,shape=1,icon="drought", unlock={'drought_l'}},
|
||||
{name='drought_l', x=-800, y=400, size=40,shape=1,icon="drought"},
|
||||
|
||||
{name='dig_10l', x=-200, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_40l','dig_eff_10l'}},
|
||||
{name='dig_40l', x=-400, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_100l'}},
|
||||
{name='dig_100l', x=-600, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_400l'}},
|
||||
{name='dig_400l', x=-800, y=-200, size=40,shape=1,icon="dig_sprint"},
|
||||
{name='dig_10l', x=-400, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_40l','dig_eff_10l'}},
|
||||
{name='dig_40l', x=-600, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_100l','dig_quad_10l'}},
|
||||
{name='dig_100l', x=-800, y=-200, size=40,shape=1,icon="dig_sprint", unlock={'dig_400l'}},
|
||||
{name='dig_400l', x=-1000,y=-200, size=40,shape=1,icon="dig_sprint"},
|
||||
|
||||
{name='dig_eff_10l', x=-400, y=0, size=40,shape=1,icon="dig_sprint", unlock={'dig_eff_40l'}},
|
||||
{name='dig_eff_40l', x=-600, y=0, size=40,shape=1,icon="dig_sprint", unlock={'dig_eff_100l'}},
|
||||
{name='dig_eff_100l', x=-800, y=0, size=40,shape=1,icon="dig_sprint", unlock={'dig_eff_400l'}},
|
||||
{name='dig_eff_400l', x=-1000, y=0, size=40,shape=1,icon="dig_sprint"},
|
||||
{name='dig_quad_10l', x=-800, y=-400, size=40,shape=1,icon="drought"},
|
||||
|
||||
{name='marathon_n', x=0, y=-600, size=60,shape=1,icon="marathon", unlock={'marathon_h','solo_e','round_e','big_n','blind_e','classic_e','survivor_e','c4wtrain_n','pctrain_n','sprintAtk','zen'}},
|
||||
{name='marathon_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n','strategy_e'}},
|
||||
{name='dig_eff_10l', x=-600, y=0, size=40,shape=1,icon="dig_eff", unlock={'dig_eff_40l'}},
|
||||
{name='dig_eff_40l', x=-800, y=0, size=40,shape=1,icon="dig_eff", unlock={'dig_eff_100l'}},
|
||||
{name='dig_eff_100l', x=-1000,y=0, size=40,shape=1,icon="dig_eff", unlock={'dig_eff_400l'}},
|
||||
{name='dig_eff_400l', x=-1200,y=0, size=40,shape=1,icon="dig_eff"},
|
||||
|
||||
{name='solo_e', x=-600, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_n'}},
|
||||
{name='solo_n', x=-800, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_h'}},
|
||||
{name='solo_h', x=-1000, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_l','techmino49_e'}},
|
||||
{name='solo_l', x=-1200, y=-1000, size=40,shape=1,icon="solo", unlock={'solo_u'}},
|
||||
{name='solo_u', x=-1400, y=-1000, size=40,shape=1,icon="solo"},
|
||||
{name='marathon_n', x=0, y=-600, size=60,shape=1,icon="marathon", unlock={'marathon_h','solo_e','round_e','big_n','blind_e','classic_e','survivor_e','c4wtrain_n','pctrain_n','sprintAtk','zen','construct_sg'}},
|
||||
{name='marathon_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n','strategy_e'}},
|
||||
|
||||
{name='techmino49_e', x=-1100, y=-1200, size=40,shape=1,icon="t49", unlock={'techmino49_h','techmino99_e'}},
|
||||
{name='techmino49_h', x=-1100, y=-1400, size=40,shape=1,icon="t49", unlock={'techmino49_u'}},
|
||||
{name='techmino49_u', x=-1100, y=-1600, size=40,shape=1,icon="t49"},
|
||||
{name='techmino99_e', x=-1300, y=-1400, size=40,shape=1,icon="t99", unlock={'techmino99_h'}},
|
||||
{name='techmino99_h', x=-1300, y=-1600, size=40,shape=1,icon="t99", unlock={'techmino99_u'}},
|
||||
{name='techmino99_u', x=-1300, y=-1800, size=40,shape=1,icon="t99"},
|
||||
{name='solo_e', x=-600, y=-1000,size=40,shape=1,icon="solo", unlock={'solo_n'}},
|
||||
{name='solo_n', x=-800, y=-1000,size=40,shape=1,icon="solo", unlock={'solo_h'}},
|
||||
{name='solo_h', x=-1000,y=-1000,size=40,shape=1,icon="solo", unlock={'solo_l','techmino49_e'}},
|
||||
{name='solo_l', x=-1200,y=-1000,size=40,shape=1,icon="solo", unlock={'solo_u'}},
|
||||
{name='solo_u', x=-1400,y=-1000,size=40,shape=1,icon="solo"},
|
||||
|
||||
{name='round_e', x=-600, y=-800, size=40,shape=1,icon="round", unlock={'round_n'}},
|
||||
{name='round_n', x=-800, y=-800, size=40,shape=1,icon="round", unlock={'round_h'}},
|
||||
{name='round_h', x=-1000, y=-800, size=40,shape=1,icon="round", unlock={'round_l'}},
|
||||
{name='round_l', x=-1200, y=-800, size=40,shape=1,icon="round", unlock={'round_u'}},
|
||||
{name='round_u', x=-1400, y=-800, size=40,shape=1,icon="round"},
|
||||
{name='techmino49_e', x=-1100,y=-1200,size=40,shape=1,icon="t49", unlock={'techmino49_h','techmino99_e'}},
|
||||
{name='techmino49_h', x=-1100,y=-1400,size=40,shape=1,icon="t49", unlock={'techmino49_u'}},
|
||||
{name='techmino49_u', x=-1100,y=-1600,size=40,shape=1,icon="t49"},
|
||||
{name='techmino99_e', x=-1300,y=-1400,size=40,shape=1,icon="t99", unlock={'techmino99_h'}},
|
||||
{name='techmino99_h', x=-1300,y=-1600,size=40,shape=1,icon="t99", unlock={'techmino99_u'}},
|
||||
{name='techmino99_u', x=-1300,y=-1800,size=40,shape=1,icon="t99"},
|
||||
|
||||
{name='big_n', x=-400, y=-400, size=40,shape=1,icon="big", unlock={'big_h'}},
|
||||
{name='big_h', x=-600, y=-400, size=40,shape=1,icon="big",},
|
||||
{name='round_e', x=-600, y=-800, size=40,shape=1,icon="round", unlock={'round_n'}},
|
||||
{name='round_n', x=-800, y=-800, size=40,shape=1,icon="round", unlock={'round_h'}},
|
||||
{name='round_h', x=-1000,y=-800, size=40,shape=1,icon="round", unlock={'round_l'}},
|
||||
{name='round_l', x=-1200,y=-800, size=40,shape=1,icon="round", unlock={'round_u'}},
|
||||
{name='round_u', x=-1400,y=-800, size=40,shape=1,icon="round"},
|
||||
|
||||
{name='master_n', x=0, y=-1000, size=40,shape=1,icon="master", unlock={'master_h','strategy_h'}},
|
||||
{name='master_h', x=0, y=-1200, size=40,shape=3,icon="master", unlock={'master_final','master_ex','master_ph','master_m','master_g','strategy_u'}},
|
||||
{name='master_m', x=100, y=-1550, size=40,shape=2,icon="master"},
|
||||
{name='master_final', x=-100, y=-1550, size=40,shape=2,icon="master"},
|
||||
{name='master_ph', x=-170, y=-1450, size=40,shape=2,icon="master"},
|
||||
{name='master_g', x=0, y=-1600, size=40,shape=3,icon="master"},
|
||||
{name='master_ex', x=170, y=-1450, size=40,shape=2,icon="master_ex"},
|
||||
{name='big_n', x=-400, y=-400, size=40,shape=1,icon="big", unlock={'big_h'}},
|
||||
{name='big_h', x=-600, y=-400, size=40,shape=1,icon="big"},
|
||||
|
||||
{name='strategy_e', x=-150, y=-1020, size=40,shape=3,icon="master", unlock={'strategy_e_plus'}},
|
||||
{name='strategy_h', x=-150, y=-1150, size=35,shape=3,icon="master", unlock={'strategy_h_plus'}},
|
||||
{name='strategy_u', x=-150, y=-1280, size=30,shape=2,icon="master", unlock={'strategy_u_plus'}},
|
||||
{name='strategy_e_plus', x=-300, y=-1120, size=40,shape=3,icon="master"},
|
||||
{name='strategy_h_plus', x=-300, y=-1250, size=35,shape=3,icon="master"},
|
||||
{name='strategy_u_plus', x=-300, y=-1380, size=30,shape=2,icon="master"},
|
||||
{name='master_n', x=0, y=-1000,size=40,shape=1,icon="master", unlock={'master_h','strategy_h'}},
|
||||
{name='master_h', x=0, y=-1200,size=40,shape=3,icon="master", unlock={'master_final','master_ex','master_ph','master_m','master_g','strategy_u'}},
|
||||
{name='master_m', x=100, y=-1550,size=40,shape=2,icon="master"},
|
||||
{name='master_final', x=-100, y=-1550,size=40,shape=2,icon="master"},
|
||||
{name='master_ph', x=-170, y=-1450,size=40,shape=2,icon="master"},
|
||||
{name='master_g', x=0, y=-1600,size=40,shape=3,icon="master"},
|
||||
{name='master_ex', x=170, y=-1450,size=40,shape=2,icon="master_ex"},
|
||||
|
||||
{name='blind_e', x=150, y=-700, size=40,shape=1,icon="hidden", unlock={'blind_n','master_instinct'}},
|
||||
{name='blind_n', x=150, y=-800, size=40,shape=1,icon="hidden2", unlock={'blind_h'}},
|
||||
{name='blind_h', x=150, y=-900, size=35,shape=1,icon="hidden3", unlock={'blind_l'}},
|
||||
{name='blind_l', x=150, y=-1000, size=35,shape=3,icon="hidden4", unlock={'blind_u'}},
|
||||
{name='blind_u', x=150, y=-1100, size=30,shape=3,icon="hidden4", unlock={'blind_wtf'}},
|
||||
{name='blind_wtf', x=150, y=-1200, size=25,shape=2,icon="hidden5"},
|
||||
{name='master_instinct', x=285, y=-835, size=40,shape=3,icon="hidden2"},
|
||||
{name='strategy_e', x=-150, y=-1020,size=40,shape=3,icon="master", unlock={'strategy_e_plus'}},
|
||||
{name='strategy_h', x=-150, y=-1150,size=35,shape=3,icon="master", unlock={'strategy_h_plus'}},
|
||||
{name='strategy_u', x=-150, y=-1280,size=30,shape=2,icon="master", unlock={'strategy_u_plus'}},
|
||||
{name='strategy_e_plus', x=-300, y=-1120,size=40,shape=3,icon="master"},
|
||||
{name='strategy_h_plus', x=-300, y=-1250,size=35,shape=3,icon="master"},
|
||||
{name='strategy_u_plus', x=-300, y=-1380,size=30,shape=2,icon="master"},
|
||||
|
||||
{name='classic_e', x=-200, y=-850, size=40,shape=1,icon="classic", unlock={'classic_h'}},
|
||||
{name='classic_h', x=-300, y=-950, size=40,shape=3,icon="classic", unlock={'classic_l'}},
|
||||
{name='classic_l', x=-400, y=-1050, size=35,shape=3,icon="classic", unlock={'classic_u'}},
|
||||
{name='classic_u', x=-500, y=-1150, size=30,shape=2,icon="classic"},
|
||||
{name='blind_e', x=150, y=-700, size=40,shape=1,icon="hidden", unlock={'blind_n','master_instinct'}},
|
||||
{name='blind_n', x=150, y=-800, size=40,shape=1,icon="hidden2", unlock={'blind_h'}},
|
||||
{name='blind_h', x=150, y=-900, size=35,shape=1,icon="hidden3", unlock={'blind_l'}},
|
||||
{name='blind_l', x=150, y=-1000,size=35,shape=3,icon="hidden4", unlock={'blind_u'}},
|
||||
{name='blind_u', x=150, y=-1100,size=30,shape=3,icon="hidden4", unlock={'blind_wtf'}},
|
||||
{name='blind_wtf', x=150, y=-1200,size=25,shape=2,icon="hidden5"},
|
||||
{name='master_instinct', x=285, y=-835, size=40,shape=3,icon="hidden2"},
|
||||
|
||||
{name='survivor_e', x=450, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_n'}},
|
||||
{name='survivor_n', x=650, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_h','attacker_h','defender_n','dig_h'}},
|
||||
{name='survivor_h', x=850, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_l'}},
|
||||
{name='survivor_l', x=1050, y=-600, size=40,shape=3,icon="survivor", unlock={'survivor_u'}},
|
||||
{name='survivor_u', x=1250, y=-600, size=40,shape=2,icon="survivor"},
|
||||
{name='classic_e', x=-200, y=-850, size=40,shape=1,icon="classic", unlock={'classic_h'}},
|
||||
{name='classic_h', x=-300, y=-950, size=40,shape=3,icon="classic", unlock={'classic_l'}},
|
||||
{name='classic_l', x=-400, y=-1050,size=35,shape=3,icon="classic", unlock={'classic_u'}},
|
||||
{name='classic_u', x=-500, y=-1150,size=30,shape=2,icon="classic"},
|
||||
|
||||
{name='attacker_h', x=450, y=-800, size=40,shape=1,icon="attack", unlock={'attacker_u'}},
|
||||
{name='attacker_u', x=450, y=-1000, size=40,shape=1,icon="attack"},
|
||||
{name='survivor_e', x=450, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_n'}},
|
||||
{name='survivor_n', x=650, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_h','attacker_h','defender_n','dig_h'}},
|
||||
{name='survivor_h', x=850, y=-600, size=40,shape=1,icon="survivor", unlock={'survivor_l'}},
|
||||
{name='survivor_l', x=1050, y=-600, size=40,shape=3,icon="survivor", unlock={'survivor_u'}},
|
||||
{name='survivor_u', x=1250, y=-600, size=40,shape=2,icon="survivor"},
|
||||
|
||||
{name='defender_n', x=650, y=-800, size=40,shape=1,icon="defend", unlock={'defender_l'}},
|
||||
{name='defender_l', x=650, y=-1000, size=40,shape=1,icon="defend"},
|
||||
{name='attacker_h', x=450, y=-800, size=40,shape=1,icon="attack", unlock={'attacker_u'}},
|
||||
{name='attacker_u', x=450, y=-1000,size=40,shape=1,icon="attack"},
|
||||
|
||||
{name='dig_h', x=850, y=-800, size=40,shape=1,icon="dig", unlock={'dig_u'}},
|
||||
{name='dig_u', x=850, y=-1000, size=40,shape=1,icon="dig"},
|
||||
{name='defender_n', x=650, y=-800, size=40,shape=1,icon="defend", unlock={'defender_l'}},
|
||||
{name='defender_l', x=650, y=-1000,size=40,shape=1,icon="defend"},
|
||||
|
||||
{name='c4wtrain_n', x=700, y=-450, size=40,shape=1,icon="pc", unlock={'c4wtrain_l'}},
|
||||
{name='c4wtrain_l', x=900, y=-450, size=40,shape=1,icon="pc"},
|
||||
{name='dig_h', x=850, y=-800, size=40,shape=1,icon="dig", unlock={'dig_u'}},
|
||||
{name='dig_u', x=850, y=-1000,size=40,shape=1,icon="dig"},
|
||||
|
||||
{name='pctrain_n', x=700, y=-300, size=40,shape=1,icon="pc", unlock={'pctrain_l','pc_n'}},
|
||||
{name='pctrain_l', x=900, y=-300, size=40,shape=1,icon="pc"},
|
||||
{name='c4wtrain_n', x=700, y=-450, size=40,shape=1,icon="pc", unlock={'c4wtrain_l'}},
|
||||
{name='c4wtrain_l', x=900, y=-450, size=40,shape=1,icon="pc"},
|
||||
|
||||
{name='pc_n', x=800, y=-140, size=40,shape=1,icon="pc", unlock={'pc_h'}},
|
||||
{name='pc_h', x=950, y=-140, size=40,shape=3,icon="pc", unlock={'pc_l','pc_inf'}},
|
||||
{name='pc_l', x=1100, y=-140, size=40,shape=3,icon="pc"},
|
||||
{name='pc_inf', x=1100, y=-280, size=40,shape=2,icon="pc"},
|
||||
{name='pctrain_n', x=700, y=-300, size=40,shape=1,icon="pc", unlock={'pctrain_l','pc_n'}},
|
||||
{name='pctrain_l', x=900, y=-300, size=40,shape=1,icon="pc"},
|
||||
|
||||
{name='sprintAtk', x=500, y=-280, size=40,shape=1,icon="sprint2", unlock={'sprintEff','tech_n','tech_finesse','tech_finesse_lock','tsd_e','backfire_n'}},
|
||||
{name='sprintEff', x=360, y=-150, size=40,shape=1,icon="sprint2"},
|
||||
{name='pc_n', x=800, y=-140, size=40,shape=1,icon="pc", unlock={'pc_h'}},
|
||||
{name='pc_h', x=950, y=-140, size=40,shape=3,icon="pc", unlock={'pc_l','pc_inf'}},
|
||||
{name='pc_l', x=1100, y=-140, size=40,shape=3,icon="pc"},
|
||||
{name='pc_inf', x=1100, y=-280, size=40,shape=2,icon="pc"},
|
||||
|
||||
{name='tech_n', x=400, y=20, size=40,shape=1,icon="tech", unlock={'tech_n_plus','tech_h'}},
|
||||
{name='tech_n_plus', x=200, y=-10, size=40,shape=3,icon="tech"},
|
||||
{name='tech_h', x=400, y=170, size=40,shape=1,icon="tech", unlock={'tech_h_plus','tech_l'}},
|
||||
{name='tech_h_plus', x=200, y=140, size=35,shape=3,icon="tech"},
|
||||
{name='tech_l', x=400, y=320, size=40,shape=1,icon="tech", unlock={'tech_l_plus'}},
|
||||
{name='tech_l_plus', x=200, y=290, size=35,shape=3,icon="tech"},
|
||||
{name='sprintAtk', x=500, y=-280, size=40,shape=1,icon="sprint2", unlock={'sprintEff','tech_n','tech_finesse','tsd_e','backfire_n'}},
|
||||
{name='sprintEff', x=360, y=-150, size=40,shape=1,icon="sprint2"},
|
||||
|
||||
{name='tech_finesse', x=850, y=20, size=40,shape=1,icon="tech", unlock={'tech_finesse_f'}},
|
||||
{name='tech_finesse_f', x=1050, y=20, size=40,shape=1,icon="tech"},
|
||||
{name='tech_n', x=400, y=20, size=40,shape=1,icon="tech", unlock={'tech_n_plus','tech_h'}},
|
||||
{name='tech_n_plus', x=200, y=-10, size=40,shape=3,icon="tech_plus"},
|
||||
{name='tech_h', x=400, y=170, size=40,shape=1,icon="tech", unlock={'tech_h_plus','tech_l'}},
|
||||
{name='tech_h_plus', x=200, y=140, size=35,shape=3,icon="tech_plus"},
|
||||
{name='tech_l', x=400, y=320, size=40,shape=1,icon="tech", unlock={'tech_l_plus'}},
|
||||
{name='tech_l_plus', x=200, y=290, size=35,shape=3,icon="tech_plus"},
|
||||
|
||||
{name='tech_finesse_lock', x=850, y=160, size=40,shape=1,icon="tech", unlock={'tech_finesse_lock_f'}},
|
||||
{name='tech_finesse_lock_f', x=1050, y=170, size=40,shape=1,icon="tech"},
|
||||
{name='tech_finesse', x=850, y=20, size=40,shape=1,icon="tech", unlock={'tech_finesse_f'}},
|
||||
{name='tech_finesse_f', x=1050, y=20, size=40,shape=1,icon="tech_plus"},
|
||||
|
||||
{name='tsd_e', x=700, y=250, size=40,shape=1,icon="tsd", unlock={'tsd_h'}},
|
||||
{name='tsd_h', x=860, y=310, size=40,shape=1,icon="tsd", unlock={'tsd_u'}},
|
||||
{name='tsd_u', x=1050, y=320, size=40,shape=1,icon="tsd"},
|
||||
{name='tsd_e', x=700, y=100, size=40,shape=1,icon="tsd", unlock={'tsd_h'}},
|
||||
{name='tsd_h', x=860, y=160, size=40,shape=1,icon="tsd", unlock={'tsd_u'}},
|
||||
{name='tsd_u', x=1050, y=170, size=40,shape=1,icon="tsd"},
|
||||
|
||||
{name='backfire_n', x=640, y=420, size=40,shape=1,icon="backfire", unlock={'backfire_h'}},
|
||||
{name='backfire_h', x=790, y=450, size=40,shape=1,icon="backfire", unlock={'backfire_l'}},
|
||||
{name='backfire_l', x=930, y=450, size=40,shape=3,icon="backfire", unlock={'backfire_u'}},
|
||||
{name='backfire_u', x=1070, y=450, size=35,shape=2,icon="backfire"},
|
||||
{name='backfire_n', x=640, y=270, size=40,shape=1,icon="backfire", unlock={'backfire_h'}},
|
||||
{name='backfire_h', x=790, y=300, size=40,shape=1,icon="backfire", unlock={'backfire_l'}},
|
||||
{name='backfire_l', x=930, y=300, size=40,shape=3,icon="backfire", unlock={'backfire_u'}},
|
||||
{name='backfire_u', x=1070, y=300, size=35,shape=2,icon="backfire"},
|
||||
|
||||
{name='zen', x=-1000, y=-600, size=40,shape=1,icon="zen", unlock={'ultra','infinite','infinite_dig','marathon_inf'}},
|
||||
{name='ultra', x=-1200, y=-600, size=40,shape=1,icon="ultra"},
|
||||
{name='infinite', x=-1200, y=-400, size=40,shape=1,icon='infinite'},
|
||||
{name='infinite_dig', x=-1000, y=-400, size=40,shape=1,icon="dig"},
|
||||
{name='marathon_inf', x=-800, y=-400, size=40,shape=1,icon="marathon"}
|
||||
{name='zen', x=-1200,y=-600, size=40,shape=1,icon="zen", unlock={'ultra','infinite','infinite_dig','marathon_inf'}},
|
||||
{name='ultra', x=-1400,y=-600, size=40,shape=1,icon="ultra"},
|
||||
{name='infinite', x=-1400,y=-400, size=40,shape=1,icon='infinite'},
|
||||
{name='infinite_dig', x=-1200,y=-400, size=40,shape=1,icon="dig"},
|
||||
{name='marathon_inf', x=-1000,y=-400, size=40,shape=1,icon="marathon"},
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ return {
|
||||
getRank=function(P)
|
||||
local W=P.modeData.wave
|
||||
return
|
||||
W>=50 and 5 or
|
||||
W>=40 and 4 or
|
||||
W>=30 and 3 or
|
||||
W>=20 and 2 or
|
||||
W>=10 and 1 or
|
||||
W>=5 and 0
|
||||
W>=50 and 5 or
|
||||
W>=40 and 4 or
|
||||
W>=30 and 3 or
|
||||
W>=20 and 2 or
|
||||
W>=10 and 1 or
|
||||
W>=5 and 0
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ return {
|
||||
getRank=function(P)
|
||||
local W=P.modeData.wave
|
||||
return
|
||||
W>=50 and 5 or
|
||||
W>=40 and 4 or
|
||||
W>=30 and 3 or
|
||||
W>=20 and 2 or
|
||||
W>=10 and 1 or
|
||||
W>=5 and 0
|
||||
W>=50 and 5 or
|
||||
W>=40 and 4 or
|
||||
W>=30 and 3 or
|
||||
W>=20 and 2 or
|
||||
W>=10 and 1 or
|
||||
W>=5 and 0
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ return {
|
||||
if L>=100 then
|
||||
local T=P.stat.time
|
||||
return
|
||||
T<50 and 5 or
|
||||
T<65 and 4 or
|
||||
T<100 and 3 or
|
||||
T<130 and 2 or
|
||||
1
|
||||
T<50 and 5 or
|
||||
T<65 and 4 or
|
||||
T<100 and 3 or
|
||||
T<130 and 2 or
|
||||
1
|
||||
else
|
||||
return
|
||||
L>=50 and 0
|
||||
L>=50 and 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ return {
|
||||
if L>=100 then
|
||||
local T=P.stat.time
|
||||
return
|
||||
T<55 and 5 or
|
||||
T<70 and 4 or
|
||||
T<110 and 3 or
|
||||
T<150 and 2 or
|
||||
1
|
||||
T<55 and 5 or
|
||||
T<70 and 4 or
|
||||
T<110 and 3 or
|
||||
T<150 and 2 or
|
||||
1
|
||||
else
|
||||
return
|
||||
L>=50 and 0
|
||||
L>=50 and 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ return {
|
||||
if L>=100 then
|
||||
local T=P.stat.time
|
||||
return
|
||||
T<45 and 5 or
|
||||
T<60 and 4 or
|
||||
T<90 and 3 or
|
||||
T<120 and 2 or
|
||||
1
|
||||
T<45 and 5 or
|
||||
T<60 and 4 or
|
||||
T<90 and 3 or
|
||||
T<120 and 2 or
|
||||
1
|
||||
else
|
||||
return
|
||||
L>=50 and 0
|
||||
L>=50 and 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ return {
|
||||
if L>=100 then
|
||||
local T=P.stat.time
|
||||
return
|
||||
T<60 and 5 or
|
||||
T<80 and 4 or
|
||||
T<120 and 3 or
|
||||
T<180 and 2 or
|
||||
1
|
||||
T<60 and 5 or
|
||||
T<80 and 4 or
|
||||
T<120 and 3 or
|
||||
T<180 and 2 or
|
||||
1
|
||||
else
|
||||
return
|
||||
L>=50 and 0
|
||||
L>=50 and 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@ return {
|
||||
if L>=200 then
|
||||
local T=P.stat.time
|
||||
return
|
||||
T<=120 and 5 or
|
||||
T<=180 and 4 or
|
||||
3
|
||||
T<=120 and 5 or
|
||||
T<=180 and 4 or
|
||||
3
|
||||
else
|
||||
return
|
||||
L>=100 and 2 or
|
||||
L>=50 and 1 or
|
||||
L>=10 and 0
|
||||
L>=100 and 2 or
|
||||
L>=50 and 1 or
|
||||
L>=10 and 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user