diff --git a/Fk/Cheat/GeneralDetail.qml b/Fk/Cheat/GeneralDetail.qml
index 5514a161..a6df28ba 100644
--- a/Fk/Cheat/GeneralDetail.qml
+++ b/Fk/Cheat/GeneralDetail.qml
@@ -56,11 +56,8 @@ Flickable {
skillDesc.append(ret)
}
data.skill.forEach(t => {
- skillDesc.append("" + luatr(t.name) + ": " + t.description)
- });
- data.related_skill.forEach(t => {
- skillDesc.append("" + luatr(t.name) +
- ": " + t.description + "")
+ skillDesc.append((t.is_related_skill ? "" : "") + luatr(t.name) +
+ ": " + t.description + (t.is_related_skill ? "" : ""));
});
skillDesc.append("\n");
});
diff --git a/Fk/Cheat/PlayerDetail.qml b/Fk/Cheat/PlayerDetail.qml
index 3a3a442f..41184d69 100644
--- a/Fk/Cheat/PlayerDetail.qml
+++ b/Fk/Cheat/PlayerDetail.qml
@@ -212,5 +212,17 @@ Flickable {
skillDesc.append("--------------------");
skillDesc.append("" + luatr(t.name) + ": " + luatr(":" + t.name));
});
+
+ const judge = leval(
+ `(function()
+ local p = ClientInstance:getPlayerById(${id})
+ return p.player_cards[Player.Judge]
+ end)()`
+ );
+ judge.forEach(cid => {
+ const t = lcall("GetCardData", cid);
+ skillDesc.append("--------------------");
+ skillDesc.append("" + luatr(t.name) + ": " + luatr(":" + t.name));
+ });
}
}
diff --git a/Fk/Common/LogEdit.qml b/Fk/Common/LogEdit.qml
index 1e0e2dfc..9fb02d74 100644
--- a/Fk/Common/LogEdit.qml
+++ b/Fk/Common/LogEdit.qml
@@ -40,7 +40,7 @@ ListView {
}
Button {
- text: "Return to Bottom"
+ text: luatr("Return to Bottom")
visible: root.currentIndex !== logModel.count - 1
onClicked: root.currentIndex = logModel.count - 1;
}
diff --git a/Fk/Config.qml b/Fk/Config.qml
index cc8babcc..3542d309 100644
--- a/Fk/Config.qml
+++ b/Fk/Config.qml
@@ -20,12 +20,14 @@ QtObject {
property string preferedMode
property int preferedPlayerNum
property int preferredGeneralNum
+ property var preferredFilter
property string ladyImg
property real bgmVolume
property bool disableMsgAudio
property bool hideUseless
property bool hideObserverChatter
property bool rotateTableCard
+ property bool hidePresents
// property list disabledGenerals: []
// property list disableGeneralSchemes: []
// property int disableSchemeIdx: 0
@@ -126,6 +128,13 @@ QtObject {
preferedMode = conf.preferedMode ?? "aaa_role_mode";
preferedPlayerNum = conf.preferedPlayerNum ?? 2;
preferredGeneralNum = conf.preferredGeneralNum ?? 3;
+ preferredFilter = conf.preferredFilter ?? {
+ name: "", // 房间名
+ id: "", // 房间ID
+ modes : [], // 游戏模式
+ full : 2, // 满员,0满,1未满,2不限
+ hasPassword : 2, // 密码,0有,1无,2不限
+ };
ladyImg = conf.ladyImg ?? AppPath + "/image/lady";
Backend.volume = conf.effectVolume ?? 50.;
bgmVolume = conf.bgmVolume ?? 50.;
@@ -133,6 +142,7 @@ QtObject {
hideUseless = conf.hideUseless ?? false;
hideObserverChatter = conf.hideObserverChatter ?? false;
rotateTableCard = conf.rotateTableCard ?? false;
+ hidePresents = conf.hidePresents ?? false;
preferredTimeout = conf.preferredTimeout ?? 15;
preferredLuckTime = conf.preferredLuckTime ?? 0;
firstRun = conf.firstRun ?? true;
@@ -165,6 +175,7 @@ QtObject {
// conf.disabledPack = disabledPack;
conf.preferedMode = preferedMode;
conf.preferedPlayerNum = preferedPlayerNum;
+ conf.preferredFilter = preferredFilter;
conf.ladyImg = ladyImg;
conf.preferredGeneralNum = preferredGeneralNum;
conf.effectVolume = Backend.volume;
@@ -173,6 +184,7 @@ QtObject {
conf.hideUseless = hideUseless;
conf.hideObserverChatter = hideObserverChatter;
conf.rotateTableCard = rotateTableCard;
+ conf.hidePresents = hidePresents;
conf.preferredTimeout = preferredTimeout;
conf.preferredLuckTime = preferredLuckTime;
conf.firstRun = firstRun;
diff --git a/Fk/LobbyElement/AudioSetting.qml b/Fk/LobbyElement/AudioSetting.qml
index cd75a61b..d6f52249 100644
--- a/Fk/LobbyElement/AudioSetting.qml
+++ b/Fk/LobbyElement/AudioSetting.qml
@@ -70,5 +70,13 @@ ColumnLayout {
}
}
+ Switch {
+ text: luatr("Hide presents")
+ checked: config.hidePresents
+ onCheckedChanged: {
+ config.hidePresents = checked;
+ }
+ }
+
}
}
diff --git a/Fk/LobbyElement/FilterRoom.qml b/Fk/LobbyElement/FilterRoom.qml
new file mode 100644
index 00000000..f310375f
--- /dev/null
+++ b/Fk/LobbyElement/FilterRoom.qml
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Flickable {
+ id: root
+ height: parent.height
+ width: layout.width
+ anchors.fill: parent
+ anchors.margins: 16
+ clip: true
+ contentWidth: layout.width
+ contentHeight: layout.height
+ ScrollBar.vertical: ScrollBar {}
+ ScrollBar.horizontal: ScrollBar {} // considering long game mode name
+
+ signal finished()
+
+ ColumnLayout {
+ id: layout
+ anchors.top: parent.top
+
+ Item { Layout.fillHeight: true }
+
+ // roomId, roomName, gameMode, playerNum, capacity, hasPassword, outdated
+
+ GridLayout {
+ columns: 2
+
+ // roomName
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Text {
+ text: luatr("Room Name")
+ font.bold: true
+ font.pixelSize: 14
+ }
+ TextField {
+ id: name
+ maximumLength: 64
+ font.pixelSize: 18
+ Layout.rightMargin: 16
+ Layout.fillWidth: true
+ text: config.preferredFilter.name
+ }
+ }
+
+ // roomId
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Text {
+ text: luatr("Room ID")
+ font.bold: true
+ font.pixelSize: 14
+ }
+ TextField {
+ id: id
+ maximumLength: 64
+ font.pixelSize: 18
+ Layout.rightMargin: 16
+ Layout.fillWidth: true
+ text: config.preferredFilter.id
+ }
+ }
+ }
+
+ // gameMode
+ ButtonGroup {
+ id: childModes
+ exclusive: false
+ checkState: parentModeBox.checkState
+ }
+
+ CheckBox {
+ id: parentModeBox
+ text: luatr("Game Mode")
+ font.bold: true
+ checkState: childModes.checkState
+ }
+ GridLayout {
+ columns: 6
+
+ Repeater {
+ id: modes
+ model: ListModel {
+ id: gameModeList
+ }
+
+ CheckBox {
+ text: name
+ checked: config.preferredFilter.modes.includes(name)
+ leftPadding: indicator.width
+ ButtonGroup.group: childModes
+ }
+ }
+ }
+
+ RowLayout {
+ anchors.rightMargin: 8
+ // spacing: 64
+ // Layout.fillWidth: true
+
+ // full
+ Column {
+ ButtonGroup {
+ id: childFull
+ exclusive: false
+ checkState: parentFullBox.checkState
+ }
+
+ CheckBox {
+ id: parentFullBox
+ text: luatr("Room Fullness")
+ font.bold: true
+ checkState: childFull.checkState
+ }
+
+ GridLayout {
+ columns: 6
+
+ Repeater {
+ id: fullStates
+ model: ["Full", "Not Full"]
+
+ CheckBox {
+ text: luatr(modelData)
+ checked: config.preferredFilter.full === index
+ leftPadding: indicator.width
+ ButtonGroup.group: childFull
+ }
+ }
+ }
+ }
+
+ // hasPassword
+ Column {
+ ButtonGroup {
+ id: childPw
+ exclusive: false
+ checkState: parentPwBox.checkState
+ }
+
+ CheckBox {
+ id: parentPwBox
+ text: luatr("Room Password")
+ font.bold: true
+ checkState: childPw.checkState
+ }
+
+ GridLayout {
+ columns: 6
+
+ Repeater {
+ id: pwStates
+ model: ["Has Password", "No Password"]
+
+ CheckBox {
+ text: luatr(modelData)
+ checked: config.preferredFilter.hasPassword === index
+ leftPadding: indicator.width
+ ButtonGroup.group: childPw
+ }
+ }
+ }
+ }
+
+ Button {
+ text: luatr("Clear")
+ onClicked: {
+ opTimer.start();
+ config.preferredFilter = {
+ name: "",
+ id: "",
+ modes : [],
+ full : 2,
+ hasPassword : 2,
+ }
+ config.preferredFilterChanged();
+ ClientInstance.notifyServer("RefreshRoomList", "");
+ lobby_dialog.item.finished();
+ }
+ }
+
+ Button {
+ text: luatr("Filter")
+ // width: 200
+ // enabled: !opTimer.running
+ onClicked: {
+ // opTimer.start();
+ filterRoom();
+ root.finished();
+ }
+ }
+ }
+
+ // capacity
+ /*
+ Column {
+ ButtonGroup {
+ id: childCapacity
+ exclusive: false
+ checkState: parentCapacityBox.checkState
+ }
+
+ CheckBox {
+ id: parentCapacityBox
+ text: luatr("Room Capacity")
+ font.bold: true
+ checkState: childCapacity.checkState
+ }
+
+ GridLayout {
+ columns: 6
+
+ Repeater {
+ id: capacityStates
+ model: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
+
+ CheckBox {
+ text: modelData
+ checked: false
+ leftPadding: indicator.width
+ ButtonGroup.group: childCapacity
+ }
+ }
+ }
+ }
+ */
+
+ Component.onCompleted: {
+ const mode_data = lcall("GetGameModes");
+ mode_data.forEach(d => {
+ gameModeList.append(d);
+ });
+ }
+ }
+ function filterRoom() {
+ let f = config.preferredFilter;
+
+ f.name = name.text;
+ f.id = id.text;
+
+ // mode
+ let modeList = [];
+ if (parentModeBox.checkState === Qt.PartiallyChecked) {
+ for (let index = 0; index < modes.count; index++) {
+ var tCheckBox = modes.itemAt(index)
+ if (tCheckBox.checked) {modeList.push(tCheckBox.text)}
+ }
+ }
+ f.modes = modeList;
+
+ f.full = parentFullBox.checkState === Qt.PartiallyChecked ? (fullStates.itemAt(0).checked ? 0 : 1) : 2;
+ f.hasPassword = parentPwBox.checkState === Qt.PartiallyChecked ? (pwStates.itemAt(0).checked ? 0 : 1) : 2;
+
+ // capacity
+ /*
+ let capacityList = [];
+ if (parentCapacityBox.checkState === Qt.PartiallyChecked) {
+ for (let index = 0; index < capacityStates.count; index++) {
+ var nCheckBox = capacityStates.itemAt(index)
+ if (nCheckBox.checked) {capacityList.push(parseInt(nCheckBox.text))}
+ }
+ }
+ */
+
+ config.preferredFilterChanged();
+
+ for (let i = roomModel.count - 1; i >= 0; i--) {
+ const r = roomModel.get(i);
+ if ((name.text !== '' && !r.roomName.includes(name.text))
+ || (id.text !== '' && !r.roomId.toString().includes(id.text))
+ || (modeList.length > 0 && !modeList.includes(luatr(r.gameMode)))
+ || (f.full !== 2 &&
+ (f.full === 0 ? r.playerNum < r.capacity : r.playerNum >= r.capacity))
+ || (f.hasPassword !== 2 &&
+ (f.hasPassword === 0 ? !r.hasPassword : r.hasPassword))
+ // || (capacityList.length > 0 && !capacityList.includes(r.capacity))
+ ) {
+ roomModel.remove(i);
+ }
+ }
+ }
+}
diff --git a/Fk/LobbyElement/RoomPackageSettings.qml b/Fk/LobbyElement/RoomPackageSettings.qml
index 3b03385b..33256d96 100644
--- a/Fk/LobbyElement/RoomPackageSettings.qml
+++ b/Fk/LobbyElement/RoomPackageSettings.qml
@@ -22,9 +22,11 @@ Flickable {
anchors.top: parent.top
anchors.topMargin: 8
+ /*
Switch {
text: luatr("Disable Extension")
}
+ */
RowLayout {
Text {
diff --git a/Fk/LobbyElement/qmldir b/Fk/LobbyElement/qmldir
index 8e3b854b..5e7c6c35 100644
--- a/Fk/LobbyElement/qmldir
+++ b/Fk/LobbyElement/qmldir
@@ -1,8 +1,10 @@
module Fk.LobbyElement
AudioSetting 1.0 AudioSetting.qml
+BanGeneralSetting 1.0 BanGeneralSetting.qml
BGSetting 1.0 BGSetting.qml
CreateRoom 1.0 CreateRoom.qml
EditProfile 1.0 EditProfile.qml
+FilterRoom 1.0 FilterRoom.qml
PersonalSettings 1.0 PersonalSettings.qml
RoomGeneralSettings 1.0 RoomGeneralSettings.qml
RoomPackageSettings 1.0 RoomPackageSettings.qml
diff --git a/Fk/Pages/CardsOverview.qml b/Fk/Pages/CardsOverview.qml
index 8b8de045..a63a81c5 100644
--- a/Fk/Pages/CardsOverview.qml
+++ b/Fk/Pages/CardsOverview.qml
@@ -8,6 +8,7 @@ import Fk.RoomElement
Item {
id: root
+ objectName: "CardsOverview"
property bool loaded: false
@@ -196,6 +197,7 @@ Item {
property var cards
function updateCard() {
const data = lcall("GetCardData", cid);
+ detailFlickable.contentY = 0; // 重置滚动条
const suitTable = {
spade: "♠", heart: '♥',
club: "♣", diamond: '♦',
@@ -234,6 +236,7 @@ Item {
}
Flickable {
+ id: detailFlickable
flickableDirection: Flickable.VerticalFlick
contentHeight: detailLayout.height
width: parent.width - 40
@@ -323,6 +326,7 @@ Item {
Button {
text: luatr("Quit")
anchors.right: parent.right
+ visible: mainStack.currentItem.objectName === "CardsOverview"
onClicked: {
mainStack.pop();
}
diff --git a/Fk/Pages/GeneralsOverview.qml b/Fk/Pages/GeneralsOverview.qml
index 88a190a4..08cc9cfa 100644
--- a/Fk/Pages/GeneralsOverview.qml
+++ b/Fk/Pages/GeneralsOverview.qml
@@ -9,6 +9,7 @@ import "RoomLogic.js" as RoomLogic
Item {
id: root
+ objectName: "GeneralsOverview"
property bool loaded: false
property int stat: 0 // 0=normal 1=banPkg 2=banChara
@@ -165,6 +166,7 @@ Item {
return luatr("BanGeneral");
}
enabled: stat !== 1
+ visible: mainStack.currentItem.objectName === "GeneralsOverview"
onClicked: {
if (stat === 0) {
stat = 2;
@@ -182,6 +184,7 @@ Item {
return luatr("BanPackage");
}
enabled: stat !== 2
+ visible: mainStack.currentItem.objectName === "GeneralsOverview"
onClicked: {
if (stat === 0) {
stat = 1;
@@ -194,6 +197,7 @@ Item {
ToolButton {
text: luatr("Quit")
font.pixelSize: 20
+ visible: mainStack.currentItem.objectName === "GeneralsOverview"
onClicked: {
mainStack.pop();
config.saveConf();
@@ -283,9 +287,9 @@ Item {
const gdata = lcall("GetGeneralData", modelData);
const pack = gdata.package;
if (s.banPkg[pack]) {
- if (s.banPkg[pack].includes(modelData)) return '启用';
+ if (s.banPkg[pack].includes(modelData)) return luatr('Enable');
} else {
- if (!!s.normalPkg[pack]?.includes(modelData)) return '禁';
+ if (!!s.normalPkg[pack]?.includes(modelData)) return luatr('Prohibit');
}
}
anchors.centerIn: parent
@@ -370,17 +374,9 @@ Item {
Text {
Layout.fillWidth: true
text: {
- const orig = '$' + name + (idx ? idx.toString() : "");
- const orig_trans = luatr(orig);
-
- // try general specific
- const orig_g = '$' + name + '_' + detailGeneralCard.name
+ const orig = '$' + name + (specific ? '_' + detailGeneralCard.name : "")
+ (idx ? idx.toString() : "");
- const orig_g_trans = luatr(orig_g);
-
- if (orig_g_trans !== orig_g) {
- return orig_g_trans;
- }
+ const orig_trans = luatr(orig);
if (orig_trans !== orig) {
return orig_trans;
@@ -396,10 +392,51 @@ Item {
callbacks["LogEvent"]({
type: "PlaySkillSound",
name: name,
- general: detailGeneralCard.name,
+ general: specific ? detailGeneralCard.name : null, // 分化特别和一般
i: idx,
});
}
+
+ onPressAndHold: {
+ Backend.copyToClipboard('$' + name + (specific ? '_' + detailGeneralCard.name : "")
+ + (idx ? idx.toString() : "") + ':');
+ toast.show(luatr("Audio Code Copy Success"));
+ }
+
+ ToolButton {
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ visible: parent.hovered
+ text: "⋮"
+ onClicked: {
+ if (skillAudioMenu.visible){
+ skillAudioMenu.close();
+ } else {
+ skillAudioMenu.open();
+ }
+ }
+ Menu {
+ id: skillAudioMenu
+ MenuItem {
+ text: luatr("Copy Audio Code")
+ onTriggered: {
+ Backend.copyToClipboard('$' + name + (specific ? '_' + detailGeneralCard.name : "")
+ + (idx ? idx.toString() : "") + ':');
+ toast.show(luatr("Audio Code Copy Success"));
+ }
+ }
+ MenuItem {
+ text: luatr("Copy Audio Text")
+ onTriggered: {
+ Backend.copyToClipboard(luatr('$' + name + (specific ? '_' + detailGeneralCard.name : "")
+ + (idx ? idx.toString() : "")));
+ toast.show(luatr("Audio Text Copy Success"));
+ }
+ }
+ }
+ }
}
}
@@ -427,7 +464,7 @@ Item {
if (Backend.exists(fname)) {
ret = true;
- audioModel.append({ name: skill, idx: i });
+ audioModel.append({ name: skill, idx: i, specific: true });
} else {
if (i > 0) break;
}
@@ -445,7 +482,7 @@ Item {
skill + (i !== 0 ? i.toString() : "") + ".mp3";
if (Backend.exists(fname)) {
- audioModel.append({ name: skill, idx: i });
+ audioModel.append({ name: skill, idx: i, specific: false});
} else {
if (i > 0) break;
}
@@ -465,6 +502,7 @@ Item {
function updateGeneral() {
detailGeneralCard.name = general;
+ detailFlickable.contentY = 0; // 重置滚动条
const data = lcall("GetGeneralDetail", general);
generalText.clear();
audioModel.clear();
@@ -479,14 +517,8 @@ Item {
}
data.skill.forEach(t => {
- generalText.append("" + luatr(t.name) +
- ": " + t.description);
-
- addSkillAudio(t.name);
- });
- data.related_skill.forEach(t => {
- generalText.append("" + luatr(t.name) +
- ": " + t.description + "");
+ generalText.append((t.is_related_skill ? "" : "") + luatr(t.name) +
+ ": " + t.description + (t.is_related_skill ? "" : ""));
addSkillAudio(t.name);
});
@@ -521,6 +553,8 @@ Item {
wrapMode: Text.WordWrap
textFormat: TextEdit.RichText
font.pixelSize: 16
+ lineHeight: 21
+ lineHeightMode: Text.FixedHeight
function trans(str) {
const ret = luatr(str);
if (ret === str) {
@@ -530,13 +564,18 @@ Item {
}
text: {
const general = generalDetail.general;
- return [
- luatr(lcall("GetGeneralData", general).package),
+ const gdata = lcall("GetGeneralData", general);
+ let ret = [
+ luatr(gdata.package),
luatr("Title") + trans("#" + general),
luatr("Designer") + trans("designer:" + general),
luatr("Voice Actor") + trans("cv:" + general),
luatr("Illustrator") + trans("illustrator:" + general),
].join("
");
+ if (gdata.hidden) {
+ ret += "
" + luatr("Hidden General") + "";
+ }
+ return ret;
}
}
@@ -547,6 +586,7 @@ Item {
Button {
text: luatr("Set as Avatar")
+ visible: mainStack.currentItem.objectName === "GeneralsOverview"
enabled: detailGeneralCard.name !== "" && !opTimer.running
&& Self.avatar !== detailGeneralCard.name
onClicked: {
@@ -562,6 +602,7 @@ Item {
}
Flickable {
+ id: detailFlickable
flickableDirection: Flickable.VerticalFlick
contentHeight: detailLayout.height
width: parent.width - 40 - generalInfo.width
@@ -628,6 +669,44 @@ Item {
Backend.playSound("./packages/" + extension + "/audio/death/"
+ general);
}
+
+ onPressAndHold: {
+ Backend.copyToClipboard("$~" + generalDetail.general);
+ toast.show(luatr("Audio Code Copy Success"));
+ }
+
+ ToolButton {
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ visible: parent.hovered
+ text: "⋮"
+ onClicked: {
+ if (deathAudioMenu.visible){
+ deathAudioMenu.close();
+ } else {
+ deathAudioMenu.open();
+ }
+ }
+ Menu {
+ id: deathAudioMenu
+ MenuItem {
+ text: luatr("Copy Audio Code")
+ onTriggered: {
+ Backend.copyToClipboard("$~" + generalDetail.general);
+ toast.show(luatr("Audio Code Copy Success"));
+ }
+ }
+ MenuItem {
+ text: luatr("Copy Audio Text")
+ onTriggered: {
+ Backend.copyToClipboard(luatr("~" + generalDetail.general));
+ toast.show(luatr("Audio Text Copy Success"));
+ }
+ }
+ }
+ }
}
}
}
diff --git a/Fk/Pages/JoinServer.qml b/Fk/Pages/JoinServer.qml
index 35582bb5..e950c958 100644
--- a/Fk/Pages/JoinServer.qml
+++ b/Fk/Pages/JoinServer.qml
@@ -102,6 +102,32 @@ Item {
}
}
+ ToolButton {
+ x: parent.width - 32
+ y: parent.height / 2 - 8
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ visible: !!favorite
+ text: "⋮"
+ onClicked: {
+ if (menu.visible){
+ menu.close();
+ } else {
+ menu.open();
+ }
+ }
+
+ Menu {
+ id: menu
+ MenuItem {
+ text: qsTr("Remove from Favorites")
+ onTriggered: {
+ removeFavorite(addr, port);
+ }
+ }
+ }
+ }
+
ColumnLayout {
x: 6
height: parent.height
@@ -125,7 +151,7 @@ Item {
height: childrenRect.height
width: serverList.width
Text {
- text: "已收藏服务器与公共服务器列表"
+ text: qsTr("List of Favorites and Public Servers")
font.pixelSize: 18
x: 32; y: 8
}
@@ -170,14 +196,14 @@ Item {
id: addressEdit
maximumLength: 64
Layout.fillWidth: true
- placeholderText: "服务器地址"
+ placeholderText: qsTr("Server Address")
text: selectedServer?.addr ?? ""
}
TextField {
id: portEdit
maximumLength: 6
Layout.fillWidth: true
- placeholderText: "端口"
+ placeholderText: qsTr("Port")
text: selectedServer?.port ?? ""
}
Flickable {
@@ -199,21 +225,21 @@ Item {
id: usernameEdit
maximumLength: 32
Layout.fillWidth: true
- placeholderText: "用户名"
+ placeholderText: qsTr("Username")
text: selectedServer?.username ?? ""
}
TextField {
id: passwordEdit
maximumLength: 32
Layout.fillWidth: true
- placeholderText: "密码"
+ placeholderText: qsTr("Password")
passwordCharacter: "*"
echoMode: TextInput.Password
text: selectedServer?.password ?? ""
}
}
Button {
- text: "登录(首次登录自动注册)"
+ text: qsTr("LOGIN (Auto-registration)")
Layout.fillWidth: true
enabled: !!(addressEdit.text && portEdit.text &&
usernameEdit.text && passwordEdit.text)
@@ -237,9 +263,9 @@ Item {
}
}
Button {
- text: "从收藏夹删除"
+ text: qsTr("Remove from Favorites")
Layout.fillWidth: true
- visible: !!(selectedServer?.favorite)
+ visible: false // !!(selectedServer?.favorite) // 暂时禁用
onClicked: {
removeFavorite(selectedServer.addr, selectedServer.port);
}
diff --git a/Fk/Pages/Lobby.qml b/Fk/Pages/Lobby.qml
index 63de27e9..0c3ae593 100644
--- a/Fk/Pages/Lobby.qml
+++ b/Fk/Pages/Lobby.qml
@@ -35,6 +35,7 @@ Item {
text: roomName
// color: outdated ? "gray" : "black"
font.pixelSize: 16
+ font.strikeout: outdated
// elide: Label.ElideRight
anchors.top: parent.top
anchors.left: parent.left
@@ -44,6 +45,7 @@ Item {
Text {
id: roomIdText
text: luatr(gameMode) + ' #' + roomId
+ font.strikeout: outdated
anchors.top: roomNameText.bottom
anchors.left: roomNameText.left
}
@@ -119,7 +121,7 @@ Item {
text: "在未来的版本中这一块区域将增加更多实用的功能,
"+
"例如直接查看房间的各种配置信息
"+
"以及更多与禁将有关的实用功能!"+
- "注:绿色按钮为试做型UI 后面优化"
+ "注:灰色按钮为试做型UI 后面优化"
font.pixelSize: 18
}
@@ -195,6 +197,13 @@ Item {
ClientInstance.notifyServer("RefreshRoomList", "");
}
}
+ Button {
+ text: luatr("Filter")
+ onClicked: {
+ lobby_dialog.sourceComponent = Qt.createComponent("../LobbyElement/FilterRoom.qml"); //roomFilterDialog;
+ lobby_drawer.open();
+ }
+ }
Button {
text: luatr("Create Room")
onClicked: {
@@ -313,7 +322,7 @@ Item {
}
}
Button {
- text: luatr("Scenarios Overview")
+ text: luatr("Modes Overview")
onClicked: {
mainStack.push(mainWindow.modesOverviewPage);
}
diff --git a/Fk/Pages/MetroButton.qml b/Fk/Pages/MetroButton.qml
index b602ce26..00412e15 100644
--- a/Fk/Pages/MetroButton.qml
+++ b/Fk/Pages/MetroButton.qml
@@ -13,6 +13,7 @@ Item {
property int padding: 5
signal clicked
+ signal rightClicked
id: button
width: icon.width + title.implicitWidth + padding * 2
@@ -44,7 +45,19 @@ Item {
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.NoButton
gesturePolicy: TapHandler.WithinBounds
- onTapped: if (parent.enabled) parent.clicked()
+ onTapped: (p, btn) => {
+ if (parent.enabled) {
+ if (btn === Qt.LeftButton || btn === Qt.NoButton) {
+ parent.clicked();
+ } else if (btn === Qt.RightButton) {
+ parent.rightClicked();
+ }
+ }
+ }
+
+ onLongPressed: {
+ parent.rightClicked();
+ }
}
HoverHandler {
diff --git a/Fk/Pages/ModesOverview.qml b/Fk/Pages/ModesOverview.qml
index d97c84a5..e6cf0034 100644
--- a/Fk/Pages/ModesOverview.qml
+++ b/Fk/Pages/ModesOverview.qml
@@ -5,6 +5,7 @@ import QtQuick.Layouts
import QtQuick.Controls
Item {
+ objectName: "ModesOverview"
RowLayout {
anchors.fill: parent
spacing: 10
@@ -30,6 +31,7 @@ Item {
TapHandler {
onTapped: {
listView.currentIndex = index;
+ detailFlickable.contentY = 0; // 重置滚动条
}
}
}
@@ -40,6 +42,7 @@ Item {
Layout.fillHeight: true
color: "#88EEEEEE"
Flickable {
+ id: detailFlickable
width: parent.width - 16
height: parent.height - 16
anchors.centerIn: parent
@@ -62,6 +65,7 @@ Item {
Button {
text: luatr("Quit")
anchors.bottom: parent.bottom
+ visible: mainStack.currentItem.objectName === "ModesOverview"
onClicked: {
mainStack.pop();
}
@@ -72,5 +76,6 @@ Item {
for (let d of mode_data) {
modeList.append(d);
}
+ listView.currentIndex = 0;
}
}
diff --git a/Fk/Pages/Room.qml b/Fk/Pages/Room.qml
index 9928829a..dc12f962 100644
--- a/Fk/Pages/Room.qml
+++ b/Fk/Pages/Room.qml
@@ -100,11 +100,12 @@ Item {
Menu {
id: menuContainer
y: menuButton.height - 12
- width: 100
+ width: parent.width * 1.8
MenuItem {
id: quitButton
text: luatr("Quit")
+ icon.source: AppPath + "/image/modmaker/back"
onClicked: {
if (config.replaying) {
Backend.controlReplayer("shutdown");
@@ -117,10 +118,57 @@ Item {
}
}
+ MenuItem {
+ id: volumeButton
+ text: luatr("Audio Settings")
+ icon.source: AppPath + "/image/button/tileicon/configure"
+ onClicked: {
+ volumeDialog.open();
+ }
+ }
+
+ Menu {
+ title: luatr("Overview")
+ icon.source: AppPath + "/image/button/tileicon/rule_summary"
+ icon.width: 24
+ icon.height: 24
+ icon.color: palette.windowText
+ MenuItem {
+ id: generalButton
+ text: luatr("Generals Overview")
+ icon.source: AppPath + "/image/button/tileicon/general_overview"
+ onClicked: {
+ overviewLoader.overviewType = "Generals";
+ overviewDialog.open();
+ overviewLoader.item.loadPackages();
+ }
+ }
+ MenuItem {
+ id: cardslButton
+ text: luatr("Cards Overview")
+ icon.source: AppPath + "/image/button/tileicon/card_overview"
+ onClicked: {
+ overviewLoader.overviewType = "Cards";
+ overviewDialog.open();
+ overviewLoader.item.loadPackages();
+ }
+ }
+ MenuItem {
+ id: modesButton
+ text: luatr("Modes Overview")
+ icon.source: AppPath + "/image/misc/paper"
+ onClicked: {
+ overviewLoader.overviewType = "Modes";
+ overviewDialog.open();
+ }
+ }
+ }
+
MenuItem {
id: surrenderButton
- enabled: !config.observing && !config.replaying
+ enabled: !config.observing && !config.replaying && isStarted
text: luatr("Surrender")
+ icon.source: AppPath + "/image/misc/surrender"
onClicked: {
const photo = getPhoto(Self.id);
if (isStarted && !(photo.dead && photo.rest <= 0)) {
@@ -130,21 +178,13 @@ Item {
luatr('Surrender is disabled in this mode');
} else {
surrenderDialog.informativeText = surrenderCheck
- .map(str => `${luatr(str.text)}(${str.passed ? '√' : '×'})`)
+ .map(str => `${luatr(str.text)}(${str.passed ? '✓' : '✗'})`)
.join('
');
}
surrenderDialog.open();
}
}
}
-
- MenuItem {
- id: volumeButton
- text: luatr("Audio Settings")
- onClicked: {
- volumeDialog.open();
- }
- }
}
}
@@ -468,7 +508,68 @@ Item {
MetroButton {
text: luatr("Sort Cards")
textFont.pixelSize: 28
- onClicked: Logic.resortHandcards();
+ onClicked: {
+ if (lcall("CanSortHandcards", Self.id)) {
+ let sortMethods = [];
+ for (let index = 0; index < sortMenuRepeater.count; index++) {
+ var tCheckBox = sortMenuRepeater.itemAt(index)
+ sortMethods.push(tCheckBox.checked)
+ }
+ Logic.sortHandcards(sortMethods);
+ }
+ }
+
+ onRightClicked: {
+ if (sortMenu.visible) {
+ sortMenu.close();
+ } else {
+ sortMenu.open();
+ }
+ }
+
+ Menu {
+ id: sortMenu
+ x: parent.width
+ y: -25
+ width: parent.width * 2
+ background: Rectangle {
+ color: "black"
+ border.width: 3
+ border.color: "white"
+ opacity: 0.8
+ }
+
+ Repeater {
+ id: sortMenuRepeater
+ model: ["Sort by Type", "Sort by Number", "Sort by Suit"]
+
+ CheckBox {
+ id: control
+ text: "" + luatr(modelData) + ""
+ checked: modelData === "Sort by Type"
+ font.pixelSize: 20
+
+ indicator: Rectangle {
+ implicitWidth: 26
+ implicitHeight: 26
+ x: control.leftPadding
+ y: control.height / 2 - height / 2
+ radius: 3
+ border.color: "white"
+
+ Rectangle {
+ width: 14
+ height: 14
+ x: 6
+ y: 6
+ radius: 2
+ color: control.down ? "#17a81a" : "#21be2b"
+ visible: control.checked
+ }
+ }
+ }
+ }
+ }
}
MetroButton {
text: luatr("Chat")
@@ -994,6 +1095,28 @@ Item {
}
}
+ Popup {
+ id: overviewDialog
+ width: realMainWin.width * 0.75
+ height: realMainWin.height * 0.75
+ anchors.centerIn: parent
+ background: Rectangle {
+ color: "#EEEEEEEE"
+ radius: 5
+ border.color: "#A6967A"
+ border.width: 1
+ }
+ Loader {
+ id: overviewLoader
+ property string overviewType: "Generals"
+ anchors.centerIn: parent
+ width: parent.width / mainWindow.scale
+ height: parent.height / mainWindow.scale
+ scale: mainWindow.scale
+ source: AppPath + "/Fk/Pages/" + overviewType + "Overview.qml"
+ }
+ }
+
GlowText {
anchors.centerIn: dashboard
visible: Logic.getPhoto(Self.id).rest > 0 && !config.observing
@@ -1127,6 +1250,8 @@ Item {
const general = luatr(data.general);
if (msg.startsWith("!")) {
+ if (config.hidePresents)
+ return true;
const splited = msg.split(":");
const type = splited[0].slice(1);
switch (type) {
diff --git a/Fk/Pages/RoomLogic.js b/Fk/Pages/RoomLogic.js
index a49e60aa..605f628e 100644
--- a/Fk/Pages/RoomLogic.js
+++ b/Fk/Pages/RoomLogic.js
@@ -297,13 +297,27 @@ function moveCards(moves) {
}
}
+const suitInteger = {
+ spade: 1, heart: 3,
+ club: 2, diamond: 4,
+}
-
-function resortHandcards() {
+function sortHandcards(sortMethods) {
if (!dashboard.handcardArea.cards.length) {
return;
}
+ const cardType = sortMethods[0];
+ const cardNum = sortMethods[1];
+ const cardSuit = sortMethods[2];
+
+ if (!cardType && !cardNum && !cardSuit) {
+ return;
+ }
+
+ let sortOutputs = [];
+ let sortedStatus = [];
+
const subtypeString2Number = {
["none"]: Card.SubtypeNone,
["delayed_trick"]: Card.SubtypeDelayedTrick,
@@ -318,51 +332,61 @@ function resortHandcards() {
return c.cid;
})
- dashboard.handcardArea.cards.sort((prev, next) => {
- if (prev.footnote === next.footnote) {
- if (prev.type === next.type) {
- const prevSubtypeNumber = subtypeString2Number[prev.subtype];
- const nextSubtypeNumber = subtypeString2Number[next.subtype];
- if (prevSubtypeNumber === nextSubtypeNumber) {
- const splitedPrevName = prev.name.split('__');
- const prevTrueName = splitedPrevName[splitedPrevName.length - 1];
+ let sortedByType = true;
+ let handcards
+ if (cardType) {
+ handcards = dashboard.handcardArea.cards.slice(0);
+ handcards.sort((prev, next) => {
+ if (prev.footnote === next.footnote) {
+ if (prev.type === next.type) {
+ const prevSubtypeNumber = subtypeString2Number[prev.subtype];
+ const nextSubtypeNumber = subtypeString2Number[next.subtype];
+ if (prevSubtypeNumber === nextSubtypeNumber) {
+ const splitedPrevName = prev.name.split('__');
+ const prevTrueName = splitedPrevName[splitedPrevName.length - 1];
- const splitedNextName = next.name.split('__');
- const nextTrueName = splitedNextName[splitedNextName.length - 1];
- if (prevTrueName === nextTrueName) {
- return prev.cid - next.cid;
+ const splitedNextName = next.name.split('__');
+ const nextTrueName = splitedNextName[splitedNextName.length - 1];
+ if (prevTrueName === nextTrueName) {
+ return prev.cid - next.cid;
+ } else {
+ return prevTrueName > nextTrueName ? -1 : 1;
+ }
} else {
- return prevTrueName > nextTrueName ? -1 : 1;
+ return prevSubtypeNumber - nextSubtypeNumber;
}
} else {
- return prevSubtypeNumber - nextSubtypeNumber;
+ return prev.type - next.type;
}
} else {
- return prev.type - next.type;
+ return prev.footnote > next.footnote ? 1 : -1;
}
- } else {
- return prev.footnote > next.footnote ? 1 : -1;
- }
- });
+ });
- let i = 0;
- let resort = true;
- dashboard.handcardArea.cards.forEach(c => {
- if (hand[i] !== c.cid) {
- resort = false;
- return;
- }
- i++;
- })
+ // Check if the cards are sorted by type
+ let i = 0;
+ handcards.every(c => {
+ if (hand[i] !== c.cid) {
+ sortedByType = false;
+ return false;
+ }
+ i++;
+ return true;
+ })
+ sortOutputs.push(handcards);
+ sortedStatus.push(sortedByType);
+ }
- if (resort) {
- dashboard.handcardArea.cards.sort((prev, next) => {
+ let sortedByNum = true;
+ if (cardNum) {
+ handcards = dashboard.handcardArea.cards.slice(0);
+ handcards.sort((prev, next) => {
if (prev.footnote === next.footnote) {
- if (prev.number === next.number) { // 按点数排
- if (prev.suit === next.suit) {
+ if (prev.number === next.number) {
+ if (suitInteger[prev.suit] === suitInteger[next.suit]) {
return prev.cid - next.cid;
} else {
- return prev.suit - next.suit;
+ return suitInteger[prev.suit] - suitInteger[next.suit];
}
} else {
return prev.number - next.number;
@@ -371,8 +395,61 @@ function resortHandcards() {
return prev.footnote > next.footnote ? 1 : -1;
}
});
+
+ let i = 0;
+ handcards.every(c => {
+ if (hand[i] !== c.cid) {
+ sortedByNum = false;
+ return false;
+ }
+ i++;
+ return true;
+ })
+ sortOutputs.push(handcards);
+ sortedStatus.push(sortedByNum);
}
+ let sortedBySuit = true;
+ if (cardSuit) {
+ handcards = dashboard.handcardArea.cards.slice(0);
+ handcards.sort((prev, next) => {
+ if (prev.footnote === next.footnote) {
+ if (suitInteger[prev.suit] === suitInteger[next.suit]) {
+ if (prev.number === next.number) {
+ return prev.cid - next.cid;
+ } else {
+ return prev.number - next.number;
+ }
+ } else {
+ return suitInteger[prev.suit] - suitInteger[next.suit];
+ }
+ } else {
+ return prev.footnote > next.footnote ? 1 : -1;
+ }
+ });
+
+ let i = 0;
+ handcards.every(c => {
+ if (hand[i] !== c.cid) {
+ sortedBySuit = false;
+ return false;
+ }
+ i++;
+ return true;
+ })
+ sortOutputs.push(handcards);
+ sortedStatus.push(sortedBySuit);
+ }
+ let output
+ for (let i = 0; i < sortedStatus.length; i++) {
+ if (sortedStatus[i]) {
+ let j = i < sortedStatus.length - 1 ? i + 1 : 0;
+ output = sortOutputs[j];
+ break;
+ }
+ }
+ if (!output) output = sortOutputs[0];
+ dashboard.handcardArea.cards = output;
dashboard.handcardArea.updateCardPosition(true);
}
@@ -933,6 +1010,18 @@ callbacks["UpdateCard"] = (j) => {
card.setData(lcall("GetCardData", id));
}
+callbacks["UpdateSkill"] = (j) => {
+ const all_skills = [roomScene.dashboard.skillButtons, roomScene.dashboard.notActiveButtons];
+ for (const skills of all_skills) {
+ for (let i = 0; i < skills.count; i++) {
+ const item = skills.itemAt(i);
+ const dat = lcall("GetSkillStatus", item.orig);
+ item.locked = dat.locked;
+ item.times = dat.times;
+ }
+ }
+}
+
callbacks["StartGame"] = (jsonData) => {
roomScene.isStarted = true;
diff --git a/Fk/RoomElement/ArrangeCardsBox.qml b/Fk/RoomElement/ArrangeCardsBox.qml
index 66b937d9..5b31ed62 100644
--- a/Fk/RoomElement/ArrangeCardsBox.qml
+++ b/Fk/RoomElement/ArrangeCardsBox.qml
@@ -82,8 +82,7 @@ GraphicsBox {
}
Row {
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
+ Layout.alignment: Qt.AlignHCenter
spacing: 32
MetroButton {
diff --git a/Fk/RoomElement/CardItem.qml b/Fk/RoomElement/CardItem.qml
index d00a51a6..e1c6ccd2 100644
--- a/Fk/RoomElement/CardItem.qml
+++ b/Fk/RoomElement/CardItem.qml
@@ -69,7 +69,7 @@ Item {
signal rightClicked()
signal doubleClicked()
signal thrown()
- signal released()
+ signal released(var card)
signal entered()
signal exited()
signal moveFinished()
@@ -287,7 +287,7 @@ Item {
onGrabChanged: (transtition, point) => {
if (transtition !== PointerDevice.UngrabExclusive) return;
- parent.released();
+ parent.released(root);
if (autoBack)
goBackAnimation.start();
}
diff --git a/Fk/RoomElement/Dashboard.qml b/Fk/RoomElement/Dashboard.qml
index 6ab8b42c..e5199b19 100644
--- a/Fk/RoomElement/Dashboard.qml
+++ b/Fk/RoomElement/Dashboard.qml
@@ -17,6 +17,7 @@ RowLayout {
property int selected_card: -1
property alias skillButtons: skillPanel.skill_buttons
+ property alias notActiveButtons: skillPanel.not_active_buttons
property var expanded_piles: ({}) // name -> int[]
property var extra_cards: []
diff --git a/Fk/RoomElement/GlowText.qml b/Fk/RoomElement/GlowText.qml
index 16e4c3c8..59cda0ee 100644
--- a/Fk/RoomElement/GlowText.qml
+++ b/Fk/RoomElement/GlowText.qml
@@ -13,6 +13,7 @@ Item {
property alias style: textItem.style
property alias styleColor: textItem.styleColor
property alias wrapMode: textItem.wrapMode
+ property alias elide: textItem.elide
property alias lineHeight: textItem.lineHeight
property alias glow: glowItem
diff --git a/Fk/RoomElement/HandcardArea.qml b/Fk/RoomElement/HandcardArea.qml
index 3cd0b53f..648445cc 100644
--- a/Fk/RoomElement/HandcardArea.qml
+++ b/Fk/RoomElement/HandcardArea.qml
@@ -7,6 +7,7 @@ Item {
property alias cards: cardArea.cards
property alias length: cardArea.length
property var selectedCards: []
+ property var movepos
signal cardSelected(int cardId, bool selected)
@@ -32,9 +33,11 @@ Item {
function filterInputCard(card)
{
card.autoBack = true;
- card.draggable = true;
+ card.draggable = lcall("CanSortHandcards", Self.id);
card.selectable = false;
card.clicked.connect(adjustCards);
+ card.released.connect(updateCardReleased);
+ card.xChanged.connect(updateCardDragging);
}
function remove(outputs)
@@ -46,6 +49,8 @@ Item {
card.draggable = false;
card.selectable = false;
card.selectedChanged.disconnect(adjustCards);
+ card.released.disconnect(updateCardReleased);
+ card.xChanged.disconnect(updateCardDragging);
card.prohibitReason = "";
}
return result;
@@ -84,6 +89,49 @@ Item {
}
}
+ function updateCardDragging()
+ {
+ let _card, c;
+ let index;
+ for (index = 0; index < cards.length; index++) {
+ c = cards[index];
+ if (c.dragging) {
+ _card = c;
+ break;
+ }
+ }
+ if (!_card) return;
+ _card.goBackAnim.stop();
+ _card.opacity = 0.8
+
+ let card;
+ movepos = null;
+ for (let i = 0; i < cards.length; i++) {
+ card = cards[i];
+ if (card.dragging) continue;
+
+ if (card.x > _card.x) {
+ movepos = i - (index < i ? 1 : 0);
+ break;
+ }
+ }
+ if (movepos == null) { // 最右
+ movepos = cards.length;
+ }
+ }
+
+ function updateCardReleased(_card)
+ {
+ let i;
+ if (movepos != null) {
+ i = cards.indexOf(_card);
+ cards.splice(i, 1);
+ cards.splice(movepos, 0, _card);
+ movepos = null;
+ }
+ updateCardPosition(true);
+ }
+
function adjustCards()
{
area.updateCardPosition(true);
diff --git a/Fk/RoomElement/Photo.qml b/Fk/RoomElement/Photo.qml
index 9d7ebee4..cc918540 100644
--- a/Fk/RoomElement/Photo.qml
+++ b/Fk/RoomElement/Photo.qml
@@ -566,6 +566,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 2
+ width: parent.width - role.width - hp.width - 20
font.pixelSize: 16
text: {
@@ -574,7 +575,8 @@ Item {
ret = luatr(" ") + ret;
return ret;
}
-
+ elide: root.playerid === Self.id ? Text.ElideNone : Text.ElideMiddle
+ horizontalAlignment: Qt.AlignHCenter
glow.radius: 8
}
diff --git a/Fk/RoomElement/SkillArea.qml b/Fk/RoomElement/SkillArea.qml
index 42c08542..1028d00f 100644
--- a/Fk/RoomElement/SkillArea.qml
+++ b/Fk/RoomElement/SkillArea.qml
@@ -7,6 +7,7 @@ Flickable {
id: root
property alias skill_buttons: skill_buttons
property alias prelight_buttons: prelight_buttons
+ property alias not_active_buttons: not_active_buttons
clip: true
contentWidth: panel.width
@@ -91,6 +92,7 @@ Flickable {
columnSpacing: 2
rowSpacing: 2
Repeater {
+ id: not_active_buttons
model: not_active_skills
onItemAdded: parent.forceLayout()
SkillButton {
diff --git a/Fk/RoomElement/SkillButton.qml b/Fk/RoomElement/SkillButton.qml
index 09316bfe..ba4138bd 100644
--- a/Fk/RoomElement/SkillButton.qml
+++ b/Fk/RoomElement/SkillButton.qml
@@ -11,6 +11,8 @@ Item {
property string orig: ""
property bool pressed: false
property bool prelighted: false
+ property bool locked: false
+ property int times: -1
onEnabledChanged: {
if (!enabled)
@@ -86,6 +88,76 @@ Item {
}
}
+ Image {
+ source: AppPath + "/image/button/skill/locked.png"
+ scale: 0.8
+ z: 2
+ visible: root.locked
+ opacity: 0.8
+ anchors.centerIn: parent
+ }
+
+ Item {
+ width: 12
+ height: 12
+ visible: root.times > -1
+ anchors.right: parent.right
+ anchors.rightMargin: type === "notactive" ? -13 : 5
+ anchors.top: parent.top
+ anchors.topMargin: 5
+
+ Rectangle {
+ width: Math.max(15, 1.4 * count.contentWidth)
+ height: 15
+ radius: width * 0.5
+ x: (parent.width - width) / 2
+ y: -1.5
+ color: "transparent"
+ border.color: "#D2AD4A"
+ border.width: 1.1
+ }
+
+ Text {
+ id: count
+ anchors.centerIn: parent
+ font.pixelSize: 16
+ font.family: fontLibian.name
+ font.bold: true
+ text: root.times
+ z: 1.5
+ }
+
+ Glow {
+ source: count
+ anchors.fill: count
+ color: "black"
+ spread: 0.3
+ radius: 5
+ }
+
+ LinearGradient {
+ anchors.fill: count
+ z: 3
+ source: count
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#FEF7C2"
+ }
+
+ GradientStop {
+ position: 0.8
+ color: "#D2AD4A"
+ }
+
+ GradientStop {
+ position: 1
+ color: "#BE9878"
+ }
+ }
+ }
+ }
+
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.NoButton
onTapped: (p, btn) => {
@@ -95,6 +167,10 @@ Item {
skillDetail.open();
}
}
+
+ onLongPressed: {
+ skillDetail.open();
+ }
}
Popup {
diff --git a/Fk/RoomElement/TablePile.qml b/Fk/RoomElement/TablePile.qml
index c6855d20..7de8d1ac 100644
--- a/Fk/RoomElement/TablePile.qml
+++ b/Fk/RoomElement/TablePile.qml
@@ -105,10 +105,10 @@ Item {
for (i = 0; i < outputs.length; i++) {
let exists = false;
for (j = 0; j < result.length; j++) {
- if (result[j].cid === outputs[i]) {
- exists = true;
- break;
- }
+ if (result[j].cid === outputs[i]) {
+ exists = true;
+ break;
+ }
}
if (!exists)
vanished.push(outputs[i]);
diff --git a/image/misc/paper.png b/image/misc/paper.png
new file mode 100644
index 00000000..6b636efc
Binary files /dev/null and b/image/misc/paper.png differ
diff --git a/image/misc/surrender.png b/image/misc/surrender.png
new file mode 100644
index 00000000..852d9c50
Binary files /dev/null and b/image/misc/surrender.png differ
diff --git a/include b/include
deleted file mode 160000
index 4fd2070d..00000000
--- a/include
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 4fd2070d099d1f967d1070d72beb0fae2cb6e4be
diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts
index 07173139..9133b542 100644
--- a/lang/zh_CN.ts
+++ b/lang/zh_CN.ts
@@ -227,6 +227,10 @@
编辑服务器
+
+
+ 已收藏服务器与公共服务器列表
+
刷新列表
@@ -239,6 +243,14 @@
返回
+
+
+ 服务器地址
+
+
+
+ 端口
+
@@ -286,6 +298,14 @@
删除服务器
+
+
+ 登录(首次登录自动注册)
+
+
+
+ 从收藏夹删除
+
@@ -549,8 +569,7 @@
新月杀本身默认只含标准包!<br>
想要体验更多武将,就要通过联机获取!<br>
- 在主界面点击“加入服务器” -> 添加服务器。<br>
- (目前推荐的服务器IP是175.178.66.93)
+ 在主界面点击“加入服务器” -> 进入公共服务器或添加新服务器。
@@ -561,8 +580,8 @@
- 更多指引可以去查阅下载链接附送的pdf。
- 这些pdf都是由开发者们编写的,不仅能让你快速掌握游戏的深入玩法,
+ 更多指引可以去查阅新月之书:<a href="https://fkbook-all-in-one.readthedocs.io">https://fkbook-all-in-one.readthedocs.io</a><br>。
+ 这些文档都是由开发者们编写的,不仅能让你快速掌握游戏的深入玩法,
还可以告诉你关于开设私服、制作拓展之类的知识。