Compare commits

...

42 Commits

Author SHA1 Message Date
SweetSea
c6903c89d9 Merge branch 'main' of https://github.com/26F-Studio/Techmino into mod-patch 2024-11-10 14:48:54 +07:00
Nguyễn Quốc Hưng
271769c502 Merge branch 'main' into mod-patch 2024-06-06 16:41:21 +07:00
Squishy (C6H12O6+NaCl+H2O)
387bbfaf69 Moving changes to #1085 2024-01-21 16:18:28 +07:00
Squishy (C6H12O6+NaCl+H2O)
44ff5e8ee1 Merge branch 'main' of https://github.com/26F-Studio/Techmino into mod-patch 2024-01-21 10:33:03 +07:00
Squishy (C6H12O6+NaCl+H2O)
378d88cff0 Small edit to manual_vi 2024-01-11 09:58:24 +07:00
Squishy (C6H12O6+NaCl+H2O)
58648f7cdb Remove some texts (most deprecated) 2024-01-11 09:56:36 +07:00
Squishy (C6H12O6+NaCl+H2O)
c143e8eee5 Moving part 3 2024-01-11 09:32:57 +07:00
Squishy (C6H12O6+NaCl+H2O)
519687a718 Moving part 2 2024-01-11 09:32:12 +07:00
Squishy (C6H12O6+NaCl+H2O)
d399f3c9d3 Moving part 1 2024-01-11 09:30:08 +07:00
SweetSea-ButImNotSweet
97b1abb5b5 Resolve change request part Tetra 2024-01-09 13:52:55 +07:00
SweetSea-ButImNotSweet
4928f1964c Remove an unused arg 2024-01-08 19:57:05 +07:00
SweetSea-ButImNotSweet
9c47e95d19 Revert the default username from SweetSea to <nil> 2024-01-08 19:52:42 +07:00
SweetSea-ButImNotSweet
c20e4ac845 Add short delay before showing nickname (again) 2024-01-08 19:49:24 +07:00
SweetSea-ButImNotSweet
f2686fb5bd Resolve change requests part 3 2024-01-08 16:34:58 +07:00
SweetSea-ButImNotSweet
888f2f6074 Resolve change requests part 2 2024-01-08 13:37:00 +07:00
SweetSea-ButImNotSweet
536174220d Resolves change requests 2024-01-08 11:33:01 +07:00
SweetSea-ButImNotSweet
dc8488ff61 Clean-up 2024-01-07 19:47:17 +07:00
SweetSea-ButImNotSweet
3cda61b48d Add a short delay before displaying username 2024-01-07 19:41:18 +07:00
SweetSea-ButImNotSweet
d61372c041 Small tweak 2024-01-07 19:29:45 +07:00
Squishy (C6H12O6+NaCl+H2O)
2816a76f5a Fix bugs and small changes to other thing 2024-01-07 18:45:21 +07:00
Squishy (C6H12O6+NaCl+H2O)
65c050f6df Small update for viewLog 2024-01-07 18:43:46 +07:00
Squishy (C6H12O6+NaCl+H2O)
898539cab9 update viewLog 2024-01-07 17:27:07 +07:00
Squishy (C6H12O6+NaCl+H2O)
d09f5b0176 update viewlog 2024-01-07 11:23:54 +07:00
Squishy (C6H12O6+NaCl+H2O)
6594b4a238 Fix viewLog 2024-01-06 23:04:49 +07:00
Squishy (C6H12O6+NaCl+H2O)
70558e82db Add viewLog 2024-01-06 22:54:17 +07:00
Squishy (C6H12O6+NaCl+H2O)
766b32b1b4 Final update 2024-01-06 16:20:55 +07:00
Squishy (C6H12O6+NaCl+H2O)
869135a10c Add English translation 2024-01-06 14:43:50 +07:00
Squishy (C6H12O6+NaCl+H2O)
3825b7ccbf Add VI translation 2024-01-06 12:57:49 +07:00
Squishy (C6H12O6+NaCl+H2O)
68733170a3 Fix mods, update UI 2024-01-06 12:57:39 +07:00
Squishy (C6H12O6+NaCl+H2O)
2cd330ffa6 Modify how executing mods again 2024-01-06 11:21:03 +07:00
Squishy (C6H12O6+NaCl+H2O)
f0a45b8b32 Change most mods' configuration 2024-01-06 11:15:28 +07:00
Squishy (C6H12O6+NaCl+H2O)
4c3abc454a Add TABLE.newWithLockMetamethod() 2024-01-06 11:15:03 +07:00
SweetSea-ButImNotSweet
72d5e46056 Change "modSystem" to "modApplyAt" 2024-01-06 07:18:52 +07:00
SweetSea-ButImNotSweet
c47ddf2900 Merge remote-tracking branch 'upstream/main' into mod-patch 2024-01-05 13:25:10 +07:00
SweetSea-ButImNotSweet
1117b5390c Fix bug (again) 2024-01-04 15:45:09 +07:00
SweetSea-ButImNotSweet
b8ec5df9dc Fix redundant "end" 2024-01-04 15:42:14 +07:00
SweetSea-ButImNotSweet
47fc75bae8 Modify some mods' behavior 2024-01-04 14:45:19 +07:00
Squishy (C6H12O6+NaCl+H2O)
e6f416eee3 Shorten code, remove `unranked` 2024-01-04 10:19:38 +07:00
SweetSea-ButImNotSweet
8252f85720 Fix some bugs 2024-01-04 07:53:28 +07:00
SweetSea-ButImNotSweet
77232885b6 small update 2024-01-03 16:11:39 +07:00
Squishy (C6H12O6+NaCl+H2O)
b3ca43fa69 Final push 2024-01-02 19:02:43 +07:00
Squishy (C6H12O6+NaCl+H2O)
478eb0774f Test 2024-01-01 18:14:37 +07:00
22 changed files with 230 additions and 98 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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={

View File

@@ -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...

View File

@@ -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",
},

View File

@@ -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={

View File

@@ -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={

View File

@@ -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={

View File

@@ -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={

View File

@@ -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={

View File

@@ -159,6 +159,7 @@ return {
mod={
title="?!?!?!",
reset="R (tab)",
applyAt="--:-- >[?!?!?!]",
unranked="X!!!",
},
pause={

View File

@@ -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={

View File

@@ -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的个数",

View File

@@ -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",
},

View File

@@ -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={

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)