From fa4b7790ecd1e56477c0312f5c00c22c6a74a861 Mon Sep 17 00:00:00 2001 From: OLDREDSTONE Date: Mon, 5 Oct 2026 18:55:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=B9=E6=B3=95=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=95=88=E6=9E=9C=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/custommethod.md | 6 +- script/custommethod-data.js | 1771 +++++++++++++++++++++------------ script/custommethod-search.js | 485 +++++---- script/custommethod-search.ts | 520 ++++++---- style/special.css | 92 ++ 5 files changed, 1833 insertions(+), 1041 deletions(-) diff --git a/pages/custommethod.md b/pages/custommethod.md index 0624909..8ea1f50 100644 --- a/pages/custommethod.md +++ b/pages/custommethod.md @@ -97,13 +97,15 @@ +
diff --git a/script/custommethod-data.js b/script/custommethod-data.js index f0fab8e..a1d31c9 100644 --- a/script/custommethod-data.js +++ b/script/custommethod-data.js @@ -1,5 +1,5 @@ -// 由解析腾讯文档“自定义方法表”xlsx 自动生成(方法名/参数/类型/说明,可能有不准确处)。 -// 结构:window.CustomMethodSearchData = { enumTypes, methods:[{name,type,description,parameters:[...]}] } +// 由解析腾讯文档“自定义方法表”xlsx 自动生成(方法名/短描述/说明/参数/类型,可能有不准确处)。 +// 结构:window.CustomMethodSearchData = { enumTypes, methods:[{name,type,shortDescription,description,parameters:[...]}] } // type: custom_method | comment | variable | condition | ink | mod | custom_class | surgery window.CustomMethodSearchData = { "enumTypes": { @@ -37,37 +37,82 @@ window.CustomMethodSearchData = { "InOutBounce" ], "Character": [ - "Boy", - "Girl", - "Cole", - "Logan", "Adog", - "Alt", + "Allison", + "Athlete", "AthletePhysio", "Barista", - "ChocoWheat", + "Beat", + "Bodybuilder", + "Boy", + "BoyRaya", + "BoyTangzhuang", + "Buro", + "Clef", + "Cockatiel", "ColeGuitar", "ColeSynth", "Controller", "DancingCouple", "Edega", + "Farmer", "FarmerAlternate", + "Girl", + "GirlCNY", + "HoodieBoy", "HoodieBoyAlternate", + "HoodieBoyBlue", + "Ian", + "IanBubble", "Janitor", - "Kaleidoscope", - "LuckyBag", + "Lucia", "LuckyBaseball", + "LuckyIce", + "LuckyBag", + "Marija", + "Miner", + "MrsStevendog", + "MrsStevenson", "MrStevendog", + "MrStevenson", + "NicoleCigs", + "NicoleCoffee", "NicoleMints", - "Observer", + "None", + "Oriole", + "Owl", + "Paige", + "Parrot", "Player", + "Politician", "Purritician", - "RaYmondCheung", - "RhythmSecurity", + "Quaver", + "Rin", "Rodney", + "Samurai", + "SamuraiBaseball", "SamuraiBlue", + "SamuraiBoss", "SamuraiBossAlt", - "Tentacle" + "SamuraiGirl", + "SamuraiGreen", + "SamuraiPirate", + "SamuraiYellow", + "Saturday", + "SmokinBarista", + "Tentacle", + "Treble", + "Mark", + "MrStevensonTango", + "MrsStevensonTango", + "Beans", + "BookDiary", + "BookEdega", + "BookEye", + "RhythmJanitor", + "RhythmJanitorReal", + "RhythmNurse", + "RhythmSecurity" ], "createPreset": [ "CustomParticles/HitExplosion", @@ -86,13 +131,25 @@ window.CustomMethodSearchData = { ], "SetBaseballTrajectoryPreset": [ "\"enum TrajectoryString\"" + ], + "level": [ + "Level_BeansHopper_rank", + "Level_Lesmis_rank", + "S", + "NotFinished" + ], + "EventType": [ + "Passive", + "Active", + "Accelerable" ] }, "methods": [ { "name": "create", "type": "comment", - "description": "创建打击粒子 - 在指定的x,y位置创建一个打击粒子效果\n举例:()=>create(CustomParticles/HitExplosion,50,50)", + "shortDescription": "创建打击粒子", + "description": "在指定的x,y位置创建一个打击粒子效果\n举例:()=>create(CustomParticles/HitExplosion,50,50)", "parameters": [ { "name": "preset", @@ -112,7 +169,8 @@ window.CustomMethodSearchData = { { "name": "ChangeCharacter", "type": "custom_method", - "description": "改变轨道角色 - 将指定行原来的角色变更为所指定的 Character 对应的角色。该方法不适用于自定义角色。\n\n已过时,现在可以在编辑器中直接修改了", + "shortDescription": "改变轨道角色", + "description": "将指定行原来的角色变更为所指定的 Character 对应的角色。该方法不适用于自定义角色。\n\n已过时,现在可以在编辑器中直接修改了", "parameters": [ { "name": "Character", @@ -123,9 +181,9 @@ window.CustomMethodSearchData = { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -133,7 +191,8 @@ window.CustomMethodSearchData = { { "name": "ChangeCharacterSmooth", "type": "custom_method", - "description": "平滑版改变轨道角色 - 与 ChangeCharacter 相同,但带有烟雾效果。\n已过时,现在可以在编辑器中直接修改了", + "shortDescription": "平滑版改变轨道角色", + "description": "与 ChangeCharacter 相同,但带有烟雾效果。\n已过时,现在可以在编辑器中直接修改了", "parameters": [ { "name": "Character", @@ -144,9 +203,9 @@ window.CustomMethodSearchData = { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -154,47 +213,56 @@ window.CustomMethodSearchData = { { "name": "DamageHeart", "type": "custom_method", - "description": "增加心脏破裂程度 - 设置轨道心脏视觉上的破损。1.0 出现第一个破损,5.0 出现小鸡。同时会震动轨道\n负数没用。\n不影响统计。", + "shortDescription": "增加心脏破裂程度", + "description": "设置轨道心脏视觉上的破损。1.0 出现第一个破损,5.0 出现小鸡。同时会震动轨道\n负数没用。\n不影响统计。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "Damage", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "HealHeart", "type": "custom_method", - "description": "减少心脏破裂程度 - 与 DamageHeart 相反。", + "shortDescription": "减少心脏破裂程度", + "description": "与 DamageHeart 相反。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "Weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "manualHeartCrack", "type": "variable", - "description": "手动心脏碎裂 - 启用后,所有轨道的心脏不会随着失误碎裂或者被治疗恢复,包括 DamageHeart 和 HealHeart 自定义方法。\n然而,心脏的精灵图仍然可以被下面的 SetHeartMistakes 修改。", + "shortDescription": "手动心脏碎裂", + "description": "启用后,所有轨道的心脏不会随着失误碎裂或者被治疗恢复,包括 DamageHeart 和 HealHeart 自定义方法。\n然而,心脏的精灵图仍然可以被下面的 SetHeartMistakes 修改。", "parameters": [ { "name": "Enabled", @@ -205,15 +273,16 @@ window.CustomMethodSearchData = { { "name": "SetHeartMistakes", "type": "custom_method", - "description": "设置心脏碎裂程度 - 当 manualHeartCrack 为 true 时,会将指定轨道的心脏设定为指定失误数下的碎裂程度。\n心脏在指定失误数下的碎裂程度取决于 missesToCrackHeart", + "shortDescription": "设置心脏碎裂程度", + "description": "当 manualHeartCrack 为 true 时,会将指定轨道的心脏设定为指定失误数下的碎裂程度。\n心脏在指定失误数下的碎裂程度取决于 missesToCrackHeart", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -225,15 +294,16 @@ window.CustomMethodSearchData = { { "name": "SetHeartCracked", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -241,15 +311,16 @@ window.CustomMethodSearchData = { { "name": "SetHeartCrackedLeft", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -257,15 +328,16 @@ window.CustomMethodSearchData = { { "name": "SetHeartCrackedRight", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -273,15 +345,16 @@ window.CustomMethodSearchData = { { "name": "SetHeartUnbeatable", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -289,15 +362,16 @@ window.CustomMethodSearchData = { { "name": "SetHeartPumpkin", "type": "custom_method", - "description": "设置心脏状态 - 设置指定轨道的心脏精灵图。", + "shortDescription": "设置心脏状态", + "description": "设置指定轨道的心脏精灵图。", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -305,15 +379,16 @@ window.CustomMethodSearchData = { { "name": "ResetHeart", "type": "custom_method", - "description": "重置心脏状态 - 在调用以上方法后,调用此方法可以使指定轨道的心脏恢复到默认状态。", + "shortDescription": "重置心脏状态", + "description": "在调用以上方法后,调用此方法可以使指定轨道的心脏恢复到默认状态。", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -321,15 +396,15 @@ window.CustomMethodSearchData = { { "name": "Rand", "type": "custom_method", - "description": "生成随机数 - 生成一个范围在1到Range的随机数。\n例如:i0 = Rand(10)", + "shortDescription": "生成随机数", + "description": "生成一个范围在1到Range的随机数。\n例如:i0 = Rand(10)", "parameters": [ { "name": "Range", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } } ] @@ -337,7 +412,8 @@ window.CustomMethodSearchData = { { "name": "invisibleChars", "type": "variable", - "description": "隐藏角色 - 隐藏所有房间所有轨道的角色,保留轨道的其他部分", + "shortDescription": "隐藏角色", + "description": "隐藏所有房间所有轨道的角色,保留轨道的其他部分", "parameters": [ { "name": "Enabled", @@ -348,7 +424,8 @@ window.CustomMethodSearchData = { { "name": "invisibleHeart", "type": "variable", - "description": "隐藏心脏 - 隐藏所有房间所有轨道的心脏,保留轨道的其他部分", + "shortDescription": "隐藏心脏", + "description": "隐藏所有房间所有轨道的心脏,保留轨道的其他部分", "parameters": [ { "name": "Enabled", @@ -359,15 +436,15 @@ window.CustomMethodSearchData = { { "name": "missesToCrackHeart", "type": "variable", - "description": "设置心脏碎裂失误数 - 设置使心脏碎裂(出现小鸡)需要的失误数。\n对于自定义血条很有用。", + "shortDescription": "设置心脏碎裂失误数", + "description": "设置使心脏碎裂(出现小鸡)需要的失误数。\n对于自定义血条很有用。", "parameters": [ { "name": "Misses", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } } ] @@ -375,93 +452,126 @@ window.CustomMethodSearchData = { { "name": "MistakeOrHeal", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "DamageOrHeal", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "MistakeOrHealP1", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "DamageOrHeal", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "MistakeOrHealP2", "type": "custom_method", - "description": "加减失误数 - 正数会出现失误的红色晕影和声音音效,并且在统计中加上相应的失误次数,影响最后的评分\n负数会出现击中的蓝色晕影和声音音效,并且在统计中扣除相应的失误次数,影响最后的评分,但是不影响过早与过晚打击的次数\n\n不会影响心脏的视觉效果。", + "shortDescription": "加减失误数", + "description": "正数会出现失误的红色晕影和声音音效,并且在统计中加上相应的失误次数,影响最后的评分\n负数会出现击中的蓝色晕影和声音音效,并且在统计中扣除相应的失误次数,影响最后的评分,但是不影响过早与过晚打击的次数\n\n不会影响心脏的视觉效果。", "parameters": [ { "name": "DamageOrHeal", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "MistakeOrHealSilent", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "Weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "MistakeOrHealP1Silent", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "Weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "MistakeOrHealP2Silent", "type": "custom_method", - "description": "加减失误数(静音版) - 像 MistakeOrHeal 动作一样,但是不发出任何声音\n但是还是有晕影,加上 noHitFlashBorder = true 就不会被人发现 ", + "shortDescription": "加减失误数(静音版)", + "description": "像 MistakeOrHeal 动作一样,但是不发出任何声音\n但是还是有晕影,加上 noHitFlashBorder = true 就不会被人发现 ", "parameters": [ { "name": "Weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "Mistake", "type": "custom_method", - "description": "增加失误数 - 单纯增加一次失误数。会有失误时的晕影和音效。", + "shortDescription": "增加失误数", + "description": "单纯增加一次失误数。会有失误时的晕影和音效。", "parameters": [] }, { "name": "MistakeSilent", "type": "custom_method", - "description": "增加失误数(静音版) - 像 Mistake 动作一样,但是不发出任何声音\n但是还是有晕影,加上 noHitFlashBorder = true 就不会被人发现 ", + "shortDescription": "增加失误数(静音版)", + "description": "像 Mistake 动作一样,但是不发出任何声音\n但是还是有晕影,加上 noHitFlashBorder = true 就不会被人发现 ", "parameters": [] }, { "name": "TweenHitMarginMultiplier", "type": "custom_method", - "description": "判定范围倍率插值 - 让判定范围倍率在指定时间内按指定缓速变化到指定的值。\n填 0 似乎没用。\n图中示例为从普通判定(80 ms)变化到 0.1 倍(8 ms),随后变化到 50 倍(4000 ms)", + "shortDescription": "判定范围倍率插值", + "description": "让判定范围倍率在指定时间内按指定缓速变化到指定的值。\n填 0 似乎没用。\n图中示例为从普通判定(80 ms)变化到 0.1 倍(8 ms),随后变化到 50 倍(4000 ms)", "parameters": [ { "name": "NewMultiplier", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "DurationBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -472,64 +582,78 @@ window.CustomMethodSearchData = { { "name": "SetMistakeWeight", "type": "custom_method", - "description": "设置失误权重 - 设置当前轨道的失误权重,默认为1\n\n如果需要让跟自定义方法块同一时间的节拍事件受该方法影响,将 执行时间 设定为 OnPreBar. 同时,如果该方法块处于节拍事件的时间内,你还需要将 排位顺序 设定为 -1,以确保该方法首先生效。", + "shortDescription": "设置失误权重", + "description": "设置当前轨道的失误权重,默认为1\n\n如果需要让跟自定义方法块同一时间的节拍事件受该方法影响,将 执行时间 设定为 OnPreBar. 同时,如果该方法块处于节拍事件的时间内,你还需要将 排位顺序 设定为 -1,以确保该方法首先生效。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "Weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "mistakeWeight", "type": "variable", - "description": "设置失误权重(所有轨道) - 设置所有轨道的失误权重。\n\n如果需要让跟自定义方法块同一时间的节拍事件受该方法影响,将 执行时间 设定为 OnPreBar. 同时,如果该方法块处于节拍事件的时间内,你还需要将 排位顺序 设定为 -1,以确保该方法首先生效。", + "shortDescription": "设置失误权重(所有轨道)", + "description": "设置所有轨道的失误权重。\n\n如果需要让跟自定义方法块同一时间的节拍事件受该方法影响,将 执行时间 设定为 OnPreBar. 同时,如果该方法块处于节拍事件的时间内,你还需要将 排位顺序 设定为 -1,以确保该方法首先生效。", "parameters": [ { "name": "Weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "SetMistakeWeightInstant", "type": "custom_method", - "description": "设置失误权重(立即) - 设置当前轨道的失误权重,默认为1\n\n与 SetMistakeWeight() 不同,此方法会立即应用到指定轨道。", + "shortDescription": "设置失误权重(立即)", + "description": "设置当前轨道的失误权重,默认为1\n\n与 SetMistakeWeight() 不同,此方法会立即应用到指定轨道。", "parameters": [ { "name": "row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "weight", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "RefreshMistakeWeight", "type": "custom_method", - "description": "刷新失误权重 - 刷新所有轨道的失误权重。\n\n也就是说,调用 SetMistakeWeight() 后立即调用本方法,和调用 SetMistakeWeightInstant() 的效果相同", + "shortDescription": "刷新失误权重", + "description": "刷新所有轨道的失误权重。\n\n也就是说,调用 SetMistakeWeight() 后立即调用本方法,和调用 SetMistakeWeightInstant() 的效果相同", "parameters": [] }, { "name": "noHitStrips", "type": "variable", - "description": "隐藏打击条 - 移除按拍时的蓝色条。\n\n\n\n\n\n\n\n\n当然也可以是红色的。", + "shortDescription": "隐藏打击条", + "description": "移除按拍时的蓝色条。\n\n\n\n\n\n\n\n\n当然也可以是红色的。", "parameters": [ { "name": "Enabled", @@ -540,7 +664,8 @@ window.CustomMethodSearchData = { { "name": "noHitParticles", "type": "variable", - "description": "隐藏打击粒子 - 隐藏按拍时的粒子特效", + "shortDescription": "隐藏打击粒子", + "description": "隐藏按拍时的粒子特效", "parameters": [ { "name": "Enabled", @@ -551,15 +676,16 @@ window.CustomMethodSearchData = { { "name": "ToggleRowHitFX", "type": "custom_method", - "description": "设置按拍效果 - 类似于 noHitParticles,但还让心脏不会变白,不过仍会有跳动效果。", + "shortDescription": "设置按拍效果", + "description": "类似于 noHitParticles,但还让心脏不会变白,不过仍会有跳动效果。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -571,7 +697,8 @@ window.CustomMethodSearchData = { { "name": "noHitFlashBorder", "type": "variable", - "description": "隐藏打击边框 - 隐藏按拍、错拍时的蓝色/红色边框", + "shortDescription": "隐藏打击边框", + "description": "隐藏按拍、错拍时的蓝色/红色边框", "parameters": [ { "name": "Enabled", @@ -582,7 +709,8 @@ window.CustomMethodSearchData = { { "name": "noPopHitstrips", "type": "variable", - "description": "隐藏空按打击条 - 隐藏没有拍子时空按产生的蓝色打击条", + "shortDescription": "隐藏空按打击条", + "description": "隐藏没有拍子时空按产生的蓝色打击条", "parameters": [ { "name": "Enabled", @@ -593,12 +721,14 @@ window.CustomMethodSearchData = { { "name": "Hit", "type": "custom_method", - "description": "创建打击边框 - 创建一个完美判定时的打击边框。\n\n\n\n\n\n\n\n\n然而并没有图中的粒子特效(", + "shortDescription": "创建打击边框", + "description": "创建一个完美判定时的打击边框。\n\n\n\n\n\n\n\n\n然而并没有图中的粒子特效(", "parameters": [] }, { "name": "shockwave", "type": "comment", + "shortDescription": "", "description": "", "parameters": [ { @@ -615,18 +745,23 @@ window.CustomMethodSearchData = { { "name": "shockwaveSizeMultiplier", "type": "variable", - "description": "设置心爆大小 - 注释命令。 将心爆的大小设置为所指定的 Value。\n\n例如:()=>shockwave(size,5)", + "shortDescription": "设置心爆大小", + "description": "注释命令。 将心爆的大小设置为所指定的 Value。\n\n例如:()=>shockwave(size,5)", "parameters": [ { "name": "Size", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "shockwaveDistortionMultiplier", "type": "variable", - "description": "设置心爆失真程度 - 注释命令。 将心爆的失真程度设置为所指定的 Value。\n\n例如:()=>shockwave(distortion,50)", + "shortDescription": "设置心爆失真程度", + "description": "注释命令。 将心爆的失真程度设置为所指定的 Value。\n\n例如:()=>shockwave(distortion,50)", "parameters": [ { "name": "Distortion", @@ -637,34 +772,37 @@ window.CustomMethodSearchData = { { "name": "shockwaveDurationMultiplier", "type": "variable", - "description": "设置心爆时长 - 注释命令。将心爆的时长设置为 Value。\n<1>=0.5s,<2>=1.0s,<3>=1.5s 以此类推,这个时间由设置速度动作决定,而非节拍\n注意一个轨道同时只能有一个激活的心爆\n\n例如:()=>shockwave(duration,5) 会创建一个持续 2.5s 的心爆", + "shortDescription": "设置心爆时长", + "description": "注释命令。将心爆的时长设置为 Value。\n<1>=0.5s,<2>=1.0s,<3>=1.5s 以此类推,这个时间由设置速度动作决定,而非节拍\n注意一个轨道同时只能有一个激活的心爆\n\n例如:()=>shockwave(duration,5) 会创建一个持续 2.5s 的心爆", "parameters": [ { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "trueCameraMove", "type": "comment", - "description": "移动真实摄像头 - 移动主题的摄像头, 但和移动房间的摄像头不同。 移动时不会切断画面外的东西, 允许你在保持角色可见的情况下将其移到场外。 它还可以让你在有大型背景的特定主题周围移动。 这些主题包括:列车(昼/夜),地下室, 和医院(昼/夜,包括佩奇的办公室)。\n注意, 其中一些主题在屏幕外盘旋着不可移动的 boss 字样。\n\n此函数不会移动自定义背景,但轨道仍会移动。\n\nX 与 Y 是从默认位置算起的(0,0 = 没有变化),并且以像素为单位,不是百分比。\n\nEase 的枚举内容详见 首页\n\n举例:()=>trueCameraMove(0, 50, 50, 2.5, OutBack)", + "shortDescription": "移动真实摄像头", + "description": "移动主题的摄像头, 但和移动房间的摄像头不同。 移动时不会切断画面外的东西, 允许你在保持角色可见的情况下将其移到场外。 它还可以让你在有大型背景的特定主题周围移动。 这些主题包括:列车(昼/夜),地下室, 和医院(昼/夜,包括佩奇的办公室)。\n注意, 其中一些主题在屏幕外盘旋着不可移动的 boss 字样。\n\n此函数不会移动自定义背景,但轨道仍会移动。\n\nX 与 Y 是从默认位置算起的(0,0 = 没有变化),并且以像素为单位,不是百分比。\n\nEase 的枚举内容详见 首页\n\n举例:()=>trueCameraMove(0, 50, 50, 2.5, OutBack)", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { "name": "Xpx", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -672,14 +810,15 @@ window.CustomMethodSearchData = { "name": "Ypx", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, { "name": "AnimationDuration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Ease", @@ -691,15 +830,16 @@ window.CustomMethodSearchData = { { "name": "roomPeek", "type": "comment", - "description": "room[int RoomID].set_peekWindowMode(bool Enabled) - 窥探房间", + "shortDescription": "room[int RoomID].set_peekWindowMode(bool Enabled)", + "description": "窥探房间", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -711,31 +851,39 @@ window.CustomMethodSearchData = { { "name": "wavyRowsAmplitude", "type": "comment", - "description": "room[int RoomID].wavyRowsAmplitude = float Amplitude - 设置轨道浮动幅度", + "shortDescription": "room[int RoomID].wavyRowsAmplitude = float Amplitude", + "description": "设置轨道浮动幅度", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { "name": "Amplitude", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "wobblyLines", "type": "variable", - "description": "设置轨道弹簧效果 - 让所有单发轨道在按拍后晃一下。\n对细分拍没用。\n\n已过时,现在可以用“设置单发波形”事件直接设置了。", + "shortDescription": "设置轨道弹簧效果", + "description": "让所有单发轨道在按拍后晃一下。\n对细分拍没用。\n\n已过时,现在可以用“设置单发波形”事件直接设置了。", "parameters": [ { "name": "Enabled", @@ -746,15 +894,16 @@ window.CustomMethodSearchData = { { "name": "SetHandToP1", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -766,15 +915,16 @@ window.CustomMethodSearchData = { { "name": "SetHandToP2", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -786,15 +936,16 @@ window.CustomMethodSearchData = { { "name": "SetHandToIan", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -806,15 +957,16 @@ window.CustomMethodSearchData = { { "name": "SetHandToPaige", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -826,15 +978,16 @@ window.CustomMethodSearchData = { { "name": "SetHandToPolitician", "type": "custom_method", - "description": "设置手外观 - 特定房间左手或右手更换为 P1,P2,佩奇或者伊恩\n只是视觉变换,CPU 与玩家 P1 还是 P2 状态不变。并且虽然伊恩和佩奇用的按钮不是普通难度,按钮声音不变。\n与\"分配手\"事件不同。", + "shortDescription": "设置手外观", + "description": "特定房间左手或右手更换为 P1,P2,佩奇或者伊恩\n只是视觉变换,CPU 与玩家 P1 还是 P2 状态不变。并且虽然伊恩和佩奇用的按钮不是普通难度,按钮声音不变。\n与\"分配手\"事件不同。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -846,14 +999,13 @@ window.CustomMethodSearchData = { { "name": "SetShadowRow", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "MimickerRowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -861,8 +1013,6 @@ window.CustomMethodSearchData = { "name": "MimickedRowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -871,14 +1021,13 @@ window.CustomMethodSearchData = { { "name": "UnsetShadowRow", "type": "custom_method", - "description": "模仿轨道 - SetShadowRow 方法允许你第一个(MimickerRowID)指定的轨道(下称模仿轨道)完全复制第二个(MimickedRowID)指定的轨道(下称被模仿轨道)的所有节拍样式,该方法可以实现如保持某房间页的节拍样式的操作。两行的其他事件可以有限制地独立生效。\n\n作用于模仿轨道的 轨道涂色 事件同样会作用于被模仿轨道,该现象无法通过别的方式解决,因而你需要在被模仿轨道上的同样时间点添加一个轨道涂色事件取消涂色来掩盖。\n\n模仿轨道上的节拍只能在该轨道上演奏,但其失误计数默认为0.5(即模仿轨道 + 被模仿轨道的失误计数合计为1)\n\n模仿轨道与被模仿轨道必须是同一种节奏类型。\n\n将执行时间设置为 OnPreBar 可获得最佳效果\n\n轨道的模仿可以通过设置了相同参数的 UnsetShadowRow 事件取消。但要小心,设定好模仿轨道后过快取消可能会不可预见的影响失误权重。", + "shortDescription": "模仿轨道", + "description": "SetShadowRow 方法允许你第一个(MimickerRowID)指定的轨道(下称模仿轨道)完全复制第二个(MimickedRowID)指定的轨道(下称被模仿轨道)的所有节拍样式,该方法可以实现如保持某房间页的节拍样式的操作。两行的其他事件可以有限制地独立生效。\n\n作用于模仿轨道的 轨道涂色 事件同样会作用于被模仿轨道,该现象无法通过别的方式解决,因而你需要在被模仿轨道上的同样时间点添加一个轨道涂色事件取消涂色来掩盖。\n\n模仿轨道上的节拍只能在该轨道上演奏,但其失误计数默认为0.5(即模仿轨道 + 被模仿轨道的失误计数合计为1)\n\n模仿轨道与被模仿轨道必须是同一种节奏类型。\n\n将执行时间设置为 OnPreBar 可获得最佳效果\n\n轨道的模仿可以通过设置了相同参数的 UnsetShadowRow 事件取消。但要小心,设定好模仿轨道后过快取消可能会不可预见的影响失误权重。", "parameters": [ { "name": "MimickerRowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -886,8 +1035,6 @@ window.CustomMethodSearchData = { "name": "MimickedRowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -896,7 +1043,8 @@ window.CustomMethodSearchData = { { "name": "smoothShake", "type": "variable", - "description": "改为平滑震动 - 把屏幕震动改成平滑版本。\n\n注意:似乎仅当执行时间为OnPreBar时生效。\n震动结束后,房间显示的内容可能会错位。\n已过时,r38更新后统一使用“自定义震动”事件来实现", + "shortDescription": "改为平滑震动", + "description": "把屏幕震动改成平滑版本。\n\n注意:似乎仅当执行时间为OnPreBar时生效。\n震动结束后,房间显示的内容可能会错位。\n已过时,r38更新后统一使用“自定义震动”事件来实现", "parameters": [ { "name": "Enabled", @@ -907,7 +1055,8 @@ window.CustomMethodSearchData = { { "name": "rotateShake", "type": "variable", - "description": "改为旋转震动 - 将屏幕震动替换为旋转版本。\n\n震动结束后,房间显示的内容可能会错位。\n已过时,r38更新后统一使用“自定义震动”事件来实现", + "shortDescription": "改为旋转震动", + "description": "将屏幕震动替换为旋转版本。\n\n震动结束后,房间显示的内容可能会错位。\n已过时,r38更新后统一使用“自定义震动”事件来实现", "parameters": [ { "name": "Enabled", @@ -918,15 +1067,16 @@ window.CustomMethodSearchData = { { "name": "SetKaleidoscopeColor", "type": "custom_method", - "description": "设置万花筒颜色 - 更改所指定房间(RoomID)的万花筒特效中所用的两种颜色\n\n颜色数值大于 1 时,新颜色将会比默认特效更亮,当数值足够大时将会开始泛光(也就是万花筒图形周边会溢出一些光)\n\n默认值为:SetKaleidoscopeColor(0,1,0,0.4,0,0.4,1)", + "shortDescription": "设置万花筒颜色", + "description": "更改所指定房间(RoomID)的万花筒特效中所用的两种颜色\n\n颜色数值大于 1 时,新颜色将会比默认特效更亮,当数值足够大时将会开始泛光(也就是万花筒图形周边会溢出一些光)\n\n默认值为:SetKaleidoscopeColor(0,1,0,0.4,0,0.4,1)", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -958,14 +1108,13 @@ window.CustomMethodSearchData = { { "name": "SyncKaleidoscopes", "type": "custom_method", - "description": "同步万花筒特效 - 让目标房间(TargetRoomID) 的万花筒特效与其他房间(OtherRoomID)的万花筒特效连起来。\n该方法不继承 SetKaleidoscopeColor 方法中设定的颜色。", + "shortDescription": "同步万花筒特效", + "description": "让目标房间(TargetRoomID) 的万花筒特效与其他房间(OtherRoomID)的万花筒特效连起来。\n该方法不继承 SetKaleidoscopeColor 方法中设定的颜色。", "parameters": [ { "name": "TargetRoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -973,8 +1122,6 @@ window.CustomMethodSearchData = { "name": "OtherRoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -983,23 +1130,22 @@ window.CustomMethodSearchData = { { "name": "SetKaleidoscopeRepeat", "type": "custom_method", - "description": "设置万花筒重复数 - 更改万花筒在自身上的重复次数。\n\n(默认值为 1,图为 1024)", + "shortDescription": "设置万花筒重复数", + "description": "更改万花筒在自身上的重复次数。\n\n(默认值为 1,图为 1024)", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { "name": "Repeat", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -1008,15 +1154,16 @@ window.CustomMethodSearchData = { { "name": "SetKaleidoscopeOffset", "type": "custom_method", - "description": "设置万花筒偏移 - 更改万花筒的镜像的偏移量。", + "shortDescription": "设置万花筒偏移", + "description": "更改万花筒的镜像的偏移量。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -1025,7 +1172,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseStr", @@ -1036,15 +1186,16 @@ window.CustomMethodSearchData = { { "name": "SetKaleidoscopeRoll", "type": "custom_method", - "description": "设置万花筒旋转方式 - 改变万花筒的镜像的旋转方式。", + "shortDescription": "设置万花筒旋转方式", + "description": "改变万花筒的镜像的旋转方式。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -1053,7 +1204,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseStr", @@ -1064,15 +1218,16 @@ window.CustomMethodSearchData = { { "name": "SetKaleidoscopeSymmetry", "type": "custom_method", - "description": "设置万花筒对称性 - 开关万花筒的对称性。\n默认值为True。", + "shortDescription": "设置万花筒对称性", + "description": "开关万花筒的对称性。\n默认值为True。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -1084,7 +1239,8 @@ window.CustomMethodSearchData = { { "name": "noOneshotShadows", "type": "variable", - "description": "移除单发拍残影 - 移除快于 ~0.83 tick 的单发拍子的残影效果。", + "shortDescription": "移除单发拍残影", + "description": "移除快于 ~0.83 tick 的单发拍子的残影效果。", "parameters": [ { "name": "Enabled", @@ -1095,15 +1251,16 @@ window.CustomMethodSearchData = { { "name": "EnableRowReflections", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } } ] @@ -1111,15 +1268,16 @@ window.CustomMethodSearchData = { { "name": "DisableRowReflections", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } } ] @@ -1127,15 +1285,16 @@ window.CustomMethodSearchData = { { "name": "ToggleRowReflectionRoom", "type": "custom_method", - "description": "设置房间轨道倒影 - 在指定房间中启用/禁用倒影效果,类似于花园主题中的效果,但适用于任何背景。\n其中,RoomID 为 -1 时代表应用到所有房间。", + "shortDescription": "设置房间轨道倒影", + "description": "在指定房间中启用/禁用倒影效果,类似于花园主题中的效果,但适用于任何背景。\n其中,RoomID 为 -1 时代表应用到所有房间。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -1147,15 +1306,16 @@ window.CustomMethodSearchData = { { "name": "ToggleRowReflection", "type": "custom_method", - "description": "设置轨道倒影 - 启用/禁用指定轨道的倒影效果,类似于花园主题中的效果,但适用于任何背景。", + "shortDescription": "设置轨道倒影", + "description": "启用/禁用指定轨道的倒影效果,类似于花园主题中的效果,但适用于任何背景。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -1167,7 +1327,8 @@ window.CustomMethodSearchData = { { "name": "rowReflectionsJumping", "type": "variable", - "description": "轨道跳跃倒影 - 使倒影效果在移动 y 位置时能与角色分离,以当前的 y 位置为起点。", + "shortDescription": "轨道跳跃倒影", + "description": "使倒影效果在移动 y 位置时能与角色分离,以当前的 y 位置为起点。", "parameters": [ { "name": "Enabled", @@ -1178,7 +1339,8 @@ window.CustomMethodSearchData = { { "name": "disableRowChangeWarningFlashes", "type": "variable", - "description": "禁用轨道切换闪烁 - 禁用当某行的操控对象改变(如电脑操控改为玩家操控)时发出的警告式闪烁。\n设置为 false 时恢复闪烁。", + "shortDescription": "禁用轨道切换闪烁", + "description": "禁用当某行的操控对象改变(如电脑操控改为玩家操控)时发出的警告式闪烁。\n设置为 false 时恢复闪烁。", "parameters": [ { "name": "Enabled", @@ -1189,18 +1351,23 @@ window.CustomMethodSearchData = { { "name": "statusSignWidth", "type": "variable", - "description": "设置状态牌宽度 - 将状态指示标识的宽度固定在指定的数值上。", + "shortDescription": "设置状态牌宽度", + "description": "将状态指示标识的宽度固定在指定的数值上。", "parameters": [ { "name": "Width", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "skippableRankScreen", "type": "variable", - "description": "允许跳过评级页 - 设定等级结果页是否可快速跳过\n\n- 如果设定值为 true, 则等级显示与默认情况一致(如果玩家在第一个结束事件后按下空格键,则执行下一个结束事件。时间线上的结束事件也会正常运行。)\n- 如果设定值为 false, 则玩家不可以在等级页按空格跳过。此时需要第四个结束事件才能完成整个关卡。\n- 在右侧的示例图里你可以看到西班牙语的 \"你的等级\" 文字以及击中条幅,这说明玩家已经按下了空格,但是等级页并没有跳出等级字母。", + "shortDescription": "允许跳过评级页", + "description": "设定等级结果页是否可快速跳过\n\n- 如果设定值为 true, 则等级显示与默认情况一致(如果玩家在第一个结束事件后按下空格键,则执行下一个结束事件。时间线上的结束事件也会正常运行。)\n- 如果设定值为 false, 则玩家不可以在等级页按空格跳过。此时需要第四个结束事件才能完成整个关卡。\n- 在右侧的示例图里你可以看到西班牙语的 \"你的等级\" 文字以及击中条幅,这说明玩家已经按下了空格,但是等级页并没有跳出等级字母。", "parameters": [ { "name": "Enabled", @@ -1211,7 +1378,8 @@ window.CustomMethodSearchData = { { "name": "skipRankText", "type": "variable", - "description": "移除评级文字 - Enabled为True时,将不会展示评级页面,对于自定义评级页面,或者直接跳过评级页面很有用。仍旧需要\"结束关卡\"事件来完成这个关卡。\n仍然会将结果保存至存档文件。", + "shortDescription": "移除评级文字", + "description": "Enabled为True时,将不会展示评级页面,对于自定义评级页面,或者直接跳过评级页面很有用。仍旧需要\"结束关卡\"事件来完成这个关卡。\n仍然会将结果保存至存档文件。", "parameters": [ { "name": "Enabled", @@ -1222,7 +1390,8 @@ window.CustomMethodSearchData = { { "name": "alternativeMatrix", "type": "variable", - "description": "替换矩阵特效 - 生成一个 Muse Dash 联动关卡中出现的粉色矩阵,仅可替换预设特效中的矩阵。\n需要与预设特效事件处于同一小节,且比预设特效事件先执行才可生效", + "shortDescription": "替换矩阵特效", + "description": "生成一个 Muse Dash 联动关卡中出现的粉色矩阵,仅可替换预设特效中的矩阵。\n需要与预设特效事件处于同一小节,且比预设特效事件先执行才可生效", "parameters": [ { "name": "Enabled", @@ -1233,24 +1402,25 @@ window.CustomMethodSearchData = { { "name": "ToggleSingleRowReflections", "type": "custom_method", - "description": "开关指定轨道倒影 - 开关特定房间内特定轨道的倒影效果。", + "shortDescription": "开关指定轨道倒影", + "description": "开关特定房间内特定轨道的倒影效果。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -1262,37 +1432,52 @@ window.CustomMethodSearchData = { { "name": "CurrentSongVol", "type": "custom_method", - "description": "设置当前音乐音量 - 让当前播放的音乐在指定的淡出时间(fadeTimeSeconds)里逐步变化到所指定的音量大小(targetVolume)。\n请注意:targetVolume = 1 即为音量 100%,音量设为 0 后该音乐将停止,且不能再次提高音量。", + "shortDescription": "设置当前音乐音量", + "description": "让当前播放的音乐在指定的淡出时间(fadeTimeSeconds)里逐步变化到所指定的音量大小(targetVolume)。\n请注意:targetVolume = 1 即为音量 100%,音量设为 0 后该音乐将停止,且不能再次提高音量。", "parameters": [ { "name": "TargetVolume", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "FadeTimeSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "PreviousSongVol", "type": "custom_method", - "description": "设置前一音乐音量 - 让前一首播放的音乐在指定的淡出时间(fadeTimeSeconds)里逐步变化到所指定的音量大小(targetVolume)。\n请注意:targetVolume = 1 即为音量 100%,音量设为 0 后该音乐将停止,且不能再次提高音量。", + "shortDescription": "设置前一音乐音量", + "description": "让前一首播放的音乐在指定的淡出时间(fadeTimeSeconds)里逐步变化到所指定的音量大小(targetVolume)。\n请注意:targetVolume = 1 即为音量 100%,音量设为 0 后该音乐将停止,且不能再次提高音量。", "parameters": [ { "name": "TargetVolume", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "FadeTimeSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "SongVol", "type": "custom_method", - "description": "设置音乐音量 - 让指定文件名的音乐在指定的淡出时间(fadeTimeSeconds)里逐步变化到所指定的音量大小(targetVolume)。\n请注意:targetVolume = 1 即为音量 100%,音量设为 0 后该音乐将停止,且不能再次提高音量。", + "shortDescription": "设置音乐音量", + "description": "让指定文件名的音乐在指定的淡出时间(fadeTimeSeconds)里逐步变化到所指定的音量大小(targetVolume)。\n请注意:targetVolume = 1 即为音量 100%,音量设为 0 后该音乐将停止,且不能再次提高音量。", "parameters": [ { "name": "filename", @@ -1300,50 +1485,60 @@ window.CustomMethodSearchData = { }, { "name": "targetVolume", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "fadeTimeSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "StopEverything", "type": "custom_method", - "description": "全部停止 - 停止所有音乐,节拍,音效等,就像boss关失败了一样。\n注意,调用此方法后处于相同时间的事件可能不会正常执行,一个比较简单的解决方案就是把调用这个方法的自定义方法事件往后挪一点。\n例如:在某小节的第 6 拍同时存在一个“设置播放方式”事件和一个调用该方法的“调用自定义方法”事件,设置播放方式事件可以跳转到某个“关卡失败”小节,为了确保该事件正常运行,可以把调用自定义方法事件放到 6.05 拍的位置(除非BPM太高)", + "shortDescription": "全部停止", + "description": "停止所有音乐,节拍,音效等,就像boss关失败了一样。\n注意,调用此方法后处于相同时间的事件可能不会正常执行,一个比较简单的解决方案就是把调用这个方法的自定义方法事件往后挪一点。\n例如:在某小节的第 6 拍同时存在一个“设置播放方式”事件和一个调用该方法的“调用自定义方法”事件,设置播放方式事件可以跳转到某个“关卡失败”小节,为了确保该事件正常运行,可以把调用自定义方法事件放到 6.05 拍的位置(除非BPM太高)", "parameters": [] }, { "name": "StopAllBeats", "type": "custom_method", - "description": "停止节拍 - 清除所有当前的节拍,同时停止所有声音事件,包括护士语音。", + "shortDescription": "停止节拍", + "description": "清除所有当前的节拍,同时停止所有声音事件,包括护士语音。", "parameters": [] }, { "name": "StopDialogue", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "StopDialogueInstantly", "type": "custom_method", - "description": "停止对话 - 关闭所有的对话框。\n调用 StopDialogueInstantly 会跳过对话框的关闭动画。", + "shortDescription": "停止对话", + "description": "关闭所有的对话框。\n调用 StopDialogueInstantly 会跳过对话框的关闭动画。", "parameters": [] }, { "name": "StopSong", "type": "custom_method", - "description": "停止音乐 - 类似于\"CurrentSongVol\",但没有音量控制,让当前播放的音乐在指定的淡出时间(fadeTimeSeconds)里逐渐停止。", + "shortDescription": "停止音乐", + "description": "类似于\"CurrentSongVol\",但没有音量控制,让当前播放的音乐在指定的淡出时间(fadeTimeSeconds)里逐渐停止。", "parameters": [ { "name": "FadeTimeInSeconds", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } } ] @@ -1351,7 +1546,8 @@ window.CustomMethodSearchData = { { "name": "OneSongAtATime", "type": "custom_method", - "description": "限制单一音乐 - Enabled 为 True 时,当另一个\"播放音乐\"事件触发,前一个播放的音乐会停止。", + "shortDescription": "限制单一音乐", + "description": "Enabled 为 True 时,当另一个\"播放音乐\"事件触发,前一个播放的音乐会停止。", "parameters": [ { "name": "Enabled", @@ -1362,20 +1558,22 @@ window.CustomMethodSearchData = { { "name": "SetUpFlashMarginFeedback", "type": "custom_method", - "description": "初始化判定文字 - 按拍时自动显示\"完美\"\"太快\"\"太慢\"文字。使用 MarginFlashFeedback 前需先调用本方法。\n注意:对于\"RowType\",似乎任何值都有效,当设置为 0 时,如果你在七拍轨道上完全失误太多次后会显示\"在第七拍按键\"。", + "shortDescription": "初始化判定文字", + "description": "按拍时自动显示\"完美\"\"太快\"\"太慢\"文字。使用 MarginFlashFeedback 前需先调用本方法。\n注意:对于\"RowType\",似乎任何值都有效,当设置为 0 时,如果你在七拍轨道上完全失误太多次后会显示\"在第七拍按键\"。", "parameters": [ { "name": "RowType", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, { "name": "LengthInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "FlashScreen", @@ -1386,7 +1584,8 @@ window.CustomMethodSearchData = { { "name": "MarginFlashFeedback", "type": "custom_method", - "description": "开关判定文字 - 开启/关闭\"SetUpFlashMarginFeedback\"的效果。\"KeepCompleteMiss\"为 True 时,如果彻底错过一个拍子,\"太慢\"和\"在第七拍按键\"文字会留在屏幕上。", + "shortDescription": "开关判定文字", + "description": "开启/关闭\"SetUpFlashMarginFeedback\"的效果。\"KeepCompleteMiss\"为 True 时,如果彻底错过一个拍子,\"太慢\"和\"在第七拍按键\"文字会留在屏幕上。", "parameters": [ { "name": "Enabled", @@ -1401,7 +1600,8 @@ window.CustomMethodSearchData = { { "name": "playerDrives7thBeat", "type": "variable", - "description": "玩家自由按拍 - 七拍子会停在第六拍的位置,直到玩家按键,就像 3-X 中一样。启用后玩家将不会在七拍上失误。", + "shortDescription": "玩家自由按拍", + "description": "七拍子会停在第六拍的位置,直到玩家按键,就像 3-X 中一样。启用后玩家将不会在七拍上失误。", "parameters": [ { "name": "Enabled", @@ -1412,23 +1612,22 @@ window.CustomMethodSearchData = { { "name": "SetClumsyRow", "type": "custom_method", - "description": "设置 CPU 失误 - 让指定轨道上 CPU 控制的拍子失误,\n对于 Clumsiness,\n-2 为太快判定的失误效果,-1 为稍快的失误效果\n2 为太慢判定的失误效果,1 为稍慢判定的失误效果\n不影响玩家的失误数。", + "shortDescription": "设置 CPU 失误", + "description": "让指定轨道上 CPU 控制的拍子失误,\n对于 Clumsiness,\n-2 为太快判定的失误效果,-1 为稍快的失误效果\n2 为太慢判定的失误效果,1 为稍慢判定的失误效果\n不影响玩家的失误数。", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "Clumsiness", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -1437,7 +1636,8 @@ window.CustomMethodSearchData = { { "name": "activeDialogues", "type": "variable", - "description": "激活对话按键并等待 - 触发对话时,需要玩家按键才能进入下一行对话,游戏将在当前小节暂停,并等待对话结束后再进入下一小节,等待时长不足一小节则等待至刚好一小节结束,既对话结束后节拍与音乐仍然同步。", + "shortDescription": "激活对话按键并等待", + "description": "触发对话时,需要玩家按键才能进入下一行对话,游戏将在当前小节暂停,并等待对话结束后再进入下一小节,等待时长不足一小节则等待至刚好一小节结束,既对话结束后节拍与音乐仍然同步。", "parameters": [ { "name": "Enabled", @@ -1448,7 +1648,8 @@ window.CustomMethodSearchData = { { "name": "activeDialoguesImmediately", "type": "variable", - "description": "激活对话按键并立即跳转 - 与 \"activeDialogues\" 类似,但在对话结束时(通常在下一个节拍)尽快跳到下一个小节,会导致音乐与节拍不同步。", + "shortDescription": "激活对话按键并立即跳转", + "description": "与 \"activeDialogues\" 类似,但在对话结束时(通常在下一个节拍)尽快跳到下一个小节,会导致音乐与节拍不同步。", "parameters": [ { "name": "Enabled", @@ -1459,15 +1660,16 @@ window.CustomMethodSearchData = { { "name": "SetDialogueRoom", "type": "custom_method", - "description": "设置对话框房间 - 更改对话框的显示位置并将其定位到指定的房间。\n\n注意:更改回 \"顶部\" 几乎不可能。\n对话框不会缩放或旋转,并且永远不会出现在屏幕外。", + "shortDescription": "设置对话框房间", + "description": "更改对话框的显示位置并将其定位到指定的房间。\n\n注意:更改回 \"顶部\" 几乎不可能。\n对话框不会缩放或旋转,并且永远不会出现在屏幕外。", "parameters": [ { "name": "Room", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } } ] @@ -1475,14 +1677,13 @@ window.CustomMethodSearchData = { { "name": "SetDialogueAnchor", "type": "custom_method", - "description": "设置对话框位置 - 就像\"显示对话\"事件中更改对话框在屏幕顶部或底部的位置,但会立即将当前对话框切换到该位置,而无需新事件。\n可以与 SetDialogueRoom 结合使用。\n其中,\n0:底部\n1:顶部", + "shortDescription": "设置对话框位置", + "description": "就像\"显示对话\"事件中更改对话框在屏幕顶部或底部的位置,但会立即将当前对话框切换到该位置,而无需新事件。\n可以与 SetDialogueRoom 结合使用。\n其中,\n0:底部\n1:顶部", "parameters": [ { "name": "Anchor", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -1491,7 +1692,8 @@ window.CustomMethodSearchData = { { "name": "noBananaBeats", "type": "variable", - "description": "移除香蕉拍 - 禁用摇摆拍的倾斜外观。", + "shortDescription": "移除香蕉拍", + "description": "禁用摇摆拍的倾斜外观。", "parameters": [ { "name": "Enabled", @@ -1502,33 +1704,38 @@ window.CustomMethodSearchData = { { "name": "TweenRowPulseBend", "type": "custom_method", - "description": "脉冲倾斜插值 - 将指定脉冲在指定时间内倾斜到指定方向。", + "shortDescription": "脉冲倾斜插值", + "description": "将指定脉冲在指定时间内倾斜到指定方向。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "Pulse", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, { "name": "BendAmount", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -1539,7 +1746,8 @@ window.CustomMethodSearchData = { { "name": "bombBeats", "type": "variable", - "description": "启用地雷拍 - 启用后,当玩家按下特定拍子时将计算为失误,可用于防止玩家乱糊跳过拍。\n使用方法:添加一个七拍轨道,在其上放置一个七拍子,并分割为自由拍,删掉后面的拍子,保留起始拍子(看起来较长的那个拍子),将起始拍子改为第七拍,把这个拍子放在跳过拍按拍的时候,既对齐打叉的黄色标记位置。\n\n注:可以使用手术将上文的地雷拍挪到二拍轨道,这样就不需要单独一条七拍轨道了,并且按下地雷拍时二拍轨道还会出现一个红色的X,就像原版关卡那样。\n用文本编辑器打开你的关卡文件(*.rdlevel),找一找这样的东西:\n{ \"bar\": 1, \"beat\": 5, \"y\": 1, \"type\": \"AddFreeTimeBeat\", \"row\": 0, \"hold\": 0, \"pulse\": 6 },\n其中,\"bar\"是选中事件时左上角现实的小节数,\"beat\"是节拍数,\"row\"代表该事件所属轨道,根据编辑器", + "shortDescription": "启用地雷拍", + "description": "启用后,当玩家按下特定拍子时将计算为失误,可用于防止玩家乱糊跳过拍。\n使用方法:添加一个七拍轨道,在其上放置一个七拍子,并分割为自由拍,删掉后面的拍子,保留起始拍子(看起来较长的那个拍子),将起始拍子改为第七拍,把这个拍子放在跳过拍按拍的时候,既对齐打叉的黄色标记位置。\n\n注:可以使用手术将上文的地雷拍挪到二拍轨道,这样就不需要单独一条七拍轨道了,并且按下地雷拍时二拍轨道还会出现一个红色的X,就像原版关卡那样。\n用文本编辑器打开你的关卡文件(*.rdlevel),找一找这样的东西:\n{ \"bar\": 1, \"beat\": 5, \"y\": 1, \"type\": \"AddFreeTimeBeat\", \"row\": 0, \"hold\": 0, \"pulse\": 6 },\n其中,\"bar\"是选中事件时左上角现实的小节数,\"beat\"是节拍数,\"row\"代表该事件所属轨道,根据编辑器所示找到这个地雷拍,将row的数值改为对应的二拍轨道(注意轨道编号是0索引的)\n如果你使用的是像是Visual Studio Code这样的代码编辑器,可以将语言模式改为json,可以避免出现语法错误,不过请忽略刚刚打开文件时出现的一大堆\"尾随逗号\"错误。\n\n现版本中,可以启用 高级模式 直接把七拍轨道的节拍拖到二拍轨道。", "parameters": [ { "name": "Enabled", @@ -1550,7 +1758,8 @@ window.CustomMethodSearchData = { { "name": "GoToLevel", "type": "custom_method", - "description": "跳转关卡 - 可以跳转到特定的内部关卡或者本地关卡文件。\n内部关卡名详见 *.rdsave 存档文件。(事实上开启调试模式也能看到内部关卡名,但如果你不知道调试模式是什么,请忽略这句)\n注意:目前,你需要输入完整的文件路径,但跳转内部关卡只需要输入内部关卡名。\n例如:\nGoToLevel(\"OrientalTechno\")\nGoToLevel(\"C:/Users/Ada Paige/Documents/Rhythm Doctor/fizzd - Oriental Techno/main.rdlevel\")\n该方法仅在正常游玩时或者按下 Ctrl+ Shift + R 测试关卡时生效,在编辑器内预览时不生效。", + "shortDescription": "跳转关卡", + "description": "可以跳转到特定的内部关卡或者本地关卡文件。\n内部关卡名详见 *.rdsave 存档文件。(事实上开启调试模式也能看到内部关卡名,但如果你不知道调试模式是什么,请忽略这句)\n注意:目前,你需要输入完整的文件路径,但跳转内部关卡只需要输入内部关卡名。\n例如:\nGoToLevel(\"OrientalTechno\")\nGoToLevel(\"C:/Users/Ada Paige/Documents/Rhythm Doctor/fizzd - Oriental Techno/main.rdlevel\")\n该方法仅在正常游玩时或者按下 Ctrl+ Shift + R 测试关卡时生效,在编辑器内预览时不生效。", "parameters": [ { "name": "LevelName", @@ -1561,7 +1770,8 @@ window.CustomMethodSearchData = { { "name": "forceNoFrameOffsets", "type": "variable", - "description": "强制禁用容错判据显示 - 强制禁用屏幕左上角的容错判据显示,并不会改变玩家设置,并且只在该事件为启用时生效。\n请注意,在非必要情况下,请勿使用该方法。", + "shortDescription": "强制禁用容错判据显示", + "description": "强制禁用屏幕左上角的容错判据显示,并不会改变玩家设置,并且只在该事件为启用时生效。\n请注意,在非必要情况下,请勿使用该方法。", "parameters": [ { "name": "Enabled", @@ -1572,7 +1782,8 @@ window.CustomMethodSearchData = { { "name": "IgnoreInput", "type": "custom_method", - "description": "忽略玩家输入 - 强制忽略玩家的输入。当你的过场动画没有黑边时很有用。", + "shortDescription": "忽略玩家输入", + "description": "强制忽略玩家的输入。当你的过场动画没有黑边时很有用。", "parameters": [ { "name": "Enabled", @@ -1583,7 +1794,8 @@ window.CustomMethodSearchData = { { "name": "ShowHealth", "type": "custom_method", - "description": "显示血条 - 在房间一显示 boss 和病人的血条\n注意:除非在支持自定义类的关卡中,血条纯属装饰。", + "shortDescription": "显示血条", + "description": "在房间一显示 boss 和病人的血条\n注意:除非在支持自定义类的关卡中,血条纯属装饰。", "parameters": [ { "name": "Show", @@ -1591,14 +1803,18 @@ window.CustomMethodSearchData = { }, { "name": "AnimationDurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "ShowVirusBar", "type": "custom_method", - "description": "显示boss血条 - 需要调用 ShowHealth,可切换“VIRUS”栏是否显示。\n注意:除非在支持自定义类的关卡中,血条纯属装饰。", + "shortDescription": "显示boss血条", + "description": "需要调用 ShowHealth,可切换“VIRUS”栏是否显示。\n注意:除非在支持自定义类的关卡中,血条纯属装饰。", "parameters": [ { "name": "Show", @@ -1609,14 +1825,13 @@ window.CustomMethodSearchData = { { "name": "SetNextBar", "type": "custom_method", - "description": "设置下一小节 - 若调用此事件,播放完当前小节后,将跳到 Bar 小节,使用后节拍与音乐不会像立即跳转那样错位,但是音乐不会随着快进", + "shortDescription": "设置下一小节", + "description": "若调用此事件,播放完当前小节后,将跳到 Bar 小节,使用后节拍与音乐不会像立即跳转那样错位,但是音乐不会随着快进", "parameters": [ { "name": "Bar", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -1625,14 +1840,13 @@ window.CustomMethodSearchData = { { "name": "MoveLyric", "type": "custom_method", - "description": "移动歌词 - 将指定 ID 的歌词线性移动到指定位置。\n\n你可以在关卡文件中找到歌词 ID。", + "shortDescription": "移动歌词", + "description": "将指定 ID 的歌词线性移动到指定位置。\n\n你可以在关卡文件中找到歌词 ID。", "parameters": [ { "name": "LyricID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -1649,31 +1863,37 @@ window.CustomMethodSearchData = { { "name": "FadeLyric", "type": "custom_method", - "description": "淡出歌词 - 让指定 ID 的歌词在消失前淡出到指定透明度。\n你可以在关卡文件中找到歌词 ID。\n\n注意:manualLyricAlpha 为 true 时,歌词最后不会消失", + "shortDescription": "淡出歌词", + "description": "让指定 ID 的歌词在消失前淡出到指定透明度。\n你可以在关卡文件中找到歌词 ID。\n\n注意:manualLyricAlpha 为 true 时,歌词最后不会消失", "parameters": [ { "name": "LyricID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, { "name": "Opacity", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "manualLyricAlpha", "type": "variable", - "description": "手动淡入淡出歌词 - 设置是否允许手动淡入淡出歌词,必须搭配 FadeLyric 使用", + "shortDescription": "手动淡入淡出歌词", + "description": "设置是否允许手动淡入淡出歌词,必须搭配 FadeLyric 使用", "parameters": [ { "name": "Enabled", @@ -1684,24 +1904,29 @@ window.CustomMethodSearchData = { { "name": "SetWindowDanceTimeShift", "type": "custom_method", - "description": "窗口动效时移 - 将窗口动效事件向前或向后移动。对于创建故障动画非常有用。\n\n节拍的偏移可以为负值或正值。设置为“0”即可恢复默认。\n\n(图示为连续 10 秒的游戏画面)\n\n注意:技术上“intWindow”被标记为“intRoom”,但它似乎确实影响特定窗口。", + "shortDescription": "窗口动效时移", + "description": "将窗口动效事件向前或向后移动。对于创建故障动画非常有用。\n\n节拍的偏移可以为负值或正值。设置为“0”即可恢复默认。\n\n(图示为连续 10 秒的游戏画面)\n\n注意:技术上“intWindow”被标记为“intRoom”,但它似乎确实影响特定窗口。", "parameters": [ { "name": "Window", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, { "name": "ShiftBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -1712,14 +1937,13 @@ window.CustomMethodSearchData = { { "name": "ToggleWindowDanceWrap", "type": "custom_method", - "description": "设置缠绕效果 - 设置指定窗口在使用缠绕移动模式时,是否可以在指定轴上缠绕屏幕。\n\n如果 Vertical 为 true,则影响垂直方向的移动;如果为 false,则影响水平方向的移动。\n\n如果 Wrap 为 true,则窗口可以在给定轴上环绕(默认);如果为 false,则窗口将不再环绕。\n\n如果之前禁用了环绕,然后后来启用了,那么窗口的位置将会像从一开始就启用了环绕一样。\n如果之前启用了环绕,然后后来禁用了,那么窗口的位置将会像从一开始就禁用了环绕一样。\n\n注意:技术上“intWindow”被标记为“intRoom”,但它似乎影响的是给定的窗口。", + "shortDescription": "设置缠绕效果", + "description": "设置指定窗口在使用缠绕移动模式时,是否可以在指定轴上缠绕屏幕。\n\n如果 Vertical 为 true,则影响垂直方向的移动;如果为 false,则影响水平方向的移动。\n\n如果 Wrap 为 true,则窗口可以在给定轴上环绕(默认);如果为 false,则窗口将不再环绕。\n\n如果之前禁用了环绕,然后后来启用了,那么窗口的位置将会像从一开始就启用了环绕一样。\n如果之前启用了环绕,然后后来禁用了,那么窗口的位置将会像从一开始就禁用了环绕一样。\n\n注意:技术上“intWindow”被标记为“intRoom”,但它似乎影响的是给定的窗口。", "parameters": [ { "name": "Window", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -1736,55 +1960,69 @@ window.CustomMethodSearchData = { { "name": "windowSize", "type": "comment", - "description": "窗口大小重设 - 注释事件版的窗口大小重设,但没有大小限制,\n可以用此来实现全屏窗口\n只能控制窗口 1,且锁定为 linear 缓速和\"无\"缩放模式", + "shortDescription": "窗口大小重设", + "description": "注释事件版的窗口大小重设,但没有大小限制,\n可以用此来实现全屏窗口\n只能控制窗口 1,且锁定为 linear 缓速和\"无\"缩放模式", "parameters": [ { "name": "SizeX", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "SizeY", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "ShakeRow", "type": "custom_method", - "description": "震动轨道 - 使指定的轨道的角色和心脏震动。", + "shortDescription": "震动轨道", + "description": "使指定的轨道的角色和心脏震动。", "parameters": [ { "name": "row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "amount", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } }, { "name": "duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "ShakeSprite", "type": "custom_method", - "description": "震动精灵图 - 使指定的精灵图震动。\n其中,spriteID 需要查看 *.rdlevel 文件中\"decorations\"下对应精灵图的\"id\"", + "shortDescription": "震动精灵图", + "description": "使指定的精灵图震动。\n其中,spriteID 需要查看 *.rdlevel 文件中\"decorations\"下对应精灵图的\"id\"", "parameters": [ { "name": "spriteID", @@ -1798,8 +2036,6 @@ window.CustomMethodSearchData = { "name": "freq", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -1816,7 +2052,8 @@ window.CustomMethodSearchData = { { "name": "ShowMarginError", "type": "custom_method", - "description": "显示判定结果 - 像 1-1 教程一样,在你按拍时用状态牌显示判定结果。", + "shortDescription": "显示判定结果", + "description": "像 1-1 教程一样,在你按拍时用状态牌显示判定结果。", "parameters": [ { "name": "Enabled", @@ -1827,7 +2064,8 @@ window.CustomMethodSearchData = { { "name": "SetRankMargin", "type": "custom_method", - "description": "设置评级失误数 - 设置指定评级的最大失误数。", + "shortDescription": "设置评级失误数", + "description": "设置指定评级的最大失误数。", "parameters": [ { "name": "rank", @@ -1837,9 +2075,8 @@ window.CustomMethodSearchData = { "name": "margin", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } } ] @@ -1847,15 +2084,16 @@ window.CustomMethodSearchData = { { "name": "InfectHeart", "type": "custom_method", - "description": "感染心脏 - 使指定轨道的心脏变为网好卡菌感染样式。\n\n可以搭配 sndBossVirusDie 音效使用。", + "shortDescription": "感染心脏", + "description": "使指定轨道的心脏变为网好卡菌感染样式。\n\n可以搭配 sndBossVirusDie 音效使用。", "parameters": [ { "name": "row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -1867,36 +2105,38 @@ window.CustomMethodSearchData = { { "name": "UpdateAllHearts", "type": "custom_method", - "description": "更新心脏 - 视觉上更新每条轨道的心脏以匹配失误数。", + "shortDescription": "更新心脏", + "description": "视觉上更新每条轨道的心脏以匹配失误数。", "parameters": [] }, { "name": "CrackAllHearts", "type": "custom_method", - "description": "碎裂心脏 - 使所有轨道的心脏碎裂。", + "shortDescription": "碎裂心脏", + "description": "使所有轨道的心脏碎裂。", "parameters": [] }, { "name": "SetRowLength", "type": "custom_method", - "description": "设置轨道长度 - 设置指定轨道的长度。最大值为 7,最小值为 1。\n推荐搭配 sndRowShrink 音效。", + "shortDescription": "设置轨道长度", + "description": "设置指定轨道的长度。最大值为 7,最小值为 1。\n推荐搭配 sndRowShrink 音效。", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "Length", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } } ] @@ -1904,14 +2144,13 @@ window.CustomMethodSearchData = { { "name": "TweenFloat", "type": "custom_method", - "description": "浮点插值 - 平滑地将给定浮点数的值在指定的节拍数内从当前值过渡到指定值,并使用给定的缓动方式。\n如果 FloatID 不在 [0, 9] 范围内,方法调用将被忽略。\n\n例如,假设 f1 目前为 3,在第 4 拍运行 TweenFloat(1, 5, 2, \"Linear\"),则:\n- 第 4 拍时,f1 为 3 并开始更新\n- 第 5 拍时,f1 为 4\n- 第 6 拍时,f1 为 5 并停止更新。", + "shortDescription": "浮点插值", + "description": "平滑地将给定浮点数的值在指定的节拍数内从当前值过渡到指定值,并使用给定的缓动方式。\n如果 FloatID 不在 [0, 9] 范围内,方法调用将被忽略。\n\n例如,假设 f1 目前为 3,在第 4 拍运行 TweenFloat(1, 5, 2, \"Linear\"),则:\n- 第 4 拍时,f1 为 3 并开始更新\n- 第 5 拍时,f1 为 4\n- 第 6 拍时,f1 为 5 并停止更新。", "parameters": [ { "name": "FloatID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -1921,7 +2160,10 @@ window.CustomMethodSearchData = { }, { "name": "Beats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Ease", @@ -1932,15 +2174,16 @@ window.CustomMethodSearchData = { { "name": "ShowSpotlight", "type": "custom_method", - "description": "显示聚光灯 - 在指定轨道的角色的位置和房间显示关卡失败和选择关卡时的聚光灯,可选播放音效。\n只能同时出现一个聚光灯,多次调用会覆盖上一次的结果。", + "shortDescription": "显示聚光灯", + "description": "在指定轨道的角色的位置和房间显示关卡失败和选择关卡时的聚光灯,可选播放音效。\n只能同时出现一个聚光灯,多次调用会覆盖上一次的结果。", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -1952,61 +2195,70 @@ window.CustomMethodSearchData = { { "name": "ExpandSpotlight", "type": "custom_method", - "description": "拓宽聚光灯 - 将聚光灯扩大,直到在指定的节拍数量内填满整个屏幕。如果聚光灯当前未激活,则不会执行任何操作。", + "shortDescription": "拓宽聚光灯", + "description": "将聚光灯扩大,直到在指定的节拍数量内填满整个屏幕。如果聚光灯当前未激活,则不会执行任何操作。", "parameters": [ { "name": "Beats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "HideSpotlight", "type": "custom_method", - "description": "隐藏聚光灯 - 立即隐藏聚光灯,如果聚光灯当前未激活,则不会执行任何操作。", + "shortDescription": "隐藏聚光灯", + "description": "立即隐藏聚光灯,如果聚光灯当前未激活,则不会执行任何操作。", "parameters": [] }, { "name": "SetRowLengthTimed", "type": "custom_method", - "description": "设置轨道长度 - 和 SetRowLength 一样,但可以自定义执行时间", + "shortDescription": "设置轨道长度", + "description": "和 SetRowLength 一样,但可以自定义执行时间", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { "name": "RowLength", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "TweenOneshotPositionOverride", "type": "custom_method", - "description": "单发拍脉冲范围插值 - 设置指定轨道单发拍脉冲出现位置的范围。\n\noverridePosition 为介于轨道最左端与轨道黄色部分最左端之间的插值比例。\n\n需要搭配 TweenOneshotPositionOverrideLerp() 才能正常使用。\n\n感谢 @Sterix_Craft砹氪硒 制作的示例图片。", + "shortDescription": "单发拍脉冲范围插值", + "description": "设置指定轨道单发拍脉冲出现位置的范围。\n\noverridePosition 为介于轨道最左端与轨道黄色部分最左端之间的插值比例。\n\n需要搭配 TweenOneshotPositionOverrideLerp() 才能正常使用。\n\n感谢 @Sterix_Craft砹氪硒 制作的示例图片。", "parameters": [ { "name": "row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -2015,22 +2267,26 @@ window.CustomMethodSearchData = { }, { "name": "durationBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "TweenOneshotPositionOverrideLerp", "type": "custom_method", - "description": "单发拍脉冲位置插值 - 把指定轨道上的单发拍脉冲移动到你想要的位置。可用于制作类似 X-PBC 中的二拍滑步效果\n\noverridePosition 是一个插值比例(0~1),介于默认位置与 TweenOneshotPositionOverride() 所设定的位置之间。\n\n特别地,对于冰冻拍:\n当脉冲被冻结时(显示为蓝线),默认冻结位置大约是 0.7。\n此时,overridePosition 表示在“这个默认冻结位置(0.7)”与 TweenOneshotPositionOverride() 设定的位置之间的插值比例。\n\n示例:\n假设 TweenOneshotPositionOverride() 设定的位置是 0.2,冻结时设置 overridePosition = 0.5,那么实际位置 = 0.2 + 0.5 × (0.7 − 0.2) = 0.45\n\n为了方便操作,你可以在脉冲冻结时", + "shortDescription": "单发拍脉冲位置插值", + "description": "把指定轨道上的单发拍脉冲移动到你想要的位置。可用于制作类似 X-PBC 中的二拍滑步效果\n\noverridePosition 是一个插值比例(0~1),介于默认位置与 TweenOneshotPositionOverride() 所设定的位置之间。\n\n特别地,对于冰冻拍:\n当脉冲被冻结时(显示为蓝线),默认冻结位置大约是 0.7。\n此时,overridePosition 表示在“这个默认冻结位置(0.7)”与 TweenOneshotPositionOverride() 设定的位置之间的插值比例。\n\n示例:\n假设 TweenOneshotPositionOverride() 设定的位置是 0.2,冻结时设置 overridePosition = 0.5,那么实际位置 = 0.2 + 0.5 × (0.7 − 0.2) = 0.45\n\n为了方便操作,你可以在脉冲冻结时,直接用 TweenOneshotPositionOverride() 将范围设为 0。\n\n当 overridePosition = 0 时,位置会重置到默认位置。\n如果需要重复实现移动效果,每次脉冲出现时都要重新重置位置。", "parameters": [ { "name": "row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } }, { @@ -2039,14 +2295,18 @@ window.CustomMethodSearchData = { }, { "name": "durationBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "SpaceStars", "type": "custom_method", - "description": "设置太空主题星星 - 开启/关闭太空主题中的星星。", + "shortDescription": "设置太空主题星星", + "description": "开启/关闭太空主题中的星星。", "parameters": [ { "name": "Enabled", @@ -2057,15 +2317,16 @@ window.CustomMethodSearchData = { { "name": "ForceHeldBeatRelease", "type": "custom_method", - "description": "强制松开长按 - 强制松开指定轨道的长按拍,无论玩家是否按住长按拍,像 7-X2 那样。\n会增加失误数。", + "shortDescription": "强制松开长按", + "description": "强制松开指定轨道的长按拍,无论玩家是否按住长按拍,像 7-X2 那样。\n会增加失误数。", "parameters": [ { "name": "Row", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -2073,7 +2334,8 @@ window.CustomMethodSearchData = { { "name": "SetBaseballTrajectory", "type": "custom_method", - "description": "设置棒球轨迹 - 改变棒球的前进方向。\n\nTrajectoryString 的枚举列表:\nField - 默认方向\nScreen - 飞向屏幕\nFoul - 角度变陡", + "shortDescription": "设置棒球轨迹", + "description": "改变棒球的前进方向。\n\nTrajectoryString 的枚举列表:\nField - 默认方向\nScreen - 飞向屏幕\nFoul - 角度变陡", "parameters": [ { "name": "preset", @@ -2085,7 +2347,8 @@ window.CustomMethodSearchData = { { "name": "SetBaseballAngleRange", "type": "custom_method", - "description": "设置棒球角度 - 改变按拍时棒球飞翔的角度范围。", + "shortDescription": "设置棒球角度", + "description": "改变按拍时棒球飞翔的角度范围。", "parameters": [ { "name": "minAngle", @@ -2100,7 +2363,8 @@ window.CustomMethodSearchData = { { "name": "CustomBaseball", "type": "custom_method", - "description": "自定义棒球 - 顾名思义,创建一个自定义棒球运动。", + "shortDescription": "自定义棒球", + "description": "顾名思义,创建一个自定义棒球运动。", "parameters": [ { "name": "startX", @@ -2128,7 +2392,10 @@ window.CustomMethodSearchData = { }, { "name": "height", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "rotation", @@ -2140,7 +2407,10 @@ window.CustomMethodSearchData = { }, { "name": "duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Ease", @@ -2152,6 +2422,7 @@ window.CustomMethodSearchData = { { "name": "SetRain", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { @@ -2163,13 +2434,15 @@ window.CustomMethodSearchData = { { "name": "KillRain", "type": "custom_method", - "description": "棒球雨 - 使棒球从天空中落下。\n使用 SetRain(0) 或 KillRain() 可以清除棒球。", + "shortDescription": "棒球雨", + "description": "使棒球从天空中落下。\n使用 SetRain(0) 或 KillRain() 可以清除棒球。", "parameters": [] }, { "name": "ToggleScoreboardLights", "type": "custom_method", - "description": "开关记分板 - 开启/关闭整个计分板。", + "shortDescription": "开关记分板", + "description": "开启/关闭整个计分板。", "parameters": [ { "name": "Enabled", @@ -2180,7 +2453,8 @@ window.CustomMethodSearchData = { { "name": "SetScoreboardLights", "type": "custom_method", - "description": "设置计分板灯光 - 设置计分板显示的文字。\n注意:有些字符不会显示,而且使用\"LuckyBreak\"自定义类会计算按拍数,但使用此方法会使计数暂时消失,直到下次按拍。\n一些实用字符:║RLJ7^_1|(制表符║会使输入框内容不显示)", + "shortDescription": "设置计分板灯光", + "description": "设置计分板显示的文字。\n注意:有些字符不会显示,而且使用\"LuckyBreak\"自定义类会计算按拍数,但使用此方法会使计数暂时消失,直到下次按拍。\n一些实用字符:║RLJ7^_1|(制表符║会使输入框内容不显示)", "parameters": [ { "name": "IsTop", @@ -2194,8 +2468,6 @@ window.CustomMethodSearchData = { "name": "StartIndex", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -2204,7 +2476,8 @@ window.CustomMethodSearchData = { { "name": "SetScoreboardLightsGentle", "type": "custom_method", - "description": "覆写计分板灯光 - 如上文\"SetScoreboardLights\",但并不会刷新整个计分板行来显示文本,仅仅是覆盖原来的内容,不会覆盖按拍计数。", + "shortDescription": "覆写计分板灯光", + "description": "如上文\"SetScoreboardLights\",但并不会刷新整个计分板行来显示文本,仅仅是覆盖原来的内容,不会覆盖按拍计数。", "parameters": [ { "name": "IsTop", @@ -2218,8 +2491,6 @@ window.CustomMethodSearchData = { "name": "StartIndex", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -2228,7 +2499,8 @@ window.CustomMethodSearchData = { { "name": "ClearScoreboardLights", "type": "custom_method", - "description": "清空计分板指定行 - 清空计分板选定行的内容。", + "shortDescription": "清空计分板指定行", + "description": "清空计分板选定行的内容。", "parameters": [ { "name": "IsTop", @@ -2239,13 +2511,15 @@ window.CustomMethodSearchData = { { "name": "ClearAllScoreboardLights", "type": "custom_method", - "description": "清空计分板 - 清空计分板上的全部内容。", + "shortDescription": "清空计分板", + "description": "清空计分板上的全部内容。", "parameters": [] }, { "name": "SetTrackingScore", "type": "custom_method", - "description": "开关计数显示 - 开关计分板上的分数显示。\n目前没用。", + "shortDescription": "开关计数显示", + "description": "开关计分板上的分数显示。\n目前没用。", "parameters": [ { "name": "Enabled", @@ -2256,7 +2530,8 @@ window.CustomMethodSearchData = { { "name": "SetGlitchyLights", "type": "custom_method", - "description": "开关记分板乱码 - 让计分板像 5-1 一样乱码。", + "shortDescription": "开关记分板乱码", + "description": "让计分板像 5-1 一样乱码。", "parameters": [ { "name": "Enabled", @@ -2267,13 +2542,15 @@ window.CustomMethodSearchData = { { "name": "AdvanceScoreboardInning", "type": "custom_method", - "description": "更新计分板显示 - 需要开启双人模式。改变\"Home\"和\"Guest\"栏的显示。调用此事件时,两个玩家中按拍较多的的一位\"RUN\"栏+1,左侧对应位置显示为 1,否则为 0,调用此事件将归零按拍计数。", + "shortDescription": "更新计分板显示", + "description": "需要开启双人模式。改变\"Home\"和\"Guest\"栏的显示。调用此事件时,两个玩家中按拍较多的的一位\"RUN\"栏+1,左侧对应位置显示为 1,否则为 0,调用此事件将归零按拍计数。", "parameters": [] }, { "name": "DoLightning", "type": "custom_method", - "description": "打雷 - 在天空中创建闪电效果,\"ShowTeam\"为 true 时也会显示路吉的球队……而他们在看着你👀", + "shortDescription": "打雷", + "description": "在天空中创建闪电效果,\"ShowTeam\"为 true 时也会显示路吉的球队……而他们在看着你👀", "parameters": [ { "name": "ShowTeam", @@ -2284,19 +2561,22 @@ window.CustomMethodSearchData = { { "name": "SetTeamStare", "type": "custom_method", - "description": "显示棒球队 - 需要棒球场主题并设置为\"风暴来临\"。\n让棒球队盯着你👀", + "shortDescription": "显示棒球队", + "description": "需要棒球场主题并设置为\"风暴来临\"。\n让棒球队盯着你👀", "parameters": [] }, { "name": "ShowPreStorm", "type": "custom_method", - "description": "显示风暴来临前的球场 - 把球场的天空变为与\"风暴来临\"略微不同的天空。", + "shortDescription": "显示风暴来临前的球场", + "description": "把球场的天空变为与\"风暴来临\"略微不同的天空。", "parameters": [] }, { "name": "SetStorm", "type": "custom_method", - "description": "显示风暴 - 把天空改成\"风暴来临\",最好把 Animate 设置为 true 并在此之前调用 ShowPreStorm()。", + "shortDescription": "显示风暴", + "description": "把天空改成\"风暴来临\",最好把 Animate 设置为 true 并在此之前调用 ShowPreStorm()。", "parameters": [ { "name": "Storm", @@ -2311,7 +2591,8 @@ window.CustomMethodSearchData = { { "name": "ShowEdega", "type": "custom_method", - "description": "显示埃德加 - 显示理疗病房背景中的埃德加。\n需要将房间三的主题设置为理疗病房。", + "shortDescription": "显示埃德加", + "description": "显示理疗病房背景中的埃德加。\n需要将房间三的主题设置为理疗病房。", "parameters": [ { "name": "Show", @@ -2322,7 +2603,8 @@ window.CustomMethodSearchData = { { "name": "ToggleBubbles", "type": "custom_method", - "description": "启用泡泡遮罩 - 启用房间 1 的泡泡遮罩效果,可以通过 MoveBubblesToRoom 移动到其他房间", + "shortDescription": "启用泡泡遮罩", + "description": "启用房间 1 的泡泡遮罩效果,可以通过 MoveBubblesToRoom 移动到其他房间", "parameters": [ { "name": "Enabled", @@ -2333,7 +2615,8 @@ window.CustomMethodSearchData = { { "name": "FlipBubbles", "type": "custom_method", - "description": "翻转泡泡遮罩 - 上下翻转泡泡遮罩效果。\n注意:如果泡泡遮罩没有在默认位置,翻转后会导致泡泡遮罩位于当前房间下面,需要移动来移回来", + "shortDescription": "翻转泡泡遮罩", + "description": "上下翻转泡泡遮罩效果。\n注意:如果泡泡遮罩没有在默认位置,翻转后会导致泡泡遮罩位于当前房间下面,需要移动来移回来", "parameters": [ { "name": "Flipped", @@ -2344,7 +2627,8 @@ window.CustomMethodSearchData = { { "name": "MoveBubbles", "type": "custom_method", - "description": "移动泡泡遮罩 - 将泡泡遮罩移动到指定位置。\n图中示例为 MoveBubbles(0, 0, \"Linear\")\n注意:如果通过 FlipBubbles() 翻转了泡泡遮罩效果,移动的位置需要改变,该位置需要大约140的数值才能重新进入画面。", + "shortDescription": "移动泡泡遮罩", + "description": "将泡泡遮罩移动到指定位置。\n图中示例为 MoveBubbles(0, 0, \"Linear\")\n注意:如果通过 FlipBubbles() 翻转了泡泡遮罩效果,移动的位置需要改变,该位置需要大约140的数值才能重新进入画面。", "parameters": [ { "name": "YPosition", @@ -2352,7 +2636,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2363,15 +2650,16 @@ window.CustomMethodSearchData = { { "name": "MoveBubblesToRoom", "type": "custom_method", - "description": "移动泡泡遮罩到房间 - 将泡泡遮罩移动到指定房间。", + "shortDescription": "移动泡泡遮罩到房间", + "description": "将泡泡遮罩移动到指定房间。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } } ] @@ -2379,14 +2667,13 @@ window.CustomMethodSearchData = { { "name": "MoveBubbleShape", "type": "custom_method", - "description": "移动气泡遮罩 - 把房间 4 的气泡遮罩移动到指定位置,必须在调用 ScaleBubbleShape 前使用才能显示效果。\n默认中心位置为\nMoveBubbleShape(0, 50, 50, 0, \"Linear\")", + "shortDescription": "移动气泡遮罩", + "description": "把房间 4 的气泡遮罩移动到指定位置,必须在调用 ScaleBubbleShape 前使用才能显示效果。\n默认中心位置为\nMoveBubbleShape(0, 50, 50, 0, \"Linear\")", "parameters": [ { "name": "ShapeID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -2400,7 +2687,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2411,14 +2701,13 @@ window.CustomMethodSearchData = { { "name": "ScaleBubbleShape", "type": "custom_method", - "description": "缩放气泡遮罩 - 将指定 ShapeID 的气泡遮罩缩放到指定大小,\n需要事先调用 MoveBubbleShape 才能正常显示。\n图中为缩放 ShapeID 1 的效果。", + "shortDescription": "缩放气泡遮罩", + "description": "将指定 ShapeID 的气泡遮罩缩放到指定大小,\n需要事先调用 MoveBubbleShape 才能正常显示。\n图中为缩放 ShapeID 1 的效果。", "parameters": [ { "name": "ShapeID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -2432,7 +2721,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2443,31 +2735,36 @@ window.CustomMethodSearchData = { { "name": "PauseBubbleMask", "type": "custom_method", - "description": "冻结气泡遮罩 - 调用时冻结房间 4 的所有气泡遮罩。", + "shortDescription": "冻结气泡遮罩", + "description": "调用时冻结房间 4 的所有气泡遮罩。", "parameters": [] }, { "name": "RunBubbleMask", "type": "custom_method", - "description": "恢复气泡遮罩 - 让房间 4 的气泡遮罩从冻结效果中恢复回来。", + "shortDescription": "恢复气泡遮罩", + "description": "让房间 4 的气泡遮罩从冻结效果中恢复回来。", "parameters": [] }, { "name": "DisableBubbleMask", "type": "custom_method", - "description": "禁用气泡遮罩 - 立即隐藏房间 4 中的所有气泡遮罩。", + "shortDescription": "禁用气泡遮罩", + "description": "立即隐藏房间 4 中的所有气泡遮罩。", "parameters": [] }, { "name": "EnableBubbleMask", "type": "custom_method", - "description": "启用气泡遮罩 - 平滑地展开房间 4 的气泡遮罩。这些遮罩仍保持原来的位置与大小。", + "shortDescription": "启用气泡遮罩", + "description": "平滑地展开房间 4 的气泡遮罩。这些遮罩仍保持原来的位置与大小。", "parameters": [] }, { "name": "TogglePhone", "type": "custom_method", - "description": "设置手机 - 显示科尔在房间 3 拿着他的手机。默认情况下会出现在房间下方的屏幕之外,屏幕上显示房间 1,并且手出现在屏幕上。", + "shortDescription": "设置手机", + "description": "显示科尔在房间 3 拿着他的手机。默认情况下会出现在房间下方的屏幕之外,屏幕上显示房间 1,并且手出现在屏幕上。", "parameters": [ { "name": "Enabled", @@ -2478,7 +2775,8 @@ window.CustomMethodSearchData = { { "name": "ToggleStreamUI", "type": "custom_method", - "description": "设置直播UI - 开启/关闭手机屏幕上油管风格的UI。", + "shortDescription": "设置直播UI", + "description": "开启/关闭手机屏幕上油管风格的UI。", "parameters": [ { "name": "Enabled", @@ -2489,7 +2787,8 @@ window.CustomMethodSearchData = { { "name": "ShowOrHideStreamUI", "type": "custom_method", - "description": "显示直播UI - 淡入/淡出手机屏幕上油管风格的UI。", + "shortDescription": "显示直播UI", + "description": "淡入/淡出手机屏幕上油管风格的UI。", "parameters": [ { "name": "Enabled", @@ -2497,14 +2796,18 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "ToggleStream", "type": "custom_method", - "description": "设置直播 - 开启/关闭房间 1 的直播,如果关闭,手机屏幕会显示妮可。", + "shortDescription": "设置直播", + "description": "开启/关闭房间 1 的直播,如果关闭,手机屏幕会显示妮可。", "parameters": [ { "name": "Enabled", @@ -2515,7 +2818,8 @@ window.CustomMethodSearchData = { { "name": "MoveStream", "type": "custom_method", - "description": "移动直播 - 将房间 1 的直播移动到手机上的指定位置。", + "shortDescription": "移动直播", + "description": "将房间 1 的直播移动到手机上的指定位置。", "parameters": [ { "name": "YPos", @@ -2523,7 +2827,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2534,7 +2841,8 @@ window.CustomMethodSearchData = { { "name": "MovePhone", "type": "custom_method", - "description": "移动手机 - 将手机移动到指定位置。", + "shortDescription": "移动手机", + "description": "将手机移动到指定位置。", "parameters": [ { "name": "XPos", @@ -2546,7 +2854,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2557,7 +2868,8 @@ window.CustomMethodSearchData = { { "name": "MoveHand", "type": "custom_method", - "description": "移动手 - 将科尔的手移动到指定位置。", + "shortDescription": "移动手", + "description": "将科尔的手移动到指定位置。", "parameters": [ { "name": "YPos", @@ -2565,7 +2877,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2576,7 +2891,8 @@ window.CustomMethodSearchData = { { "name": "ToggleHandPress", "type": "custom_method", - "description": "设置手点击 - 让科尔的手点击屏幕。", + "shortDescription": "设置手点击", + "description": "让科尔的手点击屏幕。", "parameters": [ { "name": "Pressing", @@ -2584,7 +2900,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2595,7 +2914,8 @@ window.CustomMethodSearchData = { { "name": "ToggleBaseball", "type": "custom_method", - "description": "设置棒球 - 显示房间 3 角落中具有音频相应效果的棒球。", + "shortDescription": "设置棒球", + "description": "显示房间 3 角落中具有音频相应效果的棒球。", "parameters": [ { "name": "Enabled", @@ -2606,7 +2926,8 @@ window.CustomMethodSearchData = { { "name": "ToggleFallingBaseballs", "type": "custom_method", - "description": "设置棒球坠落 - 创建棒球坠落效果。\n注意:调用此事件前需要先调用 ToggleBaseball,不然中间会显示漂浮之心主题中的心脏。", + "shortDescription": "设置棒球坠落", + "description": "创建棒球坠落效果。\n注意:调用此事件前需要先调用 ToggleBaseball,不然中间会显示漂浮之心主题中的心脏。", "parameters": [ { "name": "Enabled", @@ -2617,72 +2938,94 @@ window.CustomMethodSearchData = { { "name": "SetFallingBaseballsSpeed", "type": "custom_method", - "description": "设置棒球坠落速度 - 改变 ToogleFallingBaseballs 中棒球坠落的速度,默认值为100。", + "shortDescription": "设置棒球坠落速度", + "description": "改变 ToogleFallingBaseballs 中棒球坠落的速度,默认值为100。", "parameters": [ { "name": "Speed", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "FadePhysioLights", "type": "custom_method", - "description": "淡入淡出理疗病房灯光 - 将理疗病房的灯光淡入淡出到指定透明度。\n最低为 0。", + "shortDescription": "淡入淡出理疗病房灯光", + "description": "将理疗病房的灯光淡入淡出到指定透明度。\n最低为 0。", "parameters": [ { "name": "Opacity", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "FadePhysioFG", "type": "custom_method", - "description": "淡入淡出理疗病房前景 - 将理疗病房的前景淡入淡出到指定透明度。", + "shortDescription": "淡入淡出理疗病房前景", + "description": "将理疗病房的前景淡入淡出到指定透明度。", "parameters": [ { "name": "Opacity", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "StartWardScroll", "type": "custom_method", - "description": "滚动医院走廊 - 无缝地滚动医院走廊背景。", + "shortDescription": "滚动医院走廊", + "description": "无缝地滚动医院走廊背景。", "parameters": [ { "name": "Speed", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "StopWardScroll", "type": "custom_method", - "description": "停止走廊滚动 - 停止走廊滚动,并停留在当前位置。", + "shortDescription": "停止走廊滚动", + "description": "停止走廊滚动,并停留在当前位置。", "parameters": [] }, { "name": "SetTransferTargetForRow", "type": "custom_method", - "description": "转移轨道表情 - 将指定轨道的按拍或失误时播放的表情转移到目标轨道上。\n可能需要提前一拍调用。", + "shortDescription": "转移轨道表情", + "description": "将指定轨道的按拍或失误时播放的表情转移到目标轨道上。\n可能需要提前一拍调用。", "parameters": [ { "name": "SourceRowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -2690,8 +3033,6 @@ window.CustomMethodSearchData = { "name": "DestinationRowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -2700,13 +3041,15 @@ window.CustomMethodSearchData = { { "name": "PasteCurrentFrame", "type": "custom_method", - "description": "粘贴当前帧 - 把当前房间 3 的内容粘贴到房间 4。\n为了制作 5-2 中的效果,需要使用移动房间事件和房间重排序,并将这两个房间设为透明背景。", + "shortDescription": "粘贴当前帧", + "description": "把当前房间 3 的内容粘贴到房间 4。\n为了制作 5-2 中的效果,需要使用移动房间事件和房间重排序,并将这两个房间设为透明背景。", "parameters": [] }, { "name": "ToggleAfterimages", "type": "custom_method", - "description": "设置残影效果 - 开启/关闭自动创建残影效果。\n不影响 PasteCurrentFrame。", + "shortDescription": "设置残影效果", + "description": "开启/关闭自动创建残影效果。\n不影响 PasteCurrentFrame。", "parameters": [ { "name": "Enabled", @@ -2717,15 +3060,22 @@ window.CustomMethodSearchData = { { "name": "SetAfterimageParams", "type": "custom_method", - "description": "配置残影效果 - 设置残影效果的参数\n\ninterval:自动粘贴残影的时间间隔(以秒为单位)\n\nFadeTime:残影的消退时间(以秒为单位)\n\nColor:应用于残影的色调(十六进制)。包括用于部分色调的 alpha 通道。\n\nSize:逐渐应用于每个残影的缩放因数以增大或缩小(默认值为 1)", + "shortDescription": "配置残影效果", + "description": "设置残影效果的参数\n\ninterval:自动粘贴残影的时间间隔(以秒为单位)\n\nFadeTime:残影的消退时间(以秒为单位)\n\nColor:应用于残影的色调(十六进制)。包括用于部分色调的 alpha 通道。\n\nSize:逐渐应用于每个残影的缩放因数以增大或缩小(默认值为 1)", "parameters": [ { "name": "Interval", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "FadeTime", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Color", @@ -2733,28 +3083,33 @@ window.CustomMethodSearchData = { }, { "name": "Size", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "SpaceSetup", "type": "custom_method", - "description": "初始化太空场景 - 给太空主题的摄像头换个角度,更靠近星球。\n注意:调用此方法后再设置主题只会显示星星,而不是主题的其他部分。可以再次调用该方法来解决问题。", + "shortDescription": "初始化太空场景", + "description": "给太空主题的摄像头换个角度,更靠近星球。\n注意:调用此方法后再设置主题只会显示星星,而不是主题的其他部分。可以再次调用该方法来解决问题。", "parameters": [] }, { "name": "AddGlowRow", "type": "custom_method", - "description": "添加轨道闪烁 - 让指定轨道随着音乐闪烁。\n可以用\"RemoveGlowRow\"方法停止,只会停止轨道随着音乐闪烁,需要用轨道涂色事件来重置外部的颜色,然而内部涂色需要 TweenOverrideAlpha 才能重置。", + "shortDescription": "添加轨道闪烁", + "description": "让指定轨道随着音乐闪烁。\n可以用\"RemoveGlowRow\"方法停止,只会停止轨道随着音乐闪烁,需要用轨道涂色事件来重置外部的颜色,然而内部涂色需要 TweenOverrideAlpha 才能重置。", "parameters": [ { "name": "RowID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 15 } } ] @@ -2762,7 +3117,8 @@ window.CustomMethodSearchData = { { "name": "SetManualGlow", "type": "custom_method", - "description": "设置闪烁颜色 - 改变轨道闪烁的颜色。", + "shortDescription": "设置闪烁颜色", + "description": "改变轨道闪烁的颜色。", "parameters": [ { "name": "R", @@ -2781,7 +3137,8 @@ window.CustomMethodSearchData = { { "name": "TweenOverrideAlpha", "type": "custom_method", - "description": "设置闪烁透明度 - 改变闪烁的透明度。", + "shortDescription": "设置闪烁透明度", + "description": "改变闪烁的透明度。", "parameters": [ { "name": "Alpha", @@ -2789,28 +3146,33 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "VRankHacky", "type": "custom_method", - "description": "修改评级字母 - 把评级字母换成V,覆盖原来文本的颜色,需要与第二个结束关卡事件同时执行,不然会出现的稍早一些,而且原来的评级字母会叠在底下。\n最好加上 atLeastRank(S+) 条件。", + "shortDescription": "修改评级字母", + "description": "把评级字母换成V,覆盖原来文本的颜色,需要与第二个结束关卡事件同时执行,不然会出现的稍早一些,而且原来的评级字母会叠在底下。\n最好加上 atLeastRank(S+) 条件。", "parameters": [] }, { "name": "ShowBossText", "type": "custom_method", - "description": "显示Boss文本 - 在指定房间的指定位置显示\"boss stage\"文本。", + "shortDescription": "显示Boss文本", + "description": "在指定房间的指定位置显示\"boss stage\"文本。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -2826,13 +3188,15 @@ window.CustomMethodSearchData = { { "name": "SetLevelFailed", "type": "custom_method", - "description": "设置关卡失败 - 让关卡被标记为失败并切换到关卡结束评级界面。", + "shortDescription": "设置关卡失败", + "description": "让关卡被标记为失败并切换到关卡结束评级界面。", "parameters": [] }, { "name": "StareAtPlayer", "type": "custom_method", - "description": "注视玩家 - 让房间 3 和房间 4 的眼睛注视玩家的手。\n\n注意:截图中是房间 3 和房间 4 一起展示", + "shortDescription": "注视玩家", + "description": "让房间 3 和房间 4 的眼睛注视玩家的手。\n\n注意:截图中是房间 3 和房间 4 一起展示", "parameters": [ { "name": "Player2", @@ -2843,13 +3207,15 @@ window.CustomMethodSearchData = { { "name": "StareAtMark", "type": "custom_method", - "description": "注视马克 - 让房间 3 和房间 4 的眼睛注视 1 号轨道的角色。\n\n注意:截图中是房间 3 和房间 4 一起展示", + "shortDescription": "注视马克", + "description": "让房间 3 和房间 4 的眼睛注视 1 号轨道的角色。\n\n注意:截图中是房间 3 和房间 4 一起展示", "parameters": [] }, { "name": "EyesBlink", "type": "custom_method", - "description": "眨眼 - 让房间 3 的大眼睛眨一下,每调用一次该方法只会眨一次眼\n\n填 0 即不眨眼,填 1 为所有眼睛都眨眼,", + "shortDescription": "眨眼", + "description": "让房间 3 的大眼睛眨一下,每调用一次该方法只会眨一次眼\n\n填 0 即不眨眼,填 1 为所有眼睛都眨眼,", "parameters": [ { "name": "PercentageOfEyes", @@ -2860,15 +3226,22 @@ window.CustomMethodSearchData = { { "name": "EyeScroll", "type": "custom_method", - "description": "眼睛滚动 - 让房间3和房间4的眼睛滚动。\n\n图中示例:EyeScroll(50, 2, \"Linear\")\n\n注意:这里隐藏了房间4,实际上房间4的眼睛也在一起滚动。", + "shortDescription": "眼睛滚动", + "description": "让房间3和房间4的眼睛滚动。\n\n图中示例:EyeScroll(50, 2, \"Linear\")\n\n注意:这里隐藏了房间4,实际上房间4的眼睛也在一起滚动。", "parameters": [ { "name": "Amount", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseDuration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2879,7 +3252,8 @@ window.CustomMethodSearchData = { { "name": "EyeAngle", "type": "custom_method", - "description": "设置眼睛滚动角度 - 设置EyeScroll中眼睛滚动的角度。\n\n图中示例: EyeAngle(1000, 100, \"Linear\")\n\n注意:这里隐藏了房间4,实际上房间4的眼睛也在一起滚动。", + "shortDescription": "设置眼睛滚动角度", + "description": "设置EyeScroll中眼睛滚动的角度。\n\n图中示例: EyeAngle(1000, 100, \"Linear\")\n\n注意:这里隐藏了房间4,实际上房间4的眼睛也在一起滚动。", "parameters": [ { "name": "Angle", @@ -2887,7 +3261,10 @@ window.CustomMethodSearchData = { }, { "name": "EaseDuration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2898,29 +3275,38 @@ window.CustomMethodSearchData = { { "name": "EyesClose", "type": "custom_method", - "description": "闭眼 - 让指定数量的眼睛闭上,对房间 4 的小眼睛没用。\n\n1 为全部闭眼,填 0 没用。", + "shortDescription": "闭眼", + "description": "让指定数量的眼睛闭上,对房间 4 的小眼睛没用。\n\n1 为全部闭眼,填 0 没用。", "parameters": [ { "name": "Amount", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "EyesToggle", "type": "custom_method", - "description": "设置大眼睛 - 随机开关房间内指定数量的眼睛。\n\n1 表示所有眼睛都会被切换,0 表示没有眼睛被切换。\n\n不影响房间 4 的小眼睛。", + "shortDescription": "设置大眼睛", + "description": "随机开关房间内指定数量的眼睛。\n\n1 表示所有眼睛都会被切换,0 表示没有眼睛被切换。\n\n不影响房间 4 的小眼睛。", "parameters": [ { "name": "Amount", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "EyesToggleSmall", "type": "custom_method", - "description": "设置小眼睛 - 切换房间 4 中的小眼睛的开启和关闭。", + "shortDescription": "设置小眼睛", + "description": "切换房间 4 中的小眼睛的开启和关闭。", "parameters": [ { "name": "Open", @@ -2931,26 +3317,31 @@ window.CustomMethodSearchData = { { "name": "SetVerticalShiftSpeed", "type": "custom_method", - "description": "设置眼睛垂直滚动速度 - 使两个房间的眼睛以棋盘格模式移动。\n\n注意:需要先至少调用一次 StareAtMark()\n图中是房间 3 和 4 同时显示的情况。", + "shortDescription": "设置眼睛垂直滚动速度", + "description": "使两个房间的眼睛以棋盘格模式移动。\n\n注意:需要先至少调用一次 StareAtMark()\n图中是房间 3 和 4 同时显示的情况。", "parameters": [ { "name": "Speed", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "MoveArmX", "type": "custom_method", - "description": "移动手X - 移动指定的手的 X 坐标。", + "shortDescription": "移动手X", + "description": "移动指定的手的 X 坐标。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -2963,7 +3354,10 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -2974,15 +3368,16 @@ window.CustomMethodSearchData = { { "name": "MoveArmY", "type": "custom_method", - "description": "移动手Y - 移动指定的手的 Y 坐标。", + "shortDescription": "移动手Y", + "description": "移动指定的手的 Y 坐标。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -2995,7 +3390,10 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -3006,15 +3404,16 @@ window.CustomMethodSearchData = { { "name": "SetArmZ", "type": "custom_method", - "description": "移动手Z - 移动指定的手的 Z 坐标。", + "shortDescription": "移动手Z", + "description": "移动指定的手的 Z 坐标。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -3030,15 +3429,16 @@ window.CustomMethodSearchData = { { "name": "MoveButtonX", "type": "custom_method", + "shortDescription": "", "description": "", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -3051,7 +3451,10 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -3062,15 +3465,16 @@ window.CustomMethodSearchData = { { "name": "MoveButtonY", "type": "custom_method", - "description": "移动按钮 - 跟 SetArmX/Y 一样,但是移动的是按钮。", + "shortDescription": "移动按钮", + "description": "跟 SetArmX/Y 一样,但是移动的是按钮。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -3083,7 +3487,10 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -3094,15 +3501,16 @@ window.CustomMethodSearchData = { { "name": "ToggleNervous", "type": "custom_method", - "description": "设置鸡爪佩奇的手 - 把佩奇的手设置成不同的精灵图。\n需要先使用分配手事件。", + "shortDescription": "设置鸡爪佩奇的手", + "description": "把佩奇的手设置成不同的精灵图。\n需要先使用分配手事件。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -3118,15 +3526,16 @@ window.CustomMethodSearchData = { { "name": "PlayArmAnim", "type": "custom_method", - "description": "播放手动画 - 让指定的手播放指定的动画。\n需要预先使用手分配事件。\n埃德加的手:\npointing, reach, grab, struggle, ungrab, return\n\n佩奇的手:\nstruggle, ungrabbed, scared, ready", + "shortDescription": "播放手动画", + "description": "让指定的手播放指定的动画。\n需要预先使用手分配事件。\n埃德加的手:\npointing, reach, grab, struggle, ungrab, return\n\n佩奇的手:\nstruggle, ungrabbed, scared, ready", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -3142,7 +3551,8 @@ window.CustomMethodSearchData = { { "name": "FlipDialog", "type": "custom_method", - "description": "翻转对话 - 和把角色放在右侧的对话一样,但是可以影响当前对话,", + "shortDescription": "翻转对话", + "description": "和把角色放在右侧的对话一样,但是可以影响当前对话,", "parameters": [ { "name": "Flipped", @@ -3153,15 +3563,16 @@ window.CustomMethodSearchData = { { "name": "ShowButton", "type": "custom_method", - "description": "显示按钮 - 设置指定手的按钮是否显示。", + "shortDescription": "显示按钮", + "description": "设置指定手的按钮是否显示。", "parameters": [ { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } }, { @@ -3177,15 +3588,22 @@ window.CustomMethodSearchData = { { "name": "SetSkySpeed", "type": "custom_method", - "description": "设置天空滚动速度 - 设置天际线主题的滚动速度", + "shortDescription": "设置天空滚动速度", + "description": "设置天际线主题的滚动速度", "parameters": [ { "name": "Speed", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -3196,7 +3614,8 @@ window.CustomMethodSearchData = { { "name": "ToggleGreySky", "type": "custom_method", - "description": "设置灰色天空 - 让天际线主题变灰", + "shortDescription": "设置灰色天空", + "description": "让天际线主题变灰", "parameters": [ { "name": "Enabled", @@ -3207,7 +3626,8 @@ window.CustomMethodSearchData = { { "name": "ToggleSecondSky", "type": "custom_method", - "description": "添加城市剪影 - 在屏幕顶部加一个反向滚动的城市剪影", + "shortDescription": "添加城市剪影", + "description": "在屏幕顶部加一个反向滚动的城市剪影", "parameters": [ { "name": "Enabled", @@ -3218,13 +3638,15 @@ window.CustomMethodSearchData = { { "name": "SetNightMode", "type": "custom_method", - "description": "设为夜晚模式 - 将医院走廊主题设置为夜晚变种", + "shortDescription": "设为夜晚模式", + "description": "将医院走廊主题设置为夜晚变种", "parameters": [] }, { "name": "SetWardMode", "type": "custom_method", - "description": "设置病房昼夜 - 设置科尔病房的昼夜", + "shortDescription": "设置病房昼夜", + "description": "设置科尔病房的昼夜", "parameters": [ { "name": "NightMode", @@ -3235,7 +3657,8 @@ window.CustomMethodSearchData = { { "name": "ToggleLights", "type": "custom_method", - "description": "设置灯光亮度 - 设置科尔病房顶部灯光的亮度", + "shortDescription": "设置灯光亮度", + "description": "设置科尔病房顶部灯光的亮度", "parameters": [ { "name": "Enabled", @@ -3246,7 +3669,8 @@ window.CustomMethodSearchData = { { "name": "ToggleHoodieBoyWardObjects", "type": "custom_method", - "description": "开关科尔病房显示 - 开关科尔病房主题的所有东西,除了 ToogleLights 设置的灯光", + "shortDescription": "开关科尔病房显示", + "description": "开关科尔病房主题的所有东西,除了 ToogleLights 设置的灯光", "parameters": [ { "name": "Enabled", @@ -3257,7 +3681,8 @@ window.CustomMethodSearchData = { { "name": "MoveWindow", "type": "custom_method", - "description": "移动窗口 - 把科尔的文件管理器窗口移动到指定位置", + "shortDescription": "移动窗口", + "description": "把科尔的文件管理器窗口移动到指定位置", "parameters": [ { "name": "TargetX", @@ -3269,7 +3694,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -3280,7 +3708,8 @@ window.CustomMethodSearchData = { { "name": "ScrollWindow", "type": "custom_method", - "description": "滚动窗口 - 上下滚动文件管理器窗口的内容。\n注意:0 为底部,1 为顶部", + "shortDescription": "滚动窗口", + "description": "上下滚动文件管理器窗口的内容。\n注意:0 为底部,1 为顶部", "parameters": [ { "name": "TargetPos", @@ -3288,7 +3717,10 @@ window.CustomMethodSearchData = { }, { "name": "DurationInBeats", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "EaseEnum", @@ -3299,14 +3731,13 @@ window.CustomMethodSearchData = { { "name": "RemoveFiles", "type": "custom_method", - "description": "移除文件 - 移除文件管理器窗口中指定数量的文件。", + "shortDescription": "移除文件", + "description": "移除文件管理器窗口中指定数量的文件。", "parameters": [ { "name": "FilesToRemove", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -3315,14 +3746,13 @@ window.CustomMethodSearchData = { { "name": "ToggleAlert", "type": "custom_method", - "description": "显示警告窗口 - 显示警告窗口,最多可以同时显示两个", + "shortDescription": "显示警告窗口", + "description": "显示警告窗口,最多可以同时显示两个", "parameters": [ { "name": "Box", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3335,14 +3765,13 @@ window.CustomMethodSearchData = { { "name": "PlaceAlertInRoom", "type": "custom_method", - "description": "警告窗口重排序 - 将指定的警告窗口移动到指定房间。", + "shortDescription": "警告窗口重排序", + "description": "将指定的警告窗口移动到指定房间。", "parameters": [ { "name": "Box", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3350,9 +3779,9 @@ window.CustomMethodSearchData = { "name": "RoomID", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0, + "max": 4 } } ] @@ -3360,14 +3789,13 @@ window.CustomMethodSearchData = { { "name": "SetAlertBox", "type": "custom_method", - "description": "设置警告窗口 - 改变指定警告窗口的图标。", + "shortDescription": "设置警告窗口", + "description": "改变指定警告窗口的图标。", "parameters": [ { "name": "Box", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3375,8 +3803,6 @@ window.CustomMethodSearchData = { "name": "Type", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -3385,14 +3811,13 @@ window.CustomMethodSearchData = { { "name": "SetAlertButtons", "type": "custom_method", - "description": "设置警告窗口按钮 - 设置指定警告窗口的按钮是否被按下。\n对于 Mode,0 代表未按下,1 代表按下。\n对于 Type,0 代表右侧图片中的图标,1 代表上面那张图片的图标。", + "shortDescription": "设置警告窗口按钮", + "description": "设置指定警告窗口的按钮是否被按下。\n对于 Mode,0 代表未按下,1 代表按下。\n对于 Type,0 代表右侧图片中的图标,1 代表上面那张图片的图标。", "parameters": [ { "name": "Box", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3400,8 +3825,6 @@ window.CustomMethodSearchData = { "name": "Mode", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3409,8 +3832,6 @@ window.CustomMethodSearchData = { "name": "Type", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -3419,27 +3840,30 @@ window.CustomMethodSearchData = { { "name": "SetAlertWidth", "type": "custom_method", - "description": "设置警告窗口宽度 - 改变指定的警告窗口的宽度。", + "shortDescription": "设置警告窗口宽度", + "description": "改变指定的警告窗口的宽度。", "parameters": [ { "name": "Box", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, { "name": "Width", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "ToggleSwarm", "type": "custom_method", - "description": "开启/关闭图标群 - 开启或关闭图标群。默认生成在房间1的底部。", + "shortDescription": "开启/关闭图标群", + "description": "开启或关闭图标群。默认生成在房间1的底部。", "parameters": [ { "name": "Enabled", @@ -3450,7 +3874,8 @@ window.CustomMethodSearchData = { { "name": "SetSwarmPos", "type": "custom_method", - "description": "移动图标群 - 改变图标群的坐标。\n图中示例: SetSwarmPos(90,10)", + "shortDescription": "移动图标群", + "description": "改变图标群的坐标。\n图中示例: SetSwarmPos(90,10)", "parameters": [ { "name": "UpperYPos", @@ -3465,22 +3890,30 @@ window.CustomMethodSearchData = { { "name": "DropSwarm", "type": "custom_method", - "description": "坠落图标群 - 让图标群向下坠落", + "shortDescription": "坠落图标群", + "description": "让图标群向下坠落", "parameters": [ { "name": "FinalSpeed", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "ToggleIconRain", "type": "custom_method", - "description": "设置图标雨 - 开启/关闭图标雨。", + "shortDescription": "设置图标雨", + "description": "开启/关闭图标雨。", "parameters": [ { "name": "Enabled", @@ -3491,13 +3924,15 @@ window.CustomMethodSearchData = { { "name": "DeactivateIconRain", "type": "custom_method", - "description": "禁用图标雨 - 立即使所有图标雨中的图标向下掉落,并停止生成新的图标。", + "shortDescription": "禁用图标雨", + "description": "立即使所有图标雨中的图标向下掉落,并停止生成新的图标。", "parameters": [] }, { "name": "ToggleIconSpiral", "type": "custom_method", - "description": "设置螺旋图标 - 开启/关闭房间3中的螺旋图标,像 7 - X2 中那样。", + "shortDescription": "设置螺旋图标", + "description": "开启/关闭房间3中的螺旋图标,像 7 - X2 中那样。", "parameters": [ { "name": "Enabled", @@ -3508,19 +3943,22 @@ window.CustomMethodSearchData = { { "name": "MoveSamuraiVaseToBackground", "type": "custom_method", - "description": "隐藏武士病房主题花瓶 - 隐藏武士病房主题中的花瓶。\n实际上是移到了背景后面。", + "shortDescription": "隐藏武士病房主题花瓶", + "description": "隐藏武士病房主题中的花瓶。\n实际上是移到了背景后面。", "parameters": [] }, { "name": "autoplay", "type": "condition", - "description": "只读变量,检查玩家是否开启自动播放。", + "shortDescription": "只读变量,检查玩家是否开启自动播放。", + "description": "", "parameters": [] }, { "name": "atLeastRank", "type": "condition", - "description": "检查当前评价等级是否大于等于给定的等级,忽略+-号,但是S+除外。", + "shortDescription": "检查当前评价等级是否大于等于给定的等级,忽略+-号,但是S+除外。", + "description": "", "parameters": [ { "name": "Rank", @@ -3531,24 +3969,23 @@ window.CustomMethodSearchData = { { "name": "atLeastNPerfects", "type": "condition", - "description": "检查最近 HitsToCheck 个拍子是否为完美判定,如果大于等于 NumberOfPerfects,则判定为 true。\n例如,可以使用 atLeastNPerfects(8, 6) 检查最近八次按拍的完美数是否大于等于6.", + "shortDescription": "检查最近 HitsToCheck 个拍子是否为完美判定,如果大于等于 NumberOfPerfects,则判定为 true。\n例如,可以使用 atLeastNPerfects(8, 6) 检查最近八次按拍的完美数是否大于等于6.", + "description": "", "parameters": [ { "name": "HitsToCheck", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } }, { "name": "NumberOfPerfects", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, - "isInteger": true + "isInteger": true, + "min": 0 } } ] @@ -3556,223 +3993,260 @@ window.CustomMethodSearchData = { { "name": "arePlayerInputsSwapped", "type": "condition", - "description": "双人模式下生效。\n检查玩家是否交换手位置。", + "shortDescription": "双人模式下生效。\n检查玩家是否交换手位置。", + "description": "", "parameters": [] }, { "name": "levelSpeed", "type": "condition", - "description": "只读变量,检查玩家是否加速/减速关卡。\n加速的 Speed 为 1.5,减速的 Speed 为 0.75。", + "shortDescription": "只读变量,检查玩家是否加速/减速关卡。\n加速的 Speed 为 1.5,减速的 Speed 为 0.75。", + "description": "", "parameters": [] }, { "name": "numMistakes", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "numMistakesP1", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "numMistakesP2", "type": "condition", - "description": "只读变量,记录玩家的失误数\n另外,即使在单人模式下,玩家二的失误数也会计入总失误数,请谨慎使用。", + "shortDescription": "只读变量,记录玩家的失误数\n另外,即使在单人模式下,玩家二的失误数也会计入总失误数,请谨慎使用。", + "description": "", "parameters": [] }, { "name": "isZeroOffset", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "isJCI", "type": "condition", - "description": "检查玩家是不是大佬\n等价于 totalOffset == 0 && numMistakes == 0 && autoplay == false\n即总偏移帧为 0 且失误数为 0 且未启用自动播放\n也就是说,任意一个条件未满足都会返回 false。", + "shortDescription": "检查玩家是不是大佬\n等价于 totalOffset == 0 && numMistakes == 0 && autoplay == false\n即总偏移帧为 0 且失误数为 0 且未启用自动播放\n也就是说,任意一个条件未满足都会返回 false。", + "description": "", "parameters": [] }, { "name": "hitmarginMultiplier", "type": "condition", - "description": "浮点可写变量,将关卡的失误评级数乘以该变量。\n默认为 1。", + "shortDescription": "浮点可写变量,将关卡的失误评级数乘以该变量。\n默认为 1。", + "description": "", "parameters": [] }, { "name": "subdivisionMissWeight", "type": "condition", - "description": "浮点可写变量,设置细分拍子的失误权重。\n默认为 0。", + "shortDescription": "浮点可写变量,设置细分拍子的失误权重。\n默认为 0。", + "description": "", "parameters": [] }, { "name": "crotchets", "type": "condition", - "description": "整型只读变量,当前每小节节拍数。", + "shortDescription": "整型只读变量,当前每小节节拍数。", + "description": "", "parameters": [] }, { "name": "barNumber", "type": "condition", - "description": "整型只读变量,当前小节数。", + "shortDescription": "整型只读变量,当前小节数。", + "description": "", "parameters": [] }, { "name": "beatNumber", "type": "condition", - "description": "整型只读变量,当前节拍数,向下取整。", + "shortDescription": "整型只读变量,当前节拍数,向下取整。", + "description": "", "parameters": [] }, { "name": "beatNumberFloat", "type": "condition", - "description": "浮点只读变量,当前节拍数。", + "shortDescription": "浮点只读变量,当前节拍数。", + "description": "", "parameters": [] }, { "name": "editorVersion", "type": "condition", - "description": "整型只读变量,当前编辑器的版本。", + "shortDescription": "整型只读变量,当前编辑器的版本。", + "description": "", "parameters": [] }, { "name": "inEditor", "type": "condition", - "description": "布尔只读变量,检查关卡是否在编辑器内播放。", + "shortDescription": "布尔只读变量,检查关卡是否在编辑器内播放。", + "description": "", "parameters": [] }, { "name": "platform", "type": "condition", - "description": "检查游戏是否在指定系统上运行。\n目前仅支持Mac和Windows,如果要检测Linux系统,则需要添加两个条件并且全部设为假(红色框) - 玩家变量", + "shortDescription": "检查游戏是否在指定系统上运行。\n目前仅支持Mac和Windows,如果要检测Linux系统,则需要添加两个条件并且全部设为假(红色框)", + "description": "玩家变量", "parameters": [] }, { "name": "buttonPressCount", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "lateOffset", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "lateOffsetP1", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "lateOffsetP2", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "earlyOffset", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "earlyOffsetP1", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "earlyOffsetP2", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "totalOffset", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "totalOffsetP1", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "totalOffsetP2", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "lastOffsetP1", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "lastOffsetP2", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "hitMarginP1", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "hitMarginP2", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "detailedLevelResults", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "bpm", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "numEarlyHits", "type": "condition", - "description": "numLateHits - numPerfectHits ", + "shortDescription": "numLateHits ", + "description": "numPerfectHits ", "parameters": [] }, { "name": "numMisses", "type": "condition", - "description": "numMistakes ", + "shortDescription": "numMistakes ", + "description": "", "parameters": [] }, { "name": "XPress", "type": "condition", + "shortDescription": "", "description": "", "parameters": [] }, { "name": "XRelease", "type": "condition", - "description": "XIsPressed - 特别地,上表中后三行变量名中的X特指按键名,使用时将X替换为对应的按键名,分别为p1(玩家1)、p2(玩家2)、anyPlayer(任意玩家)、up(上)、down(下)、left(左)、right(右)", + "shortDescription": "XIsPressed ", + "description": "特别地,上表中后三行变量名中的X特指按键名,使用时将X替换为对应的按键名,分别为p1(玩家1)、p2(玩家2)、anyPlayer(任意玩家)、up(上)、down(下)、left(左)、right(右)", "parameters": [] }, { "name": "passedLevel", "type": "condition", - "description": "检查玩家的存档1中是否通关了指定关卡\n类似的,这不会返回一个布尔变量\n获取关卡ID的最新方法是检查你自己的存档。在游戏的安装目录(在Steam上,右键点击导航栏中的游戏,在“管理”下点击“浏览本地文件...”;进入安装目录后,在User文件夹下,会有(最多3个)slot#.rdsave文件——slot0.rdsave是第一个存档,slot1是第二个,slot2是第三个。打开其中一个文件(最好是那个玩过最多故事模式关卡的存档),然后查找 Level_[关卡 ID]_rank 字符串。\n例如 “Level_BeansHopper_rank”,其中 BeansHopper 是用于此条件检查武士豆子跳是否通过的关卡 ID\n有些 ID 可能不明确(例如 Lesmis 指 3-X),所以在游戏关闭时,可以编辑存档文件来修改某个关卡的等级(如果在修改时游戏是开启的,修改会被覆盖)。例如,将 “Level", + "shortDescription": "检查玩家的存档1中是否通关了指定关卡\n类似的,这不会返回一个布尔变量\n获取关卡ID的最新方法是检查你自己的存档。在游戏的安装目录(在Steam上,右键点击导航栏中的游戏,在“管理”下点击“浏览本地文件...”;进入安装目录后,在User文件夹下,会有(最多3个)slot#.rdsave文件——slot0.rdsave是第一个存档,slot1是第二个,slot2是第三个。打开其中一个文件(最好是那个玩过最多故事模式关卡的存档),然后查找 Level_[关卡 ID]_rank 字符串。\n例如 “Level_BeansHopper_rank”,其中 BeansHopper 是用于此条件检查武士豆子跳是否通过的关卡 ID\n有些 ID 可能不明确(例如 Lesmis 指 3-X),所以在游戏关闭时,可以编辑存档文件来修改某个关卡的等级(如果在修改时游戏是开启的,修改会被覆盖)。例如,将 “Level_Lesmis_rank\":\"S” 改为 “Level_Lesmis_rank\":\"NotFinished”,可以将 3-X 的状态从完美改为未完成(请不要用这来作弊)", + "description": "", "parameters": [ { "name": "level", @@ -3784,25 +4258,29 @@ window.CustomMethodSearchData = { { "name": "narration", "type": "condition", - "description": "检查玩家是否启用无障碍朗读功能\n类似paigeLeaves,这也不是个布尔变量\n现在可以直接用全局条件了。", + "shortDescription": "检查玩家是否启用无障碍朗读功能\n类似paigeLeaves,这也不是个布尔变量\n现在可以直接用全局条件了。", + "description": "", "parameters": [] }, { "name": "isScrubbing", "type": "condition", - "description": "只读布尔变量,如果玩家在编辑器中将播放进度拖到比事件当前位置更远的进度,则返回 true。如果事件按“正常”方式到达,则返回 false,并且在编辑器外永远不会为 true。", + "shortDescription": "只读布尔变量,如果玩家在编辑器中将播放进度拖到比事件当前位置更远的进度,则返回 true。如果事件按“正常”方式到达,则返回 false,并且在编辑器外永远不会为 true。", + "description": "", "parameters": [] }, { "name": "audioVolume", "type": "condition", - "description": "当前音频音量,变化范围为 [0,1],可以用于制作音频响应视效 - 可写变量", + "shortDescription": "当前音频音量,变化范围为 [0,1],可以用于制作音频响应视效", + "description": "可写变量", "parameters": [] }, { "name": "setDialogueType", "type": "ink", - "description": "设置对话类型 - 枚举列表:\"Passive\", \"Active\", \"Accelerable\"\nPassive: 正常显示对话事件\nActive: 类似 激活对话按键并等待\nAccelerable: 类似 激活对话按键并立即跳转", + "shortDescription": "设置对话类型", + "description": "枚举列表:\"Passive\", \"Active\", \"Accelerable\"\nPassive: 正常显示对话事件\nActive: 类似 激活对话按键并等待\nAccelerable: 类似 激活对话按键并立即跳转", "parameters": [ { "name": "EventType", @@ -3814,7 +4292,8 @@ window.CustomMethodSearchData = { { "name": "runEvent", "type": "ink", - "description": "运行事件 - 立即运行指定标签中的事件。", + "shortDescription": "运行事件", + "description": "立即运行指定标签中的事件。", "parameters": [ { "name": "TagName", @@ -3825,77 +4304,93 @@ window.CustomMethodSearchData = { { "name": "hidePanel", "type": "ink", - "description": "隐藏对话框 - 隐藏对话框,在指定时间后再次弹出并显示下一句对话。\n例如:\n[[ink:this]]\nDOTHIS{setDialogueType(Active)}\nSamurai_Happy: 有些日子过得可真开心啊。\nDOTHIS{hidePanel(10)}\nPaige: 的确。\n在武士说完后,对话框被隐藏,过十秒后对话框再次显示,佩奇说的确。", + "shortDescription": "隐藏对话框", + "description": "隐藏对话框,在指定时间后再次弹出并显示下一句对话。\n例如:\n[[ink:this]]\nDOTHIS{setDialogueType(Active)}\nSamurai_Happy: 有些日子过得可真开心啊。\nDOTHIS{hidePanel(10)}\nPaige: 的确。\n在武士说完后,对话框被隐藏,过十秒后对话框再次显示,佩奇说的确。", "parameters": [ { "name": "TimeInSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "wait", "type": "ink", - "description": "等待 - 将对话暂停指定的时间,随后继续下一行对话\n和 hidePanel 类似,但不会隐藏对话框。", + "shortDescription": "等待", + "description": "将对话暂停指定的时间,随后继续下一行对话\n和 hidePanel 类似,但不会隐藏对话框。", "parameters": [ { "name": "TimeInSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "stopMusic", "type": "ink", - "description": "停止音乐 - 在指定时间内停止当前播放的音乐。", + "shortDescription": "停止音乐", + "description": "在指定时间内停止当前播放的音乐。", "parameters": [ { "name": "TimeInSeconds", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "forceNarrateSpeakerName", "type": "ink", - "description": "强制朗读角色名称 - 仅当启用朗读时生效。\n一般来讲,当一个角色连着说两行或多行对话时,无障碍朗读只会朗读一次角色名\n调用该事件后,无障碍朗读无论如何都会朗读角色名。", + "shortDescription": "强制朗读角色名称", + "description": "仅当启用朗读时生效。\n一般来讲,当一个角色连着说两行或多行对话时,无障碍朗读只会朗读一次角色名\n调用该事件后,无障碍朗读无论如何都会朗读角色名。", "parameters": [] }, { "name": "flash", "type": "ink", - "description": "闪烁 - 让屏幕闪一次。", + "shortDescription": "闪烁", + "description": "让屏幕闪一次。", "parameters": [] }, { "name": "shakeCam", "type": "ink", - "description": "震动摄像头 - 跟默认的屏幕震动事件效果一样。", + "shortDescription": "震动摄像头", + "description": "跟默认的屏幕震动事件效果一样。", "parameters": [] }, { "name": "fadeIn", "type": "ink", - "description": "淡入 - 让屏幕从黑色淡入。", + "shortDescription": "淡入", + "description": "让屏幕从黑色淡入。", "parameters": [] }, { "name": "fadeOut", "type": "ink", - "description": "淡出 - 让屏幕淡出到黑色。", + "shortDescription": "淡出", + "description": "让屏幕淡出到黑色。", "parameters": [] }, { "name": "setColor", "type": "ink", - "description": "设置文本颜色 - 设置文本颜色。", + "shortDescription": "设置文本颜色", + "description": "设置文本颜色。", "parameters": [ { "name": "Red", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3903,8 +4398,6 @@ window.CustomMethodSearchData = { "name": "Green", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3912,8 +4405,6 @@ window.CustomMethodSearchData = { "name": "Blue", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } }, @@ -3921,8 +4412,6 @@ window.CustomMethodSearchData = { "name": "Alpha", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -3931,25 +4420,28 @@ window.CustomMethodSearchData = { { "name": "setSpeed", "type": "ink", - "description": "设置文本速度 - 设置文本速度。默认值为 1。", + "shortDescription": "设置文本速度", + "description": "设置文本速度。默认值为 1。", "parameters": [ { "name": "SpeedPerCharacter", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } } ] }, { "name": "setPanelSide", "type": "ink", + "shortDescription": "", "description": "", "parameters": [ { "name": "Side", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -3958,14 +4450,13 @@ window.CustomMethodSearchData = { { "name": "setAlignment", "type": "ink", - "description": "设置对齐方式 - 设置文本在对话框中的位置。\n0:靠左顶端对齐(默认)\n1:居中顶端对齐\n2:靠右顶端对齐\n3:靠左居中对齐\n4:居中对齐\n5:靠右居中对齐\n6:靠左底端对齐\n7:居中底端对齐\n8:靠右底端对齐\n其他数字没用。\n\n注意:由于中文模式下显示对话事件只会显示两行,所以底端对齐类不会正常显示。", + "shortDescription": "设置对齐方式", + "description": "设置文本在对话框中的位置。\n0:靠左顶端对齐(默认)\n1:居中顶端对齐\n2:靠右顶端对齐\n3:靠左居中对齐\n4:居中对齐\n5:靠右居中对齐\n6:靠左底端对齐\n7:居中底端对齐\n8:靠右底端对齐\n其他数字没用。\n\n注意:由于中文模式下显示对话事件只会显示两行,所以底端对齐类不会正常显示。", "parameters": [ { "name": "Location", "type": "number", "numericRange": { - "min": -2147483648, - "max": 2147483647, "isInteger": true } } @@ -3974,7 +4465,8 @@ window.CustomMethodSearchData = { { "name": "moveCam_ease", "type": "ink", - "description": "绝对移动真实摄像头 - 移动房间 1 的真实摄像头。\n类似 RoomID 为 0 的()=>trueCameraMove()", + "shortDescription": "绝对移动真实摄像头", + "description": "移动房间 1 的真实摄像头。\n类似 RoomID 为 0 的()=>trueCameraMove()", "parameters": [ { "name": "XPos", @@ -3986,7 +4478,10 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Ease", @@ -3998,7 +4493,8 @@ window.CustomMethodSearchData = { { "name": "translateCam_ease", "type": "ink", - "description": "相对移动摄真实像头 - 类似 moveCam_ease,但是是相对运动。", + "shortDescription": "相对移动摄真实像头", + "description": "类似 moveCam_ease,但是是相对运动。", "parameters": [ { "name": "XPos", @@ -4010,7 +4506,10 @@ window.CustomMethodSearchData = { }, { "name": "Duration", - "type": "number" + "type": "number", + "numericRange": { + "min": 0 + } }, { "name": "Ease", @@ -4022,127 +4521,155 @@ window.CustomMethodSearchData = { { "name": "Injury", "type": "custom_class", + "shortDescription": "Intimate(1-2 亲密)", "description": "添加棒球场的动画以及棒球。", "parameters": [] }, { "name": "Intimate", "type": "custom_class", + "shortDescription": "OrientalTechno(1-1 东方电舞曲)", "description": "1-2 亲密原版关卡。(就像这关,有些内置关卡实际上就是用自定义类写的)", "parameters": [] }, { "name": "OrientalTechno", "type": "custom_class", + "shortDescription": "OrientalDubstep(1-1N 东方回响贝斯)", "description": "原版关卡,同上", "parameters": [] }, { "name": "OrientalDubstep", "type": "custom_class", + "shortDescription": "LuckyBreak(5-1 路吉摔了一跤)", "description": "使房间 1 在 6 小节出现漂浮之心,但不会像主题那样修改背景颜色;2 号房间为 1-1 开头出现的武士病房,可以使用 OpenDoors 方法来开启病房中的大门。\n包含硬编码的震动和闪烁效果。", "parameters": [] }, { "name": "LuckyBreak", "type": "custom_class", + "shortDescription": "Rollerdisco (4-1N 轮滑迪斯科震颤)", "description": "就像\"Injury\"自定义类一样,但是启用了背景中的计分板和一些其他的自定义方法。", "parameters": [] }, { "name": "Rollerdisco", "type": "custom_class", + "shortDescription": "Unbeatable (X-WOT Worn Out Tapes)", "description": "使用略微不同的沙漠主题。", "parameters": [] }, { "name": "Unbeatable", "type": "custom_class", + "shortDescription": "VividStasis (X-FTS 恋恋群星)", "description": "关卡中需要五条以上轨道。把心脏改成X-WOT中的样式。", "parameters": [] }, { "name": "VividStasis", "type": "custom_class", + "shortDescription": "Unreachable(2-2N)", "description": "强制把S+评级文字改成“无 限 暴 打”,解锁VRankHacky()自定义方法。", "parameters": [] }, { "name": "Unreachable", "type": "custom_class", + "shortDescription": "PaigesReckoning (6-X Boss战)", "description": "启用另一个版本的太空主题,轨道音频响应以及其他自定义方法。", "parameters": [] }, { "name": "PaigesReckoning", "type": "custom_class", + "shortDescription": "Halloween", "description": "启用大眼睛和小眼睛以及你可以在关卡中使用的一些 Boss 关机制。", "parameters": [] }, + { + "name": "Halloween", + "type": "custom_class", + "shortDescription": "其他自定义类详见自定义方法工作表末尾的自定义类方法", + "description": "将心脏改成万圣节版的南瓜。\n此自定义类已损坏。", + "parameters": [] + }, { "name": "firstBeatBehavior", "type": "mod", - "description": "第一拍事件行为 - \"RunNormally\" (默认值) - 第一小节第一拍的事件按原来时间运行。\n\"RunEventsOnPrebar\" - 第一小节第一拍的事件在前一小节运行,基本上就是在关卡完全开始之前,类似于第零拍。", + "shortDescription": "第一拍事件行为", + "description": "\"RunNormally\" (默认值) - 第一小节第一拍的事件按原来时间运行。\n\"RunEventsOnPrebar\" - 第一小节第一拍的事件在前一小节运行,基本上就是在关卡完全开始之前,类似于第零拍。", "parameters": [] }, { "name": "classicHitParticles", "type": "mod", - "description": "经典按拍特效 - 手术模组,或者自定义方法,使按拍特效粒子不随轨道的移动而移动或变化大小。", + "shortDescription": "经典按拍特效", + "description": "手术模组,或者自定义方法,使按拍特效粒子不随轨道的移动而移动或变化大小。", "parameters": [] }, { "name": "gentleBassDrop", "type": "mod", - "description": "柔和重低音震动 - 手术模组,或者自定义方法,让重低音震动更柔和。\n\n注意:需要搭配\"oldBassDrop\"(见下文)", + "shortDescription": "柔和重低音震动", + "description": "手术模组,或者自定义方法,让重低音震动更柔和。\n\n注意:需要搭配\"oldBassDrop\"(见下文)", "parameters": [] }, { "name": "oldBassDrop", "type": "mod", - "description": "传统重低音震动 - 手术模组,或者自定义方法,使用以前的重低音震动动画,会使重低音震动事件中的强度选项没用。", + "shortDescription": "传统重低音震动", + "description": "手术模组,或者自定义方法,使用以前的重低音震动动画,会使重低音震动事件中的强度选项没用。", "parameters": [] }, { "name": "adaptRowsToRoomHeight", "type": "mod", - "description": "轨道间距适应房间高度 - 当与“排列显示房间”事件一起使用时,使不在自定义位置的轨道在房间的高度内均匀分布。覆盖 verticalRowSpacing", + "shortDescription": "轨道间距适应房间高度", + "description": "当与“排列显示房间”事件一起使用时,使不在自定义位置的轨道在房间的高度内均匀分布。覆盖 verticalRowSpacing", "parameters": [] }, { "name": "noShadowRowWeighting", "type": "mod", - "description": "禁止自动降低模仿轨道权重 - 启用后,模仿轨道与被模仿轨道不会随其降低失误权重", + "shortDescription": "禁止自动降低模仿轨道权重", + "description": "启用后,模仿轨道与被模仿轨道不会随其降低失误权重", "parameters": [] }, { "name": "runTaggedEventsWhileScrubbing", "type": "mod", - "description": "中途播放时强制播放标签事件 - 编辑器从中途播放时默认不会运行带有标签的事件,使用此mod会强制编辑器播放该事件", + "shortDescription": "中途播放时强制播放标签事件", + "description": "编辑器从中途播放时默认不会运行带有标签的事件,使用此mod会强制编辑器播放该事件", "parameters": [] }, { "name": "startImmediately", "type": "mod", - "description": "立即开始关卡 - 手术模组,跳过关卡前“按空格键开始”的部分,关卡会立即开始", + "shortDescription": "立即开始关卡", + "description": "手术模组,跳过关卡前“按空格键开始”的部分,关卡会立即开始", "parameters": [] }, { "name": "noPopHitstrips", "type": "mod", - "description": "移除空按打击条 - 隐藏没有拍子时空按产生的蓝色打击条", + "shortDescription": "移除空按打击条", + "description": "隐藏没有拍子时空按产生的蓝色打击条", "parameters": [] }, { "name": "showHitstripOnlyOnActiveBeats", "type": "mod", - "description": "限制击拍条出现 - 仅模组生效,仅在击拍的轨道上显示击拍条", + "shortDescription": "限制击拍条出现", + "description": "仅模组生效,仅在击拍的轨道上显示击拍条", "parameters": [] }, { "name": "skippable", "type": "mod", - "description": "允许跳过关卡 - 手术模组,也能用做自定义方法,暂停菜单出现“跳过”选项,将立即结束关卡并获得S评级", + "shortDescription": "允许跳过关卡", + "description": "手术模组,也能用做自定义方法,暂停菜单出现“跳过”选项,将立即结束关卡并获得S评级", "parameters": [] } ] diff --git a/script/custommethod-search.js b/script/custommethod-search.js index be54208..e4f5b4d 100644 --- a/script/custommethod-search.js +++ b/script/custommethod-search.js @@ -50,55 +50,56 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } } class Method { - constructor(name, type, description) { + constructor(name, type, shortDescription, description) { this.name = name; this.type = type; + this.shortDescription = shortDescription; this.description = description; } } class Mod extends Method { - constructor(name, description) { - super(name, MethodType.Mod, description); + constructor(name, shortDescription, description) { + super(name, MethodType.Mod, shortDescription, description); } } class Surgery extends Method { - constructor(name, description) { - super(name, MethodType.Surgery, description); + constructor(name, shortDescription, description) { + super(name, MethodType.Surgery, shortDescription, description); } } class CommentMethod extends Method { - constructor(name, description, parameters) { - super(name, MethodType.Comment, description); + constructor(name, shortDescription, description, parameters) { + super(name, MethodType.Comment, shortDescription, description); this.parameters = parameters; } } class InkMethod extends Method { - constructor(name, description, parameters) { - super(name, MethodType.Ink, description); + constructor(name, shortDescription, description, parameters) { + super(name, MethodType.Ink, shortDescription, description); this.parameters = parameters; } } class CustomMethods extends Method { - constructor(name, description, parameters) { - super(name, MethodType.CustomMethod, description); + constructor(name, shortDescription, description, parameters) { + super(name, MethodType.CustomMethod, shortDescription, description); this.parameters = parameters; } } class VariableMethod extends Method { - constructor(name, description, parameters) { - super(name, MethodType.Variable, description); + constructor(name, shortDescription, description, parameters) { + super(name, MethodType.Variable, shortDescription, description); this.parameters = parameters; } } class ConditionMethod extends Method { - constructor(name, description, parameters) { - super(name, MethodType.Condition, description); + constructor(name, shortDescription, description, parameters) { + super(name, MethodType.Condition, shortDescription, description); this.parameters = parameters; } } class CustomClassMethod extends Method { - constructor(name, description) { - super(name, MethodType.CustomClass, description); + constructor(name, shortDescription, description) { + super(name, MethodType.CustomClass, shortDescription, description); } } function editDistance(a, b, caseSensitive = true) { @@ -131,41 +132,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge var _a; return (_a = method.parameters) !== null && _a !== void 0 ? _a : []; } + // 全局策略:字符串写法、数字/布尔默认的常量/表达式状态 + const strategies = { + string: "prefix", + number: "constant", + boolean: "constant", + }; // --------------------------------------------------------------------- - // 数据:可直接在此编辑,或通过 window.CustomMethodSearch.setMethods(...) 覆盖 + // 外置数据 hydrate(script/custommethod-data.js) // --------------------------------------------------------------------- - let methods = [ - new Mod("wobblyLines", "让单发拍子的轨道抖动"), - new Mod("invisibleHeart", "隐藏轨道上的心脏"), - new CustomMethods("ChangeCharacter", "修改某条轨道对应的人物", [ - new Parameter("character", ParameterType.Enum, "Characters"), - new Parameter("row", ParameterType.Number, "轨道编号", undefined, new NumericRange(0, 15, true)), - ]), - new CustomMethods("DisableRowReflections", "开关某个房间的地面反射", [ - new Parameter("room", ParameterType.Number, "房间编号", undefined, new NumericRange(0, 3, true)), - ]), - new CustomMethods("SetRowLength", "设置轨道长度", [ - new Parameter("row", ParameterType.Number, "轨道编号", undefined, new NumericRange(0, 15, true)), - new Parameter("length", ParameterType.Number, "轨道长度", undefined, new NumericRange(1, 7, true)), - ]), - new CommentMethod("trueCameraMove", "移动真实摄像头", [ - new Parameter("x", ParameterType.Number, "目标 X"), - new Parameter("y", ParameterType.Number, "目标 Y"), - new Parameter("angle", ParameterType.Number, "角度"), - new Parameter("duration", ParameterType.Number, "时长"), - new Parameter("ease", ParameterType.Enum, "缓动类型", "EaseType"), - ]), - new CustomMethods("DemoAllTypes", "演示四种参数控件", [ - new Parameter("text", ParameterType.String, "文本"), - new Parameter("count", ParameterType.Number, "数字"), - new Parameter("enabled", ParameterType.Boolean, "开关"), - new Parameter("character", ParameterType.Enum, "角色", "Characters"), - new Parameter("color", ParameterType.Enum, "颜色"), - ]), - ]; - // 合并外置数据(script/custommethod-data.js),同名以内置为准 function hydrateMethod(raw) { - var _a, _b, _c, _d, _e, _f, _g, _h; + var _a, _b, _c, _d; + const shortDescription = (_b = (_a = raw.shortDescription) !== null && _a !== void 0 ? _a : raw.description) !== null && _b !== void 0 ? _b : ""; + const description = (_d = (_c = raw.description) !== null && _c !== void 0 ? _c : raw.shortDescription) !== null && _d !== void 0 ? _d : ""; const parameters = Array.isArray(raw.parameters) ? raw.parameters.map((item) => { var _a, _b; @@ -175,16 +154,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }) : []; switch (raw.type) { - case MethodType.Mod: return new Mod(raw.name, (_a = raw.description) !== null && _a !== void 0 ? _a : ""); - case MethodType.Surgery: return new Surgery(raw.name, (_b = raw.description) !== null && _b !== void 0 ? _b : ""); - case MethodType.Comment: return new CommentMethod(raw.name, (_c = raw.description) !== null && _c !== void 0 ? _c : "", parameters); - case MethodType.Ink: return new InkMethod(raw.name, (_d = raw.description) !== null && _d !== void 0 ? _d : "", parameters); - case MethodType.Variable: return new VariableMethod(raw.name, (_e = raw.description) !== null && _e !== void 0 ? _e : "", parameters); - case MethodType.Condition: return new ConditionMethod(raw.name, (_f = raw.description) !== null && _f !== void 0 ? _f : "", parameters); - case MethodType.CustomClass: return new CustomClassMethod(raw.name, (_g = raw.description) !== null && _g !== void 0 ? _g : ""); - default: return new CustomMethods(raw.name, (_h = raw.description) !== null && _h !== void 0 ? _h : "", parameters); + case MethodType.Mod: return new Mod(raw.name, shortDescription, description); + case MethodType.Surgery: return new Surgery(raw.name, shortDescription, description); + case MethodType.Comment: return new CommentMethod(raw.name, shortDescription, description, parameters); + case MethodType.Ink: return new InkMethod(raw.name, shortDescription, description, parameters); + case MethodType.Variable: return new VariableMethod(raw.name, shortDescription, description, parameters); + case MethodType.Condition: return new ConditionMethod(raw.name, shortDescription, description, parameters); + case MethodType.CustomClass: return new CustomClassMethod(raw.name, shortDescription, description); + default: return new CustomMethods(raw.name, shortDescription, description, parameters); } } + let methods = []; function loadExternalData() { const data = window.CustomMethodSearchData; if (!data) @@ -247,7 +227,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge .map((item) => item.method); } // --------------------------------------------------------------------- - // DOM 构建 + // DOM 工具 // --------------------------------------------------------------------- function el(tag, className) { const node = document.createElement(tag); @@ -256,27 +236,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge return node; } function resolveEnumOptions(parameter) { - if (parameter.enumType && enumTypeMap[parameter.enumType]) { + if (parameter.enumType && enumTypeMap[parameter.enumType]) return enumTypeMap[parameter.enumType]; - } - // 兼容把枚举类型名写在 description 的情况 - if (enumTypeMap[parameter.description]) { + if (enumTypeMap[parameter.description]) return enumTypeMap[parameter.description]; - } - if (enumTypeMap[parameter.name]) { + if (enumTypeMap[parameter.name]) return enumTypeMap[parameter.name]; - } return []; } - // 布尔值可用 true/false,也可用布尔变量 b0~b9 + // 布尔可用 true/false,或布尔变量 b0~b9 const BOOLEAN_OPTIONS = ["true", "false"]; for (let i = 0; i < 10; i++) { BOOLEAN_OPTIONS.push("b" + i); } - function isNumberVariable(value) { - // 数字位置允许的变量:i0~i9(整型)、f0~f9(浮点)、b0~b9(布尔) - return /^[ifb][0-9]$/.test(value); - } function makeCombo(parameter, options, onChange) { const combo = el("span", "cm-combo"); const input = el("input", "cm-input cm-combo-input"); @@ -316,112 +288,177 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } list.hidden = false; } - input.addEventListener("input", () => { - populate(); - onChange(); - }); + input.addEventListener("input", () => { populate(); onChange(); }); input.addEventListener("focus", populate); - input.addEventListener("blur", () => { - window.setTimeout(() => { list.hidden = true; }, 120); - }); + input.addEventListener("blur", () => { window.setTimeout(() => { list.hidden = true; }, 120); }); combo.appendChild(input); combo.appendChild(list); return combo; } - function makeControl(parameter, onChange) { + function makeModeToggle(initial, onChange) { + const button = el("button", "cm-mode"); + button.type = "button"; + let mode = initial; + const render = () => { + button.textContent = mode === "expression" ? "表达式" : "常量"; + button.title = "切换 常量 / 表达式"; + button.classList.toggle("is-expression", mode === "expression"); + }; + render(); + button.addEventListener("click", (event) => { + event.preventDefault(); + mode = mode === "expression" ? "constant" : "expression"; + render(); + onChange(); + }); + return { el: button, get: () => mode }; + } + function stringValue(value) { + if (value.length === 0) + return "<文本>"; + return strategies.string === "quote" ? `"${value}"` : `str:${value}`; + } + function makeField(parameter, onChange) { switch (parameter.type) { case ParameterType.Boolean: { - return makeCombo(parameter, BOOLEAN_OPTIONS, onChange); - } - case ParameterType.Enum: { - // 可输入的下拉框:输入时用编辑距离筛选候选项 - return makeCombo(parameter, resolveEnumOptions(parameter), onChange); + const wrap = el("span", "cm-field"); + const checkbox = el("input", "cm-input cm-check"); + checkbox.type = "checkbox"; + checkbox.addEventListener("change", onChange); + const combo = makeCombo(parameter, BOOLEAN_OPTIONS, onChange); + const comboInput = combo.querySelector("input"); + let mode = strategies.boolean; + const toggle = makeModeToggle(strategies.boolean, () => { + mode = toggle.get(); + applyMode(); + onChange(); + }); + function applyMode() { + const expression = mode === "expression"; + checkbox.hidden = expression; + combo.hidden = !expression; + } + applyMode(); + wrap.appendChild(toggle.el); + wrap.appendChild(checkbox); + wrap.appendChild(combo); + return { + el: wrap, + read: () => { + if (mode === "constant") { + return { text: checkbox.checked ? "true" : "false", valid: true, invalid: false }; + } + const value = comboInput.value.trim(); + return value.length > 0 + ? { text: value, valid: true, invalid: false } + : { text: "<布尔>", valid: false, invalid: true }; + }, + }; } case ParameterType.Number: { - // 普通输入框,合法性由 readParameter 校验(非数字标红) - const number = el("input", "cm-input"); - number.type = "text"; - number.inputMode = "decimal"; - number.placeholder = parameter.name; - number.addEventListener("input", onChange); - return number; + const wrap = el("span", "cm-field"); + const input = el("input", "cm-input"); + input.type = "text"; + input.inputMode = "decimal"; + input.placeholder = parameter.name; + input.addEventListener("input", onChange); + const mode = makeModeToggle(strategies.number, onChange); + wrap.appendChild(mode.el); + wrap.appendChild(input); + return { + el: wrap, + read: () => { + const value = input.value.trim(); + if (value.length === 0) + return { text: "<数字>", valid: false, invalid: true }; + if (mode.get() === "expression") + return { text: value, valid: true, invalid: false }; + const number = Number(value); + let valid = isFinite(number); + const range = parameter.numericRange; + if (valid && range) { + if (range.isInteger && !Number.isInteger(number)) + valid = false; + if (range.min !== undefined && number < range.min) + valid = false; + if (range.max !== undefined && number > range.max) + valid = false; + } + return { text: value, valid, invalid: !valid }; + }, + }; + } + case ParameterType.Enum: { + const wrap = el("span", "cm-field cm-field-string"); + const open = el("span", "cm-lit"); + const close = el("span", "cm-lit"); + open.textContent = strategies.string === "quote" ? "\"" : "str:"; + close.textContent = strategies.string === "quote" ? "\"" : ""; + const combo = makeCombo(parameter, resolveEnumOptions(parameter), onChange); + const input = combo.querySelector("input"); + wrap.appendChild(open); + wrap.appendChild(combo); + wrap.appendChild(close); + return { + el: wrap, + read: () => { + const value = input.value.trim(); + const options = resolveEnumOptions(parameter); + const valid = options.length > 0 + ? options.some((option) => option.toLowerCase() === value.toLowerCase()) + : value.length > 0; + return { text: stringValue(value), valid, invalid: !valid }; + }, + }; } default: { - const text = el("input", "cm-input"); - text.type = "text"; - text.placeholder = parameter.name; - text.addEventListener("input", onChange); - return text; + const wrap = el("span", "cm-field cm-field-string"); + const open = el("span", "cm-lit"); + const close = el("span", "cm-lit"); + open.textContent = strategies.string === "quote" ? "\"" : "str:"; + close.textContent = strategies.string === "quote" ? "\"" : ""; + const input = el("input", "cm-input"); + input.type = "text"; + input.placeholder = parameter.name; + input.addEventListener("input", onChange); + wrap.appendChild(open); + wrap.appendChild(input); + wrap.appendChild(close); + return { + el: wrap, + read: () => { + const value = input.value.trim(); + return { text: stringValue(value), valid: value.length > 0, invalid: value.length === 0 }; + }, + }; } } } - function readParameter(parameter, control) { - switch (parameter.type) { - case ParameterType.Boolean: { - const input = control.querySelector("input"); - const value = input.value.trim(); - const valid = value === "true" || value === "false" || /^b[0-9]$/.test(value); - return { text: value || "<布尔>", valid, invalid: value.length > 0 && !valid, control }; - } - case ParameterType.Enum: { - const input = control.querySelector("input"); - const value = input.value.trim(); - const options = resolveEnumOptions(parameter); - const valid = options.length > 0 - ? options.some((option) => option.toLowerCase() === value.toLowerCase()) - : value.length > 0; - return { text: value || "<选项>", valid, invalid: value.length > 0 && !valid, control }; - } - case ParameterType.Number: { - const input = control; - const value = input.value.trim(); - if (value.length === 0) { - return { text: "<数字>", valid: false, invalid: false, control }; - } - if (isNumberVariable(value)) { - return { text: value, valid: true, invalid: false, control }; - } - const number = Number(value); - let valid = isFinite(number); - const range = parameter.numericRange; - if (valid && range) { - if (range.isInteger && !Number.isInteger(number)) - valid = false; - if (number < range.min || number > range.max) - valid = false; - } - return { text: value, valid, invalid: !valid, control }; - } - default: { - const input = control; - const value = input.value.trim(); - return { text: value ? `str:${value}` : "<文本>", valid: value.length > 0, invalid: false, control }; - } + function methodSkeleton(method, hasParams) { + switch (method.type) { + case MethodType.Comment: return { prefix: `()=>${method.name}(`, suffix: ")" }; + case MethodType.Ink: return { prefix: `DOTHIS{${method.name}(`, suffix: ")}" }; + case MethodType.Variable: return { prefix: `${method.name} = `, suffix: "" }; + case MethodType.Mod: return { prefix: `"mods": [..., "`, suffix: `"]` }; + case MethodType.CustomClass: return { prefix: `"customClass": "`, suffix: `"` }; + case MethodType.Condition: + return hasParams ? { prefix: `${method.name}(`, suffix: ")" } : { prefix: method.name, suffix: "" }; + case MethodType.Surgery: return { prefix: method.name, suffix: "" }; + default: + return hasParams ? { prefix: `${method.name}(`, suffix: ")" } : { prefix: method.name, suffix: "" }; } } - function stripStringPrefix(text) { - return text.startsWith("str:") ? text.slice(4) : text; - } function formatMethod(method, states) { - const values = states.map((state) => state.text); - const args = values.join(", "); + const args = states.map((state) => state.text).join(", "); switch (method.type) { - case MethodType.Comment: - return `()=>${method.name}(${args})`; - case MethodType.Ink: - return `DOTHIS{${method.name}(${args})}`; - case MethodType.Variable: - return `${method.name} = ${values.length ? stripStringPrefix(values[0]) : ""}`; - case MethodType.Mod: - return `"mods": [..., "${method.name}"]`; - case MethodType.CustomClass: - return `"customClass": "${method.name}"`; - case MethodType.Condition: - return values.length ? `${method.name}(${args})` : method.name; - case MethodType.Surgery: - return method.name; - default: - return values.length ? `${method.name}(${args})` : method.name; + case MethodType.Comment: return `()=>${method.name}(${args})`; + case MethodType.Ink: return `DOTHIS{${method.name}(${args})}`; + case MethodType.Variable: return `${method.name} = ${states.length ? states[0].text : ""}`; + case MethodType.Mod: return `"mods": [..., "${method.name}"]`; + case MethodType.CustomClass: return `"customClass": "${method.name}"`; + case MethodType.Condition: return states.length ? `${method.name}(${args})` : method.name; + case MethodType.Surgery: return method.name; + default: return states.length ? `${method.name}(${args})` : method.name; } } function copyText(text) { @@ -433,7 +470,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } } catch (error) { - // fallthrough to execCommand + // fall through } try { const area = document.createElement("textarea"); @@ -451,19 +488,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } }); } + // --------------------------------------------------------------------- + // 渲染 + // --------------------------------------------------------------------- function renderContainer(container) { if (container.dataset.cmReady === "1") return; container.dataset.cmReady = "1"; - // 优先使用 custommethod.md 里写好的骨架;缺失时再动态生成 + let currentMethod = null; let query = container.querySelector(".cm-query"); let suggest = container.querySelector(".cm-suggest"); let selected = container.querySelector(".cm-selected"); let nameEl = container.querySelector(".cm-name"); - let descEl = container.querySelector(".cm-desc"); - let row = container.querySelector(".cm-row"); + let shortEl = container.querySelector(".cm-short"); + let call = container.querySelector(".cm-call"); let preview = container.querySelector(".cm-preview"); - if (!query || !suggest || !selected || !nameEl || !descEl || !row || !preview) { + let desc = container.querySelector(".cm-desc"); + let options = container.querySelector(".cm-options"); + if (!query || !suggest || !selected || !nameEl || !shortEl || !call || !preview || !desc) { container.textContent = ""; const searchBar = el("div", "cm-search"); query = el("input", "cm-query"); @@ -477,32 +519,68 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge selected.hidden = true; const head = el("div", "cm-head"); nameEl = el("span", "cm-name"); - descEl = el("span", "cm-desc"); + shortEl = el("span", "cm-short"); head.appendChild(nameEl); - head.appendChild(descEl); - row = el("div", "cm-row"); + head.appendChild(shortEl); + call = el("div", "cm-call"); preview = el("code", "cm-preview"); + desc = el("div", "cm-desc"); selected.appendChild(head); - selected.appendChild(row); + selected.appendChild(call); selected.appendChild(preview); + selected.appendChild(desc); container.appendChild(searchBar); container.appendChild(selected); } + // 搜索框下的策略选项 + options = container.querySelector(".cm-options"); + if (!options) { + options = el("div", "cm-options"); + query.parentElement.insertAdjacentElement("afterend", options); + } + if (!options.querySelector(".cm-option-select")) { + const optionsBox = options; + function addOption(label, key, values, current) { + const wrap = el("label", "cm-option"); + const text = el("span", "cm-option-label"); + text.textContent = label; + const select = el("select", "cm-option-select"); + for (const [value, caption] of values) { + const opt = el("option"); + opt.value = value; + opt.textContent = caption; + select.appendChild(opt); + } + select.value = current; + select.addEventListener("change", () => { + strategies[key] = select.value; + if (currentMethod) { + selectMethod(currentMethod); + } + }); + wrap.appendChild(text); + wrap.appendChild(select); + optionsBox.appendChild(wrap); + } + addOption("字符串", "string", [["prefix", "str: 前缀"], ["quote", "引号 \"…\""]], strategies.string); + } const queryEl = query; const suggestEl = suggest; const selectedEl = selected; const nameNode = nameEl; - const descNode = descEl; - const rowEl = row; + const shortNode = shortEl; + const callEl = call; const previewEl = preview; + const descNode = desc; const copyBtn = el("button", "cm-copy"); copyBtn.type = "button"; copyBtn.textContent = "复制"; copyBtn.hidden = true; - copyBtn.title = "复制生成的调用代码"; + copyBtn.title = "复制生成的代码"; selectedEl.appendChild(copyBtn); copyBtn.addEventListener("click", () => { - copyText(previewEl.textContent).then((ok) => { + var _a; + copyText((_a = previewEl.textContent) !== null && _a !== void 0 ? _a : "").then((ok) => { copyBtn.textContent = ok ? "已复制" : "复制失败"; window.setTimeout(() => { copyBtn.textContent = "复制"; }, 1200); }); @@ -511,51 +589,61 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge suggestEl.textContent = ""; } function selectMethod(method) { + currentMethod = method; clearSuggest(); queryEl.value = method.name; selectedEl.hidden = false; nameNode.textContent = method.name; - descNode.textContent = method.description; - rowEl.textContent = ""; + shortNode.textContent = method.shortDescription || ""; + descNode.textContent = method.description || ""; + callEl.textContent = ""; previewEl.textContent = ""; copyBtn.hidden = true; const parameters = parametersOf(method); - const controls = []; + const fields = []; function updatePreview() { - const states = controls.map((item) => readParameter(item.parameter, item.control)); - states.forEach((state) => state.control.classList.toggle("cm-invalid", state.invalid)); + const states = fields.map((field) => field.read()); + fields.forEach((field, i) => field.el.classList.toggle("cm-invalid", states[i].invalid)); previewEl.textContent = formatMethod(method, states); copyBtn.hidden = !states.every((state) => state.valid); } + const skeleton = methodSkeleton(method, parameters.length > 0); + const code = el("code", "cm-code"); + const prefix = el("span", "cm-lit"); + prefix.textContent = skeleton.prefix; + code.appendChild(prefix); + parameters.forEach((parameter, index) => { + if (index > 0) { + const sep = el("span", "cm-lit"); + sep.textContent = ", "; + code.appendChild(sep); + } + const field = makeField(parameter, updatePreview); + field.el.title = parameter.description; + code.appendChild(field.el); + fields.push(field); + }); + if (skeleton.suffix) { + const suffix = el("span", "cm-lit"); + suffix.textContent = skeleton.suffix; + code.appendChild(suffix); + } + callEl.appendChild(code); if (parameters.length === 0) { const empty = el("span", "cm-empty"); - empty.textContent = "该方法没有参数"; - rowEl.appendChild(empty); - updatePreview(); - return; - } - for (const parameter of parameters) { - const field = el("label", "cm-param"); - field.title = parameter.description; - const label = el("span", "cm-param-name"); - label.textContent = parameter.name; - const control = makeControl(parameter, updatePreview); - field.appendChild(label); - field.appendChild(control); - rowEl.appendChild(field); - controls.push({ parameter, control }); + empty.textContent = "(无参数)"; + callEl.appendChild(empty); } updatePreview(); } function updateSuggestions() { clearSuggest(); - const matches = searchMethods(queryEl.value); - for (const method of matches) { + for (const method of searchMethods(queryEl.value)) { const item = el("li", "cm-suggest-item"); const nameSpan = el("span", "cm-suggest-name"); nameSpan.textContent = method.name; const descSpan = el("span", "cm-suggest-desc"); - descSpan.textContent = method.description; + descSpan.textContent = method.shortDescription || method.description; item.appendChild(nameSpan); item.appendChild(descSpan); item.addEventListener("mousedown", (event) => { @@ -578,8 +666,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } } function initAll() { - const containers = document.querySelectorAll(".custommethods-search"); - containers.forEach((container) => renderContainer(container)); + document.querySelectorAll(".custommethods-search").forEach((container) => renderContainer(container)); } function register() { const docsify = window.$docsify; @@ -599,11 +686,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge search: searchMethods, editDistance, renderAll: initAll, + strategies, getMethods: () => methods, - setMethods: (list) => { - methods = list; - initAll(); - }, + setMethods: (list) => { methods = list; initAll(); }, Parameter, ParameterType, Method, diff --git a/script/custommethod-search.ts b/script/custommethod-search.ts index 833cdc5..941106d 100644 --- a/script/custommethod-search.ts +++ b/script/custommethod-search.ts @@ -17,17 +17,20 @@ Condition = "condition", CustomClass = "custom_class", } + type ValueMode = "constant" | "expression"; + type StringStrategy = "prefix" | "quote"; const enumTypeMap: Record = { Characters: ["Logan", "Green", "Blue", "Yellow", "Purple", "Orange"], Size: ["Small", "Medium", "Large"], Shape: ["Circle", "Square", "Triangle"], }; -class NumericRange { - min: number; - max: number; + + class NumericRange { + min?: number; + max?: number; isInteger: boolean; - public constructor(min: number, max: number, isInteger: boolean = false) { + public constructor(min?: number, max?: number, isInteger: boolean = false) { this.min = min; this.max = max; this.isInteger = isInteger; @@ -50,61 +53,63 @@ class NumericRange { class Method { name: string; type: MethodType; + shortDescription: string; description: string; - public constructor(name: string, type: MethodType, description: string) { + public constructor(name: string, type: MethodType, shortDescription: string, description: string) { this.name = name; this.type = type; + this.shortDescription = shortDescription; this.description = description; } } class Mod extends Method { - public constructor(name: string, description: string) { - super(name, MethodType.Mod, description); + public constructor(name: string, shortDescription: string, description: string) { + super(name, MethodType.Mod, shortDescription, description); } } class Surgery extends Method { - public constructor(name: string, description: string) { - super(name, MethodType.Surgery, description); + public constructor(name: string, shortDescription: string, description: string) { + super(name, MethodType.Surgery, shortDescription, description); } } class CommentMethod extends Method { parameters: Parameter[]; - public constructor(name: string, description: string, parameters: Parameter[]) { - super(name, MethodType.Comment, description); + public constructor(name: string, shortDescription: string, description: string, parameters: Parameter[]) { + super(name, MethodType.Comment, shortDescription, description); this.parameters = parameters; } } class InkMethod extends Method { parameters: Parameter[]; - public constructor(name: string, description: string, parameters: Parameter[]) { - super(name, MethodType.Ink, description); + public constructor(name: string, shortDescription: string, description: string, parameters: Parameter[]) { + super(name, MethodType.Ink, shortDescription, description); this.parameters = parameters; } } class CustomMethods extends Method { parameters: Parameter[]; - public constructor(name: string, description: string, parameters: Parameter[]) { - super(name, MethodType.CustomMethod, description); + public constructor(name: string, shortDescription: string, description: string, parameters: Parameter[]) { + super(name, MethodType.CustomMethod, shortDescription, description); this.parameters = parameters; } } class VariableMethod extends Method { parameters: Parameter[]; - public constructor(name: string, description: string, parameters: Parameter[]) { - super(name, MethodType.Variable, description); + public constructor(name: string, shortDescription: string, description: string, parameters: Parameter[]) { + super(name, MethodType.Variable, shortDescription, description); this.parameters = parameters; } } class ConditionMethod extends Method { parameters: Parameter[]; - public constructor(name: string, description: string, parameters: Parameter[]) { - super(name, MethodType.Condition, description); + public constructor(name: string, shortDescription: string, description: string, parameters: Parameter[]) { + super(name, MethodType.Condition, shortDescription, description); this.parameters = parameters; } } class CustomClassMethod extends Method { - public constructor(name: string, description: string) { - super(name, MethodType.CustomClass, description); + public constructor(name: string, shortDescription: string, description: string) { + super(name, MethodType.CustomClass, shortDescription, description); } } @@ -139,41 +144,19 @@ class NumericRange { return (method as CommentMethod | InkMethod | CustomMethods | VariableMethod | ConditionMethod).parameters ?? []; } - // --------------------------------------------------------------------- - // 数据:可直接在此编辑,或通过 window.CustomMethodSearch.setMethods(...) 覆盖 - // --------------------------------------------------------------------- - let methods: Method[] = [ - new Mod("wobblyLines", "让单发拍子的轨道抖动"), - new Mod("invisibleHeart", "隐藏轨道上的心脏"), - new CustomMethods("ChangeCharacter", "修改某条轨道对应的人物", [ - new Parameter("character", ParameterType.Enum, "Characters"), - new Parameter("row", ParameterType.Number, "轨道编号", undefined, new NumericRange(0, 15, true)), - ]), - new CustomMethods("DisableRowReflections", "开关某个房间的地面反射", [ - new Parameter("room", ParameterType.Number, "房间编号", undefined, new NumericRange(0, 3, true)), - ]), - new CustomMethods("SetRowLength", "设置轨道长度", [ - new Parameter("row", ParameterType.Number, "轨道编号", undefined, new NumericRange(0, 15, true)), - new Parameter("length", ParameterType.Number, "轨道长度", undefined, new NumericRange(1, 7, true)), - ]), - new CommentMethod("trueCameraMove", "移动真实摄像头", [ - new Parameter("x", ParameterType.Number, "目标 X"), - new Parameter("y", ParameterType.Number, "目标 Y"), - new Parameter("angle", ParameterType.Number, "角度"), - new Parameter("duration", ParameterType.Number, "时长"), - new Parameter("ease", ParameterType.Enum, "缓动类型", "EaseType"), - ]), - new CustomMethods("DemoAllTypes", "演示四种参数控件", [ - new Parameter("text", ParameterType.String, "文本"), - new Parameter("count", ParameterType.Number, "数字"), - new Parameter("enabled", ParameterType.Boolean, "开关"), - new Parameter("character", ParameterType.Enum, "角色", "Characters"), - new Parameter("color", ParameterType.Enum, "颜色"), - ]), - ]; + // 全局策略:字符串写法、数字/布尔默认的常量/表达式状态 + const strategies: { string: StringStrategy; number: ValueMode; boolean: ValueMode } = { + string: "prefix", + number: "constant", + boolean: "constant", + }; - // 合并外置数据(script/custommethod-data.js),同名以内置为准 + // --------------------------------------------------------------------- + // 外置数据 hydrate(script/custommethod-data.js) + // --------------------------------------------------------------------- function hydrateMethod(raw: any): Method { + const shortDescription = raw.shortDescription ?? raw.description ?? ""; + const description = raw.description ?? raw.shortDescription ?? ""; const parameters: Parameter[] = Array.isArray(raw.parameters) ? raw.parameters.map((item: any) => new Parameter( item.name, @@ -186,17 +169,19 @@ class NumericRange { )) : []; switch (raw.type) { - case MethodType.Mod: return new Mod(raw.name, raw.description ?? ""); - case MethodType.Surgery: return new Surgery(raw.name, raw.description ?? ""); - case MethodType.Comment: return new CommentMethod(raw.name, raw.description ?? "", parameters); - case MethodType.Ink: return new InkMethod(raw.name, raw.description ?? "", parameters); - case MethodType.Variable: return new VariableMethod(raw.name, raw.description ?? "", parameters); - case MethodType.Condition: return new ConditionMethod(raw.name, raw.description ?? "", parameters); - case MethodType.CustomClass: return new CustomClassMethod(raw.name, raw.description ?? ""); - default: return new CustomMethods(raw.name, raw.description ?? "", parameters); + case MethodType.Mod: return new Mod(raw.name, shortDescription, description); + case MethodType.Surgery: return new Surgery(raw.name, shortDescription, description); + case MethodType.Comment: return new CommentMethod(raw.name, shortDescription, description, parameters); + case MethodType.Ink: return new InkMethod(raw.name, shortDescription, description, parameters); + case MethodType.Variable: return new VariableMethod(raw.name, shortDescription, description, parameters); + case MethodType.Condition: return new ConditionMethod(raw.name, shortDescription, description, parameters); + case MethodType.CustomClass: return new CustomClassMethod(raw.name, shortDescription, description); + default: return new CustomMethods(raw.name, shortDescription, description, parameters); } } + let methods: Method[] = []; + function loadExternalData(): void { const data = (window as any).CustomMethodSearchData; if (!data) return; @@ -254,7 +239,7 @@ class NumericRange { } // --------------------------------------------------------------------- - // DOM 构建 + // DOM 工具 // --------------------------------------------------------------------- function el(tag: K, className?: string): HTMLElementTagNameMap[K] { const node = document.createElement(tag); @@ -263,30 +248,18 @@ class NumericRange { } function resolveEnumOptions(parameter: Parameter): string[] { - if (parameter.enumType && enumTypeMap[parameter.enumType]) { - return enumTypeMap[parameter.enumType]; - } - // 兼容把枚举类型名写在 description 的情况 - if (enumTypeMap[parameter.description]) { - return enumTypeMap[parameter.description]; - } - if (enumTypeMap[parameter.name]) { - return enumTypeMap[parameter.name]; - } + if (parameter.enumType && enumTypeMap[parameter.enumType]) return enumTypeMap[parameter.enumType]; + if (enumTypeMap[parameter.description]) return enumTypeMap[parameter.description]; + if (enumTypeMap[parameter.name]) return enumTypeMap[parameter.name]; return []; } - // 布尔值可用 true/false,也可用布尔变量 b0~b9 + // 布尔可用 true/false,或布尔变量 b0~b9 const BOOLEAN_OPTIONS: string[] = ["true", "false"]; for (let i = 0; i < 10; i++) { BOOLEAN_OPTIONS.push("b" + i); } - function isNumberVariable(value: string): boolean { - // 数字位置允许的变量:i0~i9(整型)、f0~f9(浮点)、b0~b9(布尔) - return /^[ifb][0-9]$/.test(value); - } - function makeCombo(parameter: Parameter, options: string[], onChange: () => void): HTMLElement { const combo = el("span", "cm-combo"); const input = el("input", "cm-input cm-combo-input") as HTMLInputElement; @@ -298,10 +271,7 @@ class NumericRange { function populate(): void { list.textContent = ""; - if (options.length === 0) { - list.hidden = true; - return; - } + if (options.length === 0) { list.hidden = true; return; } const query = input.value.trim(); const ql = query.toLowerCase(); const maxDistance = Math.max(1, Math.floor(query.length / 2)); @@ -311,10 +281,7 @@ class NumericRange { editDistance(option, query, false) <= maxDistance) : options ).slice(0, 10); - if (shown.length === 0) { - list.hidden = true; - return; - } + if (shown.length === 0) { list.hidden = true; return; } for (const option of shown) { const item = el("li", "cm-combo-item"); item.textContent = option; @@ -330,122 +297,191 @@ class NumericRange { list.hidden = false; } - input.addEventListener("input", () => { - populate(); - onChange(); - }); + input.addEventListener("input", () => { populate(); onChange(); }); input.addEventListener("focus", populate); - input.addEventListener("blur", () => { - window.setTimeout(() => { list.hidden = true; }, 120); - }); - + input.addEventListener("blur", () => { window.setTimeout(() => { list.hidden = true; }, 120); }); combo.appendChild(input); combo.appendChild(list); return combo; } - function makeControl(parameter: Parameter, onChange: () => void): HTMLElement { - switch (parameter.type) { - case ParameterType.Boolean: { - return makeCombo(parameter, BOOLEAN_OPTIONS, onChange); - } - case ParameterType.Enum: { - // 可输入的下拉框:输入时用编辑距离筛选候选项 - return makeCombo(parameter, resolveEnumOptions(parameter), onChange); - } - case ParameterType.Number: { - // 普通输入框,合法性由 readParameter 校验(非数字标红) - const number = el("input", "cm-input") as HTMLInputElement; - number.type = "text"; - number.inputMode = "decimal"; - number.placeholder = parameter.name; - number.addEventListener("input", onChange); - return number; - } - default: { - const text = el("input", "cm-input") as HTMLInputElement; - text.type = "text"; - text.placeholder = parameter.name; - text.addEventListener("input", onChange); - return text; - } - } + function makeModeToggle(initial: ValueMode, onChange: () => void): { el: HTMLButtonElement; get: () => ValueMode } { + const button = el("button", "cm-mode") as HTMLButtonElement; + button.type = "button"; + let mode = initial; + const render = (): void => { + button.textContent = mode === "expression" ? "表达式" : "常量"; + button.title = "切换 常量 / 表达式"; + button.classList.toggle("is-expression", mode === "expression"); + }; + render(); + button.addEventListener("click", (event) => { + event.preventDefault(); + mode = mode === "expression" ? "constant" : "expression"; + render(); + onChange(); + }); + return { el: button, get: () => mode }; } - interface ParameterState { + interface ParamState { text: string; valid: boolean; invalid: boolean; - control: HTMLElement; + } + interface Field { + el: HTMLElement; + read: () => ParamState; } - function readParameter(parameter: Parameter, control: HTMLElement): ParameterState { + function stringValue(value: string): string { + if (value.length === 0) return "<文本>"; + return strategies.string === "quote" ? `"${value}"` : `str:${value}`; + } + + function makeField(parameter: Parameter, onChange: () => void): Field { switch (parameter.type) { case ParameterType.Boolean: { - const input = control.querySelector("input") as HTMLInputElement; - const value = input.value.trim(); - const valid = value === "true" || value === "false" || /^b[0-9]$/.test(value); - return { text: value || "<布尔>", valid, invalid: value.length > 0 && !valid, control }; - } - case ParameterType.Enum: { - const input = control.querySelector("input") as HTMLInputElement; - const value = input.value.trim(); - const options = resolveEnumOptions(parameter); - const valid = options.length > 0 - ? options.some((option) => option.toLowerCase() === value.toLowerCase()) - : value.length > 0; - return { text: value || "<选项>", valid, invalid: value.length > 0 && !valid, control }; + const wrap = el("span", "cm-field"); + const checkbox = el("input", "cm-input cm-check") as HTMLInputElement; + checkbox.type = "checkbox"; + checkbox.addEventListener("change", onChange); + const combo = makeCombo(parameter, BOOLEAN_OPTIONS, onChange); + const comboInput = combo.querySelector("input") as HTMLInputElement; + let mode: ValueMode = strategies.boolean; + const toggle = makeModeToggle(strategies.boolean, () => { + mode = toggle.get(); + applyMode(); + onChange(); + }); + function applyMode(): void { + const expression = mode === "expression"; + checkbox.hidden = expression; + combo.hidden = !expression; + } + applyMode(); + wrap.appendChild(toggle.el); + wrap.appendChild(checkbox); + wrap.appendChild(combo); + return { + el: wrap, + read: () => { + if (mode === "constant") { + return { text: checkbox.checked ? "true" : "false", valid: true, invalid: false }; + } + const value = comboInput.value.trim(); + return value.length > 0 + ? { text: value, valid: true, invalid: false } + : { text: "<布尔>", valid: false, invalid: true }; + }, + }; } case ParameterType.Number: { - const input = control as HTMLInputElement; - const value = input.value.trim(); - if (value.length === 0) { - return { text: "<数字>", valid: false, invalid: false, control }; - } - if (isNumberVariable(value)) { - return { text: value, valid: true, invalid: false, control }; - } - const number = Number(value); - let valid = isFinite(number); - const range = parameter.numericRange; - if (valid && range) { - if (range.isInteger && !Number.isInteger(number)) valid = false; - if (number < range.min || number > range.max) valid = false; - } - return { text: value, valid, invalid: !valid, control }; + const wrap = el("span", "cm-field"); + const input = el("input", "cm-input") as HTMLInputElement; + input.type = "text"; + input.inputMode = "decimal"; + input.placeholder = parameter.name; + input.addEventListener("input", onChange); + const mode = makeModeToggle(strategies.number, onChange); + wrap.appendChild(mode.el); + wrap.appendChild(input); + return { + el: wrap, + read: () => { + const value = input.value.trim(); + if (value.length === 0) return { text: "<数字>", valid: false, invalid: true }; + if (mode.get() === "expression") return { text: value, valid: true, invalid: false }; + const number = Number(value); + let valid = isFinite(number); + const range = parameter.numericRange; + if (valid && range) { + if (range.isInteger && !Number.isInteger(number)) valid = false; + if (range.min !== undefined && number < range.min) valid = false; + if (range.max !== undefined && number > range.max) valid = false; + } + return { text: value, valid, invalid: !valid }; + }, + }; + } + case ParameterType.Enum: { + const wrap = el("span", "cm-field cm-field-string"); + const open = el("span", "cm-lit"); + const close = el("span", "cm-lit"); + open.textContent = strategies.string === "quote" ? "\"" : "str:"; + close.textContent = strategies.string === "quote" ? "\"" : ""; + const combo = makeCombo(parameter, resolveEnumOptions(parameter), onChange); + const input = combo.querySelector("input") as HTMLInputElement; + wrap.appendChild(open); + wrap.appendChild(combo); + wrap.appendChild(close); + return { + el: wrap, + read: () => { + const value = input.value.trim(); + const options = resolveEnumOptions(parameter); + const valid = options.length > 0 + ? options.some((option) => option.toLowerCase() === value.toLowerCase()) + : value.length > 0; + return { text: stringValue(value), valid, invalid: !valid }; + }, + }; } default: { - const input = control as HTMLInputElement; - const value = input.value.trim(); - return { text: value ? `str:${value}` : "<文本>", valid: value.length > 0, invalid: false, control }; + const wrap = el("span", "cm-field cm-field-string"); + const open = el("span", "cm-lit"); + const close = el("span", "cm-lit"); + open.textContent = strategies.string === "quote" ? "\"" : "str:"; + close.textContent = strategies.string === "quote" ? "\"" : ""; + const input = el("input", "cm-input") as HTMLInputElement; + input.type = "text"; + input.placeholder = parameter.name; + input.addEventListener("input", onChange); + wrap.appendChild(open); + wrap.appendChild(input); + wrap.appendChild(close); + return { + el: wrap, + read: () => { + const value = input.value.trim(); + return { text: stringValue(value), valid: value.length > 0, invalid: value.length === 0 }; + }, + }; } } } - function stripStringPrefix(text: string): string { - return text.startsWith("str:") ? text.slice(4) : text; + interface Skeleton { + prefix: string; + suffix: string; } - function formatMethod(method: Method, states: ParameterState[]): string { - const values = states.map((state) => state.text); - const args = values.join(", "); + function methodSkeleton(method: Method, hasParams: boolean): Skeleton { switch (method.type) { - case MethodType.Comment: - return `()=>${method.name}(${args})`; - case MethodType.Ink: - return `DOTHIS{${method.name}(${args})}`; - case MethodType.Variable: - return `${method.name} = ${values.length ? stripStringPrefix(values[0]) : ""}`; - case MethodType.Mod: - return `"mods": [..., "${method.name}"]`; - case MethodType.CustomClass: - return `"customClass": "${method.name}"`; + case MethodType.Comment: return { prefix: `()=>${method.name}(`, suffix: ")" }; + case MethodType.Ink: return { prefix: `DOTHIS{${method.name}(`, suffix: ")}" }; + case MethodType.Variable: return { prefix: `${method.name} = `, suffix: "" }; + case MethodType.Mod: return { prefix: `"mods": [..., "`, suffix: `"]` }; + case MethodType.CustomClass: return { prefix: `"customClass": "`, suffix: `"` }; case MethodType.Condition: - return values.length ? `${method.name}(${args})` : method.name; - case MethodType.Surgery: - return method.name; + return hasParams ? { prefix: `${method.name}(`, suffix: ")" } : { prefix: method.name, suffix: "" }; + case MethodType.Surgery: return { prefix: method.name, suffix: "" }; default: - return values.length ? `${method.name}(${args})` : method.name; + return hasParams ? { prefix: `${method.name}(`, suffix: ")" } : { prefix: method.name, suffix: "" }; + } + } + + function formatMethod(method: Method, states: ParamState[]): string { + const args = states.map((state) => state.text).join(", "); + switch (method.type) { + case MethodType.Comment: return `()=>${method.name}(${args})`; + case MethodType.Ink: return `DOTHIS{${method.name}(${args})}`; + case MethodType.Variable: return `${method.name} = ${states.length ? states[0].text : ""}`; + case MethodType.Mod: return `"mods": [..., "${method.name}"]`; + case MethodType.CustomClass: return `"customClass": "${method.name}"`; + case MethodType.Condition: return states.length ? `${method.name}(${args})` : method.name; + case MethodType.Surgery: return method.name; + default: return states.length ? `${method.name}(${args})` : method.name; } } @@ -456,7 +492,7 @@ class NumericRange { return true; } } catch (error) { - // fallthrough to execCommand + // fall through } try { const area = document.createElement("textarea"); @@ -473,20 +509,26 @@ class NumericRange { } } + // --------------------------------------------------------------------- + // 渲染 + // --------------------------------------------------------------------- function renderContainer(container: HTMLElement): void { if (container.dataset.cmReady === "1") return; container.dataset.cmReady = "1"; - // 优先使用 custommethod.md 里写好的骨架;缺失时再动态生成 + let currentMethod: Method | null = null; + let query = container.querySelector(".cm-query"); let suggest = container.querySelector(".cm-suggest"); let selected = container.querySelector(".cm-selected"); let nameEl = container.querySelector(".cm-name"); - let descEl = container.querySelector(".cm-desc"); - let row = container.querySelector(".cm-row"); + let shortEl = container.querySelector(".cm-short"); + let call = container.querySelector(".cm-call"); let preview = container.querySelector(".cm-preview"); + let desc = container.querySelector(".cm-desc"); + let options = container.querySelector(".cm-options"); - if (!query || !suggest || !selected || !nameEl || !descEl || !row || !preview) { + if (!query || !suggest || !selected || !nameEl || !shortEl || !call || !preview || !desc) { container.textContent = ""; const searchBar = el("div", "cm-search"); query = el("input", "cm-query") as HTMLInputElement; @@ -500,34 +542,68 @@ class NumericRange { selected.hidden = true; const head = el("div", "cm-head"); nameEl = el("span", "cm-name"); - descEl = el("span", "cm-desc"); + shortEl = el("span", "cm-short"); head.appendChild(nameEl); - head.appendChild(descEl); - row = el("div", "cm-row"); + head.appendChild(shortEl); + call = el("div", "cm-call"); preview = el("code", "cm-preview"); + desc = el("div", "cm-desc"); selected.appendChild(head); - selected.appendChild(row); + selected.appendChild(call); selected.appendChild(preview); + selected.appendChild(desc); container.appendChild(searchBar); container.appendChild(selected); } + // 搜索框下的策略选项 + options = container.querySelector(".cm-options"); + if (!options) { + options = el("div", "cm-options"); + (query.parentElement as HTMLElement).insertAdjacentElement("afterend", options); + } + if (!options.querySelector(".cm-option-select")) { + const optionsBox = options; + function addOption(label: string, key: "string" | "number" | "boolean", values: [string, string][], current: string): void { + const wrap = el("label", "cm-option"); + const text = el("span", "cm-option-label"); + text.textContent = label; + const select = el("select", "cm-option-select") as HTMLSelectElement; + for (const [value, caption] of values) { + const opt = el("option"); + opt.value = value; + opt.textContent = caption; + select.appendChild(opt); + } + select.value = current; + select.addEventListener("change", () => { + (strategies as any)[key] = select.value; + if (currentMethod) { selectMethod(currentMethod); } + }); + wrap.appendChild(text); + wrap.appendChild(select); + optionsBox.appendChild(wrap); + } + addOption("字符串", "string", [["prefix", "str: 前缀"], ["quote", "引号 \"…\""]], strategies.string); + } + const queryEl = query; const suggestEl = suggest; const selectedEl = selected; const nameNode = nameEl; - const descNode = descEl; - const rowEl = row; + const shortNode = shortEl; + const callEl = call; const previewEl = preview; + const descNode = desc; const copyBtn = el("button", "cm-copy") as HTMLButtonElement; copyBtn.type = "button"; copyBtn.textContent = "复制"; copyBtn.hidden = true; - copyBtn.title = "复制生成的调用代码"; + copyBtn.title = "复制生成的代码"; selectedEl.appendChild(copyBtn); copyBtn.addEventListener("click", () => { - copyText(previewEl.textContent).then((ok) => { + copyText(previewEl.textContent ?? "").then((ok) => { copyBtn.textContent = ok ? "已复制" : "复制失败"; window.setTimeout(() => { copyBtn.textContent = "复制"; }, 1200); }); @@ -538,56 +614,69 @@ class NumericRange { } function selectMethod(method: Method): void { + currentMethod = method; clearSuggest(); queryEl.value = method.name; selectedEl.hidden = false; nameNode.textContent = method.name; - descNode.textContent = method.description; - rowEl.textContent = ""; + shortNode.textContent = method.shortDescription || ""; + descNode.textContent = method.description || ""; + callEl.textContent = ""; previewEl.textContent = ""; copyBtn.hidden = true; const parameters = parametersOf(method); - const controls: { parameter: Parameter; control: HTMLElement }[] = []; + const fields: Field[] = []; function updatePreview(): void { - const states = controls.map((item) => readParameter(item.parameter, item.control)); - states.forEach((state) => state.control.classList.toggle("cm-invalid", state.invalid)); + const states = fields.map((field) => field.read()); + fields.forEach((field, i) => field.el.classList.toggle("cm-invalid", states[i].invalid)); previewEl.textContent = formatMethod(method, states); copyBtn.hidden = !states.every((state) => state.valid); } + const skeleton = methodSkeleton(method, parameters.length > 0); + const code = el("code", "cm-code"); + const prefix = el("span", "cm-lit"); + prefix.textContent = skeleton.prefix; + code.appendChild(prefix); + + parameters.forEach((parameter, index) => { + if (index > 0) { + const sep = el("span", "cm-lit"); + sep.textContent = ", "; + code.appendChild(sep); + } + const field = makeField(parameter, updatePreview); + field.el.title = parameter.description; + code.appendChild(field.el); + fields.push(field); + }); + + if (skeleton.suffix) { + const suffix = el("span", "cm-lit"); + suffix.textContent = skeleton.suffix; + code.appendChild(suffix); + } + callEl.appendChild(code); + if (parameters.length === 0) { const empty = el("span", "cm-empty"); - empty.textContent = "该方法没有参数"; - rowEl.appendChild(empty); - updatePreview(); - return; + empty.textContent = "(无参数)"; + callEl.appendChild(empty); } - for (const parameter of parameters) { - const field = el("label", "cm-param"); - field.title = parameter.description; - const label = el("span", "cm-param-name"); - label.textContent = parameter.name; - const control = makeControl(parameter, updatePreview); - field.appendChild(label); - field.appendChild(control); - rowEl.appendChild(field); - controls.push({ parameter, control }); - } updatePreview(); } function updateSuggestions(): void { clearSuggest(); - const matches = searchMethods(queryEl.value); - for (const method of matches) { + for (const method of searchMethods(queryEl.value)) { const item = el("li", "cm-suggest-item"); const nameSpan = el("span", "cm-suggest-name"); nameSpan.textContent = method.name; const descSpan = el("span", "cm-suggest-desc"); - descSpan.textContent = method.description; + descSpan.textContent = method.shortDescription || method.description; item.appendChild(nameSpan); item.appendChild(descSpan); item.addEventListener("mousedown", (event) => { @@ -613,8 +702,7 @@ class NumericRange { } function initAll(): void { - const containers = document.querySelectorAll(".custommethods-search"); - containers.forEach((container) => renderContainer(container)); + document.querySelectorAll(".custommethods-search").forEach((container) => renderContainer(container)); } function register(): void { @@ -634,11 +722,9 @@ class NumericRange { search: searchMethods, editDistance, renderAll: initAll, + strategies, getMethods: () => methods, - setMethods: (list: Method[]) => { - methods = list; - initAll(); - }, + setMethods: (list: Method[]) => { methods = list; initAll(); }, Parameter, ParameterType, Method, diff --git a/style/special.css b/style/special.css index 309bff3..d927895 100644 --- a/style/special.css +++ b/style/special.css @@ -485,4 +485,96 @@ div.custommethods-search { border-color: #3b8e59; } } + + & .cm-options { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 6px; + font-size: 12px; + } + + & .cm-option { + display: inline-flex; + align-items: center; + gap: 4px; + opacity: 0.85; + } + + & .cm-option-select { + padding: 2px 4px; + font-size: 12px; + color: inherit; + background-color: var(--background-color); + border: 1px solid var(--background-border-color); + border-radius: 4px; + } + + & .cm-short { + font-size: 12px; + opacity: 0.7; + } + + & .cm-call { + margin-top: 8px; + } + + & .cm-code { + display: inline-flex; + flex-wrap: wrap; + align-items: center; + gap: 4px; + padding: 8px 10px; + font-family: d9c, d9, monospace; + background-color: rgba(127, 127, 127, 0.12); + border-radius: 6px; + } + + & .cm-lit { + font-family: d9c, d9, monospace; + opacity: 0.85; + white-space: pre; + } + + & .cm-field { + display: inline-flex; + align-items: center; + gap: 3px; + + & [hidden] { + display: none !important; + } + } + + & .cm-field.cm-invalid .cm-input { + border-color: #e5484d; + box-shadow: 0 0 0 1px #e5484d; + } + + & .cm-check { + width: auto; + } + + & .cm-desc { + margin-top: 8px; + font-size: 12px; + line-height: 1.5; + opacity: 0.75; + white-space: pre-wrap; + } + + & .cm-mode { + padding: 1px 6px; + font-size: 11px; + color: inherit; + background-color: transparent; + border: 1px solid var(--background-border-color); + border-radius: 8px; + cursor: pointer; + + &.is-expression { + color: #3b8e59; + border-color: #3b8e59; + } + } } \ No newline at end of file -- 2.48.1.windows.1