Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6903c89d9 | ||
|
|
271769c502 | ||
|
|
387bbfaf69 | ||
|
|
44ff5e8ee1 | ||
|
|
378d88cff0 | ||
|
|
58648f7cdb | ||
|
|
c143e8eee5 | ||
|
|
519687a718 | ||
|
|
d399f3c9d3 | ||
|
|
97b1abb5b5 | ||
|
|
4928f1964c | ||
|
|
9c47e95d19 | ||
|
|
c20e4ac845 | ||
|
|
f2686fb5bd | ||
|
|
888f2f6074 | ||
|
|
536174220d | ||
|
|
dc8488ff61 | ||
|
|
3cda61b48d | ||
|
|
d61372c041 | ||
|
|
2816a76f5a | ||
|
|
65c050f6df | ||
|
|
898539cab9 | ||
|
|
d09f5b0176 | ||
|
|
6594b4a238 | ||
|
|
70558e82db | ||
|
|
766b32b1b4 | ||
|
|
869135a10c | ||
|
|
3825b7ccbf | ||
|
|
68733170a3 | ||
|
|
2cd330ffa6 | ||
|
|
f0a45b8b32 | ||
|
|
4c3abc454a | ||
|
|
72d5e46056 | ||
|
|
c47ddf2900 | ||
|
|
1117b5390c | ||
|
|
b8ec5df9dc | ||
|
|
47fc75bae8 | ||
|
|
e6f416eee3 | ||
|
|
8252f85720 | ||
|
|
77232885b6 | ||
|
|
b3ca43fa69 | ||
|
|
478eb0774f |
@@ -15,6 +15,29 @@ function TABLE.new(val,count)
|
||||
return L
|
||||
end
|
||||
|
||||
-- Get a new empty table with __lock() and __unlock() to protect changes
|
||||
function TABLE.newWithLockMetamethod()
|
||||
local t
|
||||
do
|
||||
local lockedKey={}
|
||||
local realTable={}
|
||||
t=setmetatable( -- This is the fake table, act like a wrapper of realTable
|
||||
{
|
||||
__lock =function(k) if k then lockedKey[k]=true end end,
|
||||
__unlock=function(k)
|
||||
if k then lockedKey[k]=false else TABLE.cut(lockedKey) end
|
||||
end,
|
||||
},{
|
||||
__index =realTable,
|
||||
__newindex=function(_,k,v) if not lockedKey[k] then realTable[k]=v end end,
|
||||
__len =function(_,_,_) return #realTable end,
|
||||
__tostring=function(_,_,_) return tostring(realTable) end,
|
||||
}
|
||||
)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- Get a copy of [1~#] elements
|
||||
function TABLE.shift(org,depth)
|
||||
if not depth then depth=1e99 end
|
||||
|
||||
@@ -314,6 +314,7 @@ do-- function DATA.saveReplay()
|
||||
seed=GAME.seed,
|
||||
setting=GAME.setting,
|
||||
mod=_getModList(),
|
||||
modApplyAt=GAME.modApplyAt,
|
||||
tasUsed=GAME.tasUsed,
|
||||
}
|
||||
if GAME.curMode.savePrivate then
|
||||
@@ -373,6 +374,7 @@ function DATA.parseReplayData(fileName,fileData,ifFull)
|
||||
seed=metaData.seed,
|
||||
setting=metaData.setting,
|
||||
mod=metaData.mod,
|
||||
modApplyAt=metaData.modApplyAt,
|
||||
tasUsed=metaData.tasUsed,
|
||||
}
|
||||
if ifFull then rep.data=fileData end
|
||||
|
||||
@@ -510,10 +510,8 @@ function mergeStat(stat,delta)-- Merge delta stat. to global stat.
|
||||
end
|
||||
end
|
||||
function scoreValid()-- Check if any unranked mods are activated
|
||||
for number,sel in next,GAME.mod do
|
||||
if sel>0 and MODOPT[number].unranked then
|
||||
return false
|
||||
end
|
||||
for _,sel in next,GAME.mod do
|
||||
if sel>0 then return false end
|
||||
end
|
||||
if GAME.playing and GAME.tasUsed then
|
||||
return false
|
||||
@@ -1000,23 +998,28 @@ do-- function dumpBasicConfig()
|
||||
end
|
||||
end
|
||||
do-- function resetGameData(args)
|
||||
local function task_showMods() -- TODO
|
||||
local function task_showMods()
|
||||
coroutine.yield()
|
||||
local counter=0
|
||||
for number,sel in next,GAME.mod do
|
||||
if sel>0 then
|
||||
if counter==0 then
|
||||
coroutine.yield()
|
||||
else
|
||||
|
||||
if usingMod() then
|
||||
SFX.play('collect',.2)
|
||||
TEXT.show(GAME.modApplyAt,640,26,45,'spin')
|
||||
for _=1,90 do coroutine.yield() end
|
||||
|
||||
for number,sel in next,GAME.mod do
|
||||
if sel>0 then
|
||||
for _=1,20 do
|
||||
coroutine.yield()
|
||||
end
|
||||
local M=MODOPT[number]
|
||||
SFX.play('collect',.2)
|
||||
TEXT.show(M.id,640+(counter%5-2)*80,26,45,'spin')
|
||||
counter=counter+1
|
||||
end
|
||||
local M=MODOPT[number]
|
||||
SFX.play('collect',.2)
|
||||
TEXT.show(M.id,640+(counter%5-2)*80,26,45,'spin')
|
||||
counter=counter+1
|
||||
end
|
||||
for _=1,(counter%5)*20+90 do coroutine.yield() end
|
||||
if GAME.playing then PLAYERS[1].showUsername=true end
|
||||
end
|
||||
end
|
||||
local gameSetting={
|
||||
|
||||
@@ -354,144 +354,172 @@ do-- Mod data
|
||||
local function _disableKey(P,key)
|
||||
table.insert(P.gameEnv.keyCancel,key)
|
||||
end
|
||||
local _invisibleTime={
|
||||
['easy'] =300,
|
||||
['slow'] =100,
|
||||
['medium']=60,
|
||||
['fast'] =20,
|
||||
['none'] =0,
|
||||
}
|
||||
local function _lockVfunc(k) do
|
||||
local K=k
|
||||
return function(P,O)
|
||||
P.gameEnv[K]=O or true
|
||||
P.gameEnv.__lock(K)
|
||||
end
|
||||
end end
|
||||
MODOPT={-- Mod options
|
||||
{no=0,id="NX",name="next",
|
||||
key="q",x=80,y=230,color='lO',
|
||||
list={0,1,2,3,4,5,6},
|
||||
func=function(P,O) P.gameEnv.nextCount=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.nextCount=O end,
|
||||
funcOnce =_lockVfunc('nextCount'),
|
||||
},
|
||||
{no=1,id="HL",name="hold",
|
||||
key="w",x=200,y=230,color='lO',
|
||||
list={0,1,2,3,4,5,6},
|
||||
func=function(P,O) P.gameEnv.holdCount=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.holdCount=O end,
|
||||
funcOnce =_lockVfunc('holdCount'),
|
||||
},
|
||||
{no=2,id="FL",name="hideNext",
|
||||
key="e",x=320,y=230,color='lA',
|
||||
list={1,2,3,4,5},
|
||||
func=function(P,O) P.gameEnv.nextStartPos=O+1 end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.nextStartPos=O+1 end,
|
||||
funcOnce =_lockVfunc('nextStartPos'),
|
||||
},
|
||||
{no=3,id="IH",name="infHold",
|
||||
key="r",x=440,y=230,color='lA',
|
||||
func=function(P) P.gameEnv.infHold=true end,
|
||||
unranked=true,
|
||||
funcInit =function(P) P.gameEnv.infHold=true end,
|
||||
funcOnce =_lockVfunc('infHold'),
|
||||
},
|
||||
{no=4,id="HB",name="hideBlock",
|
||||
key="y",x=680,y=230,color='lV',
|
||||
func=function(P) P.gameEnv.block=false end,
|
||||
unranked=true,
|
||||
funcInit =function(P) P.gameEnv.block=false end,
|
||||
funcOnce =_lockVfunc('block'),
|
||||
},
|
||||
{no=5,id="HG",name="hideGhost",
|
||||
key="u",x=800,y=230,color='lV',
|
||||
func=function(P) P.gameEnv.ghost=false end,
|
||||
unranked=true,
|
||||
funcInit =function(P) P.gameEnv.ghost=false end,
|
||||
funcOnce =function(P) P.gameEnv.ghost=false; P.gameEnv.__lock('ghost') end,
|
||||
},
|
||||
{no=6,id="HD",name="hidden",
|
||||
key="i",x=920,y=230,color='lP',
|
||||
list={'easy','slow','medium','fast','none'},
|
||||
func=function(P,O) P.gameEnv.visible=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.visible=O end,
|
||||
funcRepeat=function(P,O)
|
||||
if P.showTime~=_invisibleTime[O] then
|
||||
P:setInvisible(_invisibleTime[O])
|
||||
end
|
||||
end,
|
||||
},
|
||||
{no=7,id="HB",name="hideBoard",
|
||||
key="o",x=1040,y=230,color='lP',
|
||||
list={'down','up','all'},
|
||||
func=function(P,O) P.gameEnv.hideBoard=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.hideBoard=O end,
|
||||
},
|
||||
{no=8,id="FB",name="flipBoard",
|
||||
key="p",x=1160,y=230,color='lJ',
|
||||
list={'U-D','L-R','180'},
|
||||
func=function(P,O) P.gameEnv.flipBoard=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.flipBoard=O end,
|
||||
funcOnce =_lockVfunc('flipBoard'),
|
||||
},
|
||||
|
||||
{no=9,id="DT",name="dropDelay",
|
||||
key="a",x=140,y=350,color='lR',
|
||||
list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
|
||||
func=function(P,O) P.gameEnv.drop=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.drop=O end,
|
||||
funcRepeat=function(P,O)
|
||||
if P.dropDelay~=O then
|
||||
P.gameEnv.drop=O
|
||||
P:set20G(O==0)
|
||||
end
|
||||
end,
|
||||
},
|
||||
{no=10,id="LT",name="lockDelay",
|
||||
key="s",x=260,y=350,color='lR',
|
||||
list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
|
||||
func=function(P,O) P.gameEnv.lock=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.lock=O end,
|
||||
funcRepeat=function(P,O) P.dropDelay=O end,
|
||||
},
|
||||
{no=11,id="ST",name="waitDelay",
|
||||
key="d",x=380,y=350,color='lR',
|
||||
list={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
|
||||
func=function(P,O) P.gameEnv.wait=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.wait=O end,
|
||||
funcOnce =_lockVfunc('waitDelay'),
|
||||
},
|
||||
{no=12,id="CT",name="fallDelay",
|
||||
key="f",x=500,y=350,color='lR',
|
||||
list={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
|
||||
func=function(P,O) P.gameEnv.fall=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.fall=O end,
|
||||
funcOnce =_lockVfunc('fallDelay'),
|
||||
},
|
||||
{no=13,id="LF",name="life",
|
||||
key="j",x=860,y=350,color='lY',
|
||||
list={0,1,2,3,5,10,15,26,42,87,500},
|
||||
func=function(P,O) P.gameEnv.life=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.life=O end,
|
||||
funcOnce =_lockVfunc('life'),
|
||||
},
|
||||
{no=14,id="FB",name="forceB2B",
|
||||
key="k",x=980,y=350,color='lY',
|
||||
func=function(P) P.gameEnv.b2bKill=true end,
|
||||
unranked=true,
|
||||
funcInit =function(P) P.gameEnv.b2bKill=true end,
|
||||
funcOnce =_lockVfunc('b2bKill'),
|
||||
},
|
||||
{no=15,id="PF",name="forceFinesse",
|
||||
key="l",x=1100,y=350,color='lY',
|
||||
func=function(P) P.gameEnv.fineKill=true end,
|
||||
unranked=true,
|
||||
funcInit =function(P) P.gameEnv.fineKill=true end,
|
||||
funcOnce =_lockVfunc('fineKill'),
|
||||
},
|
||||
|
||||
{no=16,id="TL",name="tele",
|
||||
key="z",x=200,y=470,color='lH',
|
||||
func=function(P)
|
||||
funcInit =function(P)
|
||||
P.gameEnv.das,P.gameEnv.arr=0,0
|
||||
P.gameEnv.sddas,P.gameEnv.sdarr=0,0
|
||||
end,
|
||||
unranked=true,
|
||||
funcOnce =function(P)
|
||||
for _,k in pairs{'das','arr','sddas','sdarr'} do
|
||||
P.gameEnv[k]=0
|
||||
P.gameEnv.__lock(k)
|
||||
end
|
||||
end
|
||||
},
|
||||
{no=17,id="FX",name="noRotation",
|
||||
key="x",x=320,y=470,color='lH',
|
||||
func=function(P)
|
||||
funcInit =function(P)
|
||||
_disableKey(P,3)
|
||||
_disableKey(P,4)
|
||||
_disableKey(P,5)
|
||||
end,
|
||||
unranked=true,
|
||||
},
|
||||
{no=18,id="GL",name="noMove",
|
||||
key="c",x=440,y=470,color='lH',
|
||||
func=function(P)
|
||||
_disableKey(P,1)_disableKey(P,2)
|
||||
funcInit =function(P)
|
||||
_disableKey(P,1) _disableKey(P,2)
|
||||
_disableKey(P,11)_disableKey(P,12)
|
||||
_disableKey(P,17)_disableKey(P,18)
|
||||
_disableKey(P,19)_disableKey(P,20)
|
||||
end,
|
||||
unranked=true,
|
||||
},
|
||||
{no=19,id="CS",name="customSeq",
|
||||
key="b",x=680,y=470,color='lB',
|
||||
list={'bag','bagES','his','hisPool','c2','bagP1inf','rnd','mess','reverb'},
|
||||
func=function(P,O) P.gameEnv.sequence=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.sequence=O end,
|
||||
funcOnce =_lockVfunc('sequence'),
|
||||
},
|
||||
{no=20,id="PS",name="pushSpeed",
|
||||
key="n",x=800,y=470,color='lB',
|
||||
list={.5,1,2,3,5,15,1e99},
|
||||
func=function(P,O) P.gameEnv.pushSpeed=O end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.pushSpeed=O end,
|
||||
funcOnce =_lockVfunc('pushSpeed'),
|
||||
},
|
||||
{no=21,id="BN",name="boneBlock",
|
||||
key="m",x=920,y=470,color='lB',
|
||||
list={'on','off'},
|
||||
func=function(P,O) P.gameEnv.bone=O=='on' end,
|
||||
unranked=true,
|
||||
funcInit =function(P,O) P.gameEnv.bone=O=='on' end,
|
||||
funcOnce =function(P,O)
|
||||
P.gameEnv.bone=O=='on'
|
||||
P.gameEnv.__lock('bone')
|
||||
end
|
||||
},
|
||||
}
|
||||
for i=1,#MODOPT do
|
||||
@@ -521,7 +549,9 @@ do-- Game data tables
|
||||
seed=1046101471, -- Game seed
|
||||
curMode=false, -- Current gamemode object
|
||||
initPlayerCount=0, -- Player count when init game
|
||||
modUsed=false,
|
||||
mod=TABLE.new(0,#MODOPT),-- List of loaded mods
|
||||
modApplyAt='postInit', -- Apply mod when? (preInit, postInit, always)
|
||||
modeEnv=false, -- Current gamemode environment
|
||||
setting={}, -- Game settings
|
||||
rep={}, -- Recording list, key,time,key,time...
|
||||
|
||||
@@ -209,6 +209,7 @@ return {
|
||||
tryAnotherBuild="UTF-8 decoding error. If you are using Microsoft Windows, please try to download the build with the different architecture. If you are using the x86 version of Techmino, try downloading the x64 version and vice versa.",
|
||||
|
||||
modInstruction="Choose your modifiers here!\nMods allow you to change the rules in various ways, but they can also crash the game. Feel free to play the game your way!\nNote that scores are not saved when using mods. You can also toggle mods using your keyboard keys (hold Shift to reverse).",
|
||||
modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations.",
|
||||
modInfo={
|
||||
next="NEXT\nOverrides the number of Next pieces displayed.",
|
||||
hold="HOLD\nOverrides the number of Hold pieces displayed.",
|
||||
@@ -449,6 +450,7 @@ C. Gamepad
|
||||
},
|
||||
mod={
|
||||
title="Mods",
|
||||
applyAt="Apply during",
|
||||
reset="Reset (tab)",
|
||||
unranked="Unranked",
|
||||
},
|
||||
|
||||
@@ -208,6 +208,7 @@ return {
|
||||
tryAnotherBuild="[UTF-8 Inválido] Si estás usando Windows, intenta descargar Techmino-win32 o Techmino-win64 (el que no estés usando ahora).",
|
||||
|
||||
modInstruction="¡Elige tus mods!\nLos mods permiten modificar el juego,\npero también es posible que lo crasheen.\nLos scores no se guardan durante el uso de mods.",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={
|
||||
next="NEXT\nSobreescribe el nro. de piezas siguientes a mostrar.",
|
||||
hold="HOLD\nSobreescribe el nro. de piezas en reserva disponibles.",
|
||||
@@ -411,6 +412,7 @@ return {
|
||||
mod={
|
||||
title="Mods",
|
||||
reset="Reinic. (tab)",
|
||||
-- applyAt="Apply during",
|
||||
unranked="Sin rango",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -210,6 +210,7 @@ return {
|
||||
-- tryAnotherBuild="[Invalid UTF-8] If you are on Windows, try downloading Techmino-win32 or Techmino-win64 (different from what you are using now).",
|
||||
|
||||
modInstruction="",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={},-- See lang_en.lua
|
||||
pauseStat={
|
||||
"Temps :",
|
||||
@@ -387,6 +388,7 @@ return {
|
||||
mod={
|
||||
title="Mods",
|
||||
reset="Réinitialiser (tab)",
|
||||
-- applyAt="Apply during",
|
||||
unranked="Unranked",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -209,6 +209,7 @@ return {
|
||||
errorMsg="Techmino mengalami eror dan harus memuat ulang.\nAnda bisa mengirim log eror ke developer.",
|
||||
|
||||
modInstruction="Pilih mod Anda!\nMod memungkinkan Anda untuk mengubah permainan,\ntetapi juga bisa menghancur permainan.\nNilai-nilai tidak akan disimpan saat menggunakan mod.",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={
|
||||
next="BLOK LANJUT\nMengubah jumlah pratinjau blok lanjut yang ditampilkan.",
|
||||
hold="SIMPAN\nMengubah jumlah blok yang bisa disimpan.",
|
||||
@@ -412,6 +413,7 @@ return {
|
||||
mod={
|
||||
title="Mod",
|
||||
reset="Reset (tab)",
|
||||
-- applyAt="Apply during",
|
||||
unranked="Tidak Berperingkat",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -210,6 +210,7 @@ return {
|
||||
tryAnotherBuild="[Invalid UTF-8]使用しているOSがMicrosoft WindowsであればTechmino-win32かTechmino-win64をダウンロードしてください! (現在使用しているソフトは違うバージョンです)",
|
||||
|
||||
modInstruction="Modを選択してください!\nModはゲームルールを変えられますが正常にプレイできなくなる可能性があります\nModを使用した場合、スコアは保存されません",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={
|
||||
next="NEXT\nNEXTの個数を変更します",
|
||||
hold="HOLD\nHOLDの個数を変更します",
|
||||
@@ -456,6 +457,7 @@ C. ゲームパッド
|
||||
mod={
|
||||
title="Mods",
|
||||
reset="リセット (tab)",
|
||||
-- applyAt="Apply during",
|
||||
unranked="記録不可",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -197,6 +197,7 @@ return {
|
||||
-- tryAnotherBuild="[Invalid UTF-8] If you are on Windows, try downloading Techmino-win32 or Techmino-win64 (different from what you are using now).",
|
||||
|
||||
modInstruction="Selecione mods (modificadores) para usar!\nMods irão modificar o jogo em formas diferentes\n(e possivelmente quebrar o jogo de formas estranhas).\nAlguns mods irão fazer seu jogo unranked.",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={
|
||||
next="Próximo\nSobrepõe a largura da fila de próximos",
|
||||
hold="Segure\nSobrepõe a largura da fila de segurar",
|
||||
@@ -400,6 +401,7 @@ return {
|
||||
mod={
|
||||
title="Mods",
|
||||
reset="Reset (tab)",
|
||||
-- applyAt="Apply during",
|
||||
unranked="Unranked",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -159,6 +159,7 @@ return {
|
||||
mod={
|
||||
title="?!?!?!",
|
||||
reset="R (tab)",
|
||||
applyAt="--:-- >[?!?!?!]",
|
||||
unranked="X!!!",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -204,6 +204,7 @@ return {
|
||||
tryAnotherBuild="LOI UTF-8! Neu dang choi Techmino tren Windows: hay doi tu x86 sang x64 va nguoc lai.",
|
||||
|
||||
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.",
|
||||
modApplyAtInstruction="Chọn thời điểm bạn muốn mod được áp dụng.\npreInit: Trước khi nạp game. Đây là tùy chọn mặc định từ phiên bản 0.17.15 trở về trước. Một số mod có thể gặp vấn đề nếu dùng tùy chọn này.\npostInit: Sau khi nạp chế độ chơi, có thể sửa được một số lỗi ở preInit. Tuy nhiên, mod có thể bị mất tác dụng ở một số trường hợp nhất định.\nalways: Luôn áp dụng trong cả game. Tùy chọn này sẽ giúp bạn giữ lại tác dụng của mod dù ở bất kì trường hợp nào.",
|
||||
modInfo={
|
||||
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",
|
||||
@@ -445,6 +446,7 @@ C. Tay cầm chơi game (Gamepad):
|
||||
mod={
|
||||
title="Mods",
|
||||
reset="Đặt lại (tab)",
|
||||
applyAt="Áp dụng mod khi",
|
||||
unranked="Không tính điểm",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -209,6 +209,7 @@ return {
|
||||
tryAnotherBuild="[解码UTF-8错误] 如果你现在用的是Windows系统,请重新下载 Techmino-32/64位 (和现在运行的不一样的那个)。",
|
||||
|
||||
modInstruction="选择你要使用的Mod!\n不同Mod会用不同的方式改变初始游戏规则(可能导致不能正常游玩)\n来开发新玩法或者挑战自我吧!\n提醒:开启一些Mod会让成绩无效,你也可以用键盘开关Mod,按住shift反向",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={
|
||||
next="Next数量:\n强制使用Next的个数",
|
||||
hold="Hold数量:\n强制使用Hold的个数",
|
||||
|
||||
@@ -157,6 +157,8 @@ return {
|
||||
tryAnotherBuild="Error.DecodeUTF8(); //如果你现在用的是Windows系统,请重新下载 Techmino-32/64位 (和现在运行的不一样的那个)。",
|
||||
|
||||
modInstruction="Mod.Instruction();\n/*选择你要使用的Mod\n不同Mod会用不同的方式改变初始游戏规则(可能导致不能正常游玩)\n提醒:开启一些Mod会让成绩无效,你也可以用键盘开关Mod,按住shift反向*/",
|
||||
-- [[[NEED TRANSLATING!]]]
|
||||
modApplyAtInstruction="Mod.ApplyDuring=PLAYERS[1].username=='shoucandanghehe' ? 'preInit' : 'postInit' --[[\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations.]]",
|
||||
modInfo={
|
||||
next="Mod.Next();\n//强制使用Next的个数",
|
||||
hold="Mod.Hold\n//强制使用Hold的个数",
|
||||
@@ -359,6 +361,7 @@ return {
|
||||
},
|
||||
mod={
|
||||
title="GameMod.UI",
|
||||
applyAt="Mod.ApplyDuring=",
|
||||
reset="Mod.Reset();",
|
||||
unranked="unranked=true",
|
||||
},
|
||||
|
||||
@@ -209,6 +209,7 @@ return {
|
||||
tryAnotherBuild="[無效的UTF-8] 如果你使用的是Windows作業系統,請嘗試下載Techmino-win32或Techmino-win64(與你現在使用的不同的版本)。",
|
||||
|
||||
modInstruction="選擇你想使用的Mod!\n不同的Mod會以不同的方式改變遊戲規則(可能導致遊戲異常)\n快來開發新玩法或挑戰自我吧!\n提醒:開啟Mod會使成績無效,你可以使用鍵盤開關Mod,按下shift反向",
|
||||
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||
modInfo={
|
||||
next="Next數量:\n強制使用Next的個數",
|
||||
hold="Hold數量:\n強制使用Hold的個數",
|
||||
@@ -412,6 +413,7 @@ return {
|
||||
mod={
|
||||
title="Mods",
|
||||
reset="重設(tab)",
|
||||
-- applyAt="Apply during",
|
||||
unranked="成績無效",
|
||||
},
|
||||
pause={
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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 độ).
|
||||
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.
|
||||
Nếu có đối thủ, đối thủ sẽ bị tấn công mạnh hoặc nhẹ tùy theo số hàng bạn gửi.
|
||||
Chơi hết hoặc đạt mục tiêu của cấp độ để thắng.
|
||||
@@ -25,19 +25,19 @@ 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 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 Đặ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 Siêu cấp (Super clear):
|
||||
Là Kiểu xóa nâng cao nhưng được thực hiện với B2B hoặc B3B
|
||||
Là Kiểu xóa Đặc biệt nhưng được thực hiện với B2B hoặc B3B
|
||||
|
||||
Kiểu xóa nâng cao (spin): Gửi gấp đôi số hàng vừa xóa.
|
||||
Kiểu xóa Đặc biệt (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 nâng cao (Techrash/Techrash+ nhưng không spin):
|
||||
Kiểu xóa Đặc biệt (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
|
||||
|
||||
@@ -55,7 +55,7 @@ Hệ thống tấn công:
|
||||
Perfect Clear (All Clear): Gửi 8 → 16 hàng rác
|
||||
PC thứ nhất chỉ gửi 8 hàng rác, các PC sau đó sẽ thêm 2 hàng rác để tấn công (tổng hàng rác có thể gửi tối đa là 16 hàng)
|
||||
|
||||
Sau khi tính toán xong, lượng sát thương sẽ bị làm tròn XUỐNG trước khi gửi.
|
||||
Sau khi tính tổng xong, lượng sát thương sẽ bị làm tròn XUỐNG trước khi gửi.
|
||||
|
||||
|
||||
Thanh Back to Back (B2B):
|
||||
@@ -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 nâng cao:
|
||||
Kiểu xóa Đặc biệt:
|
||||
— 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
|
||||
@@ -82,12 +82,13 @@ Hệ thống tính điểm:
|
||||
Việc tính điểm cũng độc lập tùy vào từng chế độ.
|
||||
|
||||
|
||||
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:
|
||||
Khoảng thời gian chờ trước khi gây sát thươ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 chúng có hiệu lực (rác tràn vào bảng).
|
||||
Thời gian chờ của các đòn tấn công như sau, xếp từ ngắn nhất tới dài 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..
|
||||
— Sát thương từ combo có thời gian chờ lâu nhất.
|
||||
|
||||
|
||||
Phản công:
|
||||
|
||||
@@ -787,9 +787,11 @@ function draw.norm(P,repMode)
|
||||
gc_scale(P.size)
|
||||
|
||||
-- Draw username
|
||||
setFont(30)
|
||||
gc_setColor(GROUP_COLORS[P.group])
|
||||
GC.mStr(P.username or USERS.getUsername(P.uid),300,-60)
|
||||
if P.showUsername then
|
||||
setFont(30)
|
||||
gc_setColor(GROUP_COLORS[P.group])
|
||||
GC.mStr(P.username or USERS.getUsername(P.uid),300,-60)
|
||||
end
|
||||
|
||||
-- Draw HUD
|
||||
if ENV.nextCount>0 then _drawNext(P,repMode) end
|
||||
|
||||
@@ -175,8 +175,49 @@ local function _newEmptyPlayer(id,mini)
|
||||
}
|
||||
return P
|
||||
end
|
||||
local function _executeMod(P)
|
||||
local applyStatus=GAME.modApplyAt
|
||||
if applyStatus=='always' then
|
||||
if not GAME.modCodeList then GAME.modCodeList={} end
|
||||
if not GAME.modCodeList[P.id] then GAME.modCodeList[P.id]={} end
|
||||
|
||||
if not GAME.applyModsTask then
|
||||
function GAME.applyModsTask()
|
||||
while GAME.playing do
|
||||
for _,p in pairs(GAME.modCodeList) do
|
||||
for _,c in pairs(p) do pcall(c) end
|
||||
end
|
||||
coroutine.yield()
|
||||
end
|
||||
-- Kill mod patching function when game stopped
|
||||
TASK.removeTask_code(GAME.applyModsTask)
|
||||
TABLE.clear(GAME.modCodeList)
|
||||
GAME.modCodeList=nil
|
||||
GAME.applyModsTask=nil
|
||||
end
|
||||
TASK.new(GAME.applyModsTask)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,#GAME.mod do
|
||||
if GAME.mod[i]>0 then
|
||||
local M=MODOPT[i]
|
||||
if applyStatus=='always' then
|
||||
if M.funcOnce then
|
||||
M.funcOnce(P,M.list and M.list[GAME.mod[i]])
|
||||
elseif M.funcRepeat then
|
||||
table.insert(GAME.modCodeList[P.id],function() M.funcInit(P,M.list and M.list[GAME.mod[i]]) end)
|
||||
else
|
||||
M.funcInit(P,M.list and M.list[GAME.mod[i]])
|
||||
end
|
||||
else -- Already checked pre or post before calling _executeMod()
|
||||
M.funcInit(P,M.list and M.list[GAME.mod[i]])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local function _loadGameEnv(P)-- Load gameEnv
|
||||
P.gameEnv={}-- Current game setting environment
|
||||
P.gameEnv=TABLE.newWithLockMetamethod()-- Current game setting environment
|
||||
local ENV=P.gameEnv
|
||||
local GAME,SETTING=GAME,SETTING
|
||||
-- Load game settings
|
||||
@@ -199,13 +240,9 @@ local function _loadGameEnv(P)-- Load gameEnv
|
||||
ENV[k]=TABLE.copy(v)
|
||||
end
|
||||
end
|
||||
if ENV.allowMod then
|
||||
for i=1,#GAME.mod do
|
||||
if GAME.mod[i]>0 then
|
||||
local M=MODOPT[i]
|
||||
M.func(P,M.list and M.list[GAME.mod[i]])
|
||||
end
|
||||
end
|
||||
|
||||
if ENV.allowMod and GAME.modApplyAt=='preInit' then
|
||||
_executeMod(P)
|
||||
end
|
||||
end
|
||||
local function _loadRemoteEnv(P,confStr)-- Load gameEnv
|
||||
@@ -309,6 +346,10 @@ local function _applyGameEnv(P)-- Finish gameEnv processing
|
||||
break
|
||||
end
|
||||
|
||||
if ENV.allowMod and GAME.modApplyAt~='preInit' then
|
||||
_executeMod(P)
|
||||
end
|
||||
|
||||
P._20G=ENV.drop==0
|
||||
P.dropDelay=ENV.drop
|
||||
P.lockDelay=ENV.lock
|
||||
@@ -389,9 +430,7 @@ local function _applyGameEnv(P)-- Finish gameEnv processing
|
||||
P:newNext()
|
||||
end
|
||||
end
|
||||
for _=1,ENV.trueNextCount do
|
||||
P:newNext()
|
||||
end
|
||||
for _=1,ENV.trueNextCount do P:newNext() end
|
||||
|
||||
if P.miniMode then
|
||||
ENV.lockFX=false
|
||||
@@ -477,6 +516,7 @@ function PLY.newAIPlayer(id,AIdata,mini,p)
|
||||
group=0,
|
||||
} if p then TABLE.coverR(p,pData) end
|
||||
P.username="BOT"..pData.uid
|
||||
P.showUsername=true
|
||||
P.sid=NET.uid_sid[pData.uid] or pData.uid
|
||||
P.group=pData.group
|
||||
if not (P.group%1==0 and P.group>=1 and P.group<=6) then P.group=0 end
|
||||
@@ -510,6 +550,8 @@ function PLY.newPlayer(id,mini,p)
|
||||
|
||||
_loadGameEnv(P)
|
||||
_applyGameEnv(P)
|
||||
|
||||
P.showUsername=not (P.gameEnv.allowMod and usingMod())
|
||||
end
|
||||
--------------------------</Public>--------------------------
|
||||
return PLY
|
||||
return PLY
|
||||
@@ -2915,6 +2915,9 @@ function Player:_die()
|
||||
end
|
||||
end
|
||||
end
|
||||
if GAME.applyModsTask then
|
||||
TABLE.cut(GAME.modCodeList[self.id])
|
||||
end
|
||||
end
|
||||
function Player:update(dt)
|
||||
self.trigFrame=self.trigFrame+dt*60
|
||||
|
||||
@@ -325,5 +325,5 @@ scene.widgetList={
|
||||
WIDGET.newButton{name='back',x=1185,y=60,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
||||
WIDGET.newKey{name='help',x=1170,y=140,w=200,h=60,font=40,fText=CHAR.controller.xboxY.."/[F1]: "..CHAR.icon.help,code=pressKey'f1'},
|
||||
}
|
||||
-- NOTE: The gap between Link-Copy, Zoom is 60*1.5-10=80; the gap between 2 buttons in one group is 60+10=70
|
||||
return scene
|
||||
|
||||
return scene
|
||||
@@ -98,11 +98,11 @@ function scene.draw()
|
||||
local t=M.time*.01-- t range:0~0.1
|
||||
GC.scale(1+3*t)
|
||||
GC.rotate(t)
|
||||
local rad,side
|
||||
if M.unranked then
|
||||
rad,side=45,5
|
||||
else
|
||||
rad=40
|
||||
local rad,side=45,5
|
||||
if GAME.modApplyAt=='always' then
|
||||
if M.funcRepeat then side=nil
|
||||
elseif M.funcOnce then side=8
|
||||
else side=5 end
|
||||
end
|
||||
local color=M.color
|
||||
GC.setColor(color[1],color[2],color[3],5*t)
|
||||
@@ -130,6 +130,9 @@ function scene.draw()
|
||||
if selected then
|
||||
setFont(30)
|
||||
GC.printf(text.modInfo[selected.name],70,540,950)
|
||||
elseif WIDGET.isFocus(scene.widgetList.modApplyAt) then
|
||||
setFont(20)
|
||||
GC.printf(text.modApplyAtInstruction,70,540,950)
|
||||
else
|
||||
setFont(25)
|
||||
GC.printf(text.modInstruction,70,540,950)
|
||||
@@ -137,10 +140,11 @@ function scene.draw()
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newText{name='title', x=80,y=50,font=70,align='L'},
|
||||
WIDGET.newText{name='unranked',x=1200,y=60,color='Y',font=50,align='R'},
|
||||
WIDGET.newButton{name='reset', x=1140,y=540,w=170,h=80,font=25,code=pressKey'tab'},
|
||||
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
||||
WIDGET.newText{name='title', x= 80,y=50,font=70,align='L'},
|
||||
WIDGET.newText{name='unranked', x= 970,y=70,color='Y',font=50,align='R'},
|
||||
WIDGET.newSelector{name='applyAt',x=1100,y=100,w=230,color='Y',font=20,list={'preInit','postInit','always'},disp=function() return GAME.modApplyAt end,code=function(v) GAME.modApplyAt=v end},
|
||||
WIDGET.newButton{name='reset', x=1140,y=540,w=170,h=80,font=25,code=pressKey'tab'},
|
||||
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
||||
}
|
||||
|
||||
return scene
|
||||
|
||||
@@ -48,6 +48,7 @@ local function _playRep(fileName)
|
||||
for _,m in next,rep.mod do
|
||||
GAME.mod[m[1]+1]=m[2]
|
||||
end
|
||||
GAME.modApplyAt=rep.modApplyAt or 'preInit' -- For V0.17.15 and older
|
||||
GAME.rep={}
|
||||
DATA.pumpRecording(rep.data,GAME.rep)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user