UI (#290)
杀光侧栏 只留战报一个 Qml标记,以及一个割圆demo 自由选将增加搜索功能 room:setBanner,相当于公共标记了,客户端可以Fk:currentRoom():getBanner拿(当然服务端也可) 改掉两个很蠢的命名
This commit is contained in:
parent
8afe5122d7
commit
9a9fc9c105
|
@ -3,6 +3,7 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Fk.RoomElement
|
||||
|
||||
Flickable {
|
||||
id: root
|
||||
|
@ -14,16 +15,25 @@ Flickable {
|
|||
contentHeight: details.height
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
id: details
|
||||
width: parent.width - 40
|
||||
x: 20
|
||||
spacing: 20
|
||||
|
||||
// TODO: player details
|
||||
CardItem {
|
||||
id: cardPic
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.topMargin: 10
|
||||
cid: 0
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Text {
|
||||
id: screenName
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 18
|
||||
color: "#E4D5A0"
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
|
@ -31,6 +41,7 @@ Flickable {
|
|||
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 18
|
||||
color: "#E4D5A0"
|
||||
|
||||
readOnly: true
|
||||
selectByKeyboard: true
|
||||
|
@ -39,10 +50,12 @@ Flickable {
|
|||
textFormat: TextEdit.RichText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onExtra_dataChanged: {
|
||||
const card = extra_data.card;
|
||||
if (!card) return;
|
||||
cardPic.setData(card.toData());
|
||||
const name = card.virt_name ? card.virt_name : card.name;
|
||||
screenName.text = Backend.translate(name);
|
||||
skillDesc.text = Backend.translate(":" + name);
|
||||
|
|
|
@ -24,6 +24,7 @@ Item {
|
|||
text: Backend.translate("Back")
|
||||
onClicked: stack.pop()
|
||||
}
|
||||
|
||||
Label {
|
||||
text: Backend.translate("Enable free assign")
|
||||
elide: Label.ElideRight
|
||||
|
@ -31,8 +32,29 @@ Item {
|
|||
verticalAlignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: word
|
||||
placeholderText: "Search..."
|
||||
clip: true
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
background: Rectangle {
|
||||
implicitHeight: 16
|
||||
implicitWidth: 120
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
opacity: 0
|
||||
text: Backend.translate("Search")
|
||||
enabled: word.text !== ""
|
||||
onClicked: {
|
||||
if (stack.depth > 1) stack.pop();
|
||||
generalModel = JSON.parse(Backend.callLuaFunction("SearchAllGenerals",
|
||||
[word.text]));
|
||||
stack.push(generalList);
|
||||
word.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,15 +80,16 @@ Item {
|
|||
ScrollBar.vertical: ScrollBar {}
|
||||
model: packages
|
||||
clip: true
|
||||
cellWidth: width / 3
|
||||
cellWidth: width / 5
|
||||
cellHeight: 40
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: listView.width / 3
|
||||
width: listView.width / 5
|
||||
height: 40
|
||||
|
||||
Text {
|
||||
text: Backend.translate(name)
|
||||
color: "#E4D5A0"
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Fk.Pages
|
||||
import Fk.RoomElement
|
||||
|
||||
Flickable {
|
||||
id: root
|
||||
|
@ -24,29 +26,18 @@ Flickable {
|
|||
Text {
|
||||
id: screenName
|
||||
font.pixelSize: 18
|
||||
color: "#E4D5A0"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: playerGameData
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 18
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: skillDesc
|
||||
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 18
|
||||
|
||||
readOnly: true
|
||||
selectByKeyboard: true
|
||||
selectByMouse: false
|
||||
wrapMode: TextEdit.WordWrap
|
||||
textFormat: TextEdit.RichText
|
||||
color: "#E4D5A0"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Button {
|
||||
MetroButton {
|
||||
text: Backend.translate("Give Flower")
|
||||
onClicked: {
|
||||
enabled = false;
|
||||
|
@ -55,7 +46,7 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
MetroButton {
|
||||
text: Backend.translate("Give Egg")
|
||||
onClicked: {
|
||||
enabled = false;
|
||||
|
@ -68,7 +59,7 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
MetroButton {
|
||||
text: Backend.translate("Give Wine")
|
||||
enabled: Math.random() < 0.3
|
||||
onClicked: {
|
||||
|
@ -78,7 +69,7 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
MetroButton {
|
||||
text: Backend.translate("Give Shoe")
|
||||
enabled: Math.random() < 0.3
|
||||
onClicked: {
|
||||
|
@ -87,10 +78,8 @@ Flickable {
|
|||
root.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Button {
|
||||
MetroButton {
|
||||
text: config.blockedUsers.indexOf(screenName.text) === -1 ? Backend.translate("Block Chatter") : Backend.translate("Unblock Chatter")
|
||||
enabled: pid !== Self.id && pid > 0
|
||||
onClicked: {
|
||||
|
@ -103,7 +92,7 @@ Flickable {
|
|||
config.blockedUsersChanged();
|
||||
}
|
||||
}
|
||||
Button {
|
||||
MetroButton {
|
||||
text: Backend.translate("Kick From Room")
|
||||
visible: !roomScene.isStarted && roomScene.isOwner
|
||||
enabled: pid !== Self.id
|
||||
|
@ -113,6 +102,41 @@ Flickable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 20
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.topMargin: 16
|
||||
|
||||
GeneralCardItem {
|
||||
id: mainChara
|
||||
name: "caocao"
|
||||
visible: name !== ""
|
||||
}
|
||||
GeneralCardItem {
|
||||
id: deputyChara
|
||||
name: "caocao"
|
||||
visible: name !== ""
|
||||
}
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: skillDesc
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.topMargin: 10
|
||||
font.pixelSize: 18
|
||||
color: "#E4D5A0"
|
||||
|
||||
readOnly: true
|
||||
selectByKeyboard: true
|
||||
selectByMouse: false
|
||||
wrapMode: TextEdit.WordWrap
|
||||
textFormat: TextEdit.RichText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function givePresent(p) {
|
||||
|
@ -136,6 +160,8 @@ Flickable {
|
|||
root.pid = id;
|
||||
|
||||
screenName.text = extra_data.photo.screenName;
|
||||
mainChara.name = extra_data.photo.general;
|
||||
deputyChara.name = extra_data.photo.deputyGeneral;
|
||||
|
||||
if (!config.observing) {
|
||||
const gamedata = JSON.parse(Backend.callLuaFunction("GetPlayerGameData", [id]));
|
||||
|
|
|
@ -28,7 +28,7 @@ Item {
|
|||
ColumnLayout {
|
||||
Text { text: Backend.translate(gname) }
|
||||
GridLayout {
|
||||
columns: 3
|
||||
columns: 6
|
||||
|
||||
Repeater {
|
||||
model: JSON.parse(Backend.callLuaFunction("GetSameGenerals", [gname]))
|
||||
|
|
|
@ -46,16 +46,7 @@ Item {
|
|||
config.disabledGenerals = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 8
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: Backend.translate("Help_Ban_List")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Button {
|
||||
text: Backend.translate("Export")
|
||||
onClicked: {
|
||||
|
@ -91,12 +82,19 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: 8
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: Backend.translate("Help_Ban_List")
|
||||
}
|
||||
|
||||
GridView {
|
||||
id: listView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
cellWidth: width / 2
|
||||
cellWidth: width / 4
|
||||
cellHeight: 24
|
||||
model: config.disabledGenerals
|
||||
delegate: Text {
|
||||
|
|
|
@ -16,6 +16,7 @@ Item {
|
|||
transformOrigin: Item.BottomLeft
|
||||
rotation: 90
|
||||
width: root.height
|
||||
background: Rectangle { color: "#EEEEEEEE" }
|
||||
TabButton {
|
||||
text: Backend.translate("General Settings")
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ Item {
|
|||
transformOrigin: Item.BottomLeft
|
||||
rotation: 90
|
||||
width: root.height
|
||||
background: Rectangle { color: "#EEEEEEEE" }
|
||||
TabButton {
|
||||
text: Backend.translate("Userinfo Settings")
|
||||
}
|
||||
|
|
|
@ -28,24 +28,6 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
Text {
|
||||
text: Backend.translate("Player num")
|
||||
}
|
||||
SpinBox {
|
||||
id: playerNum
|
||||
from: 2
|
||||
to: 12
|
||||
value: config.preferedPlayerNum
|
||||
|
||||
onValueChanged: {
|
||||
config.preferedPlayerNum = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
|
@ -69,12 +51,33 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
GridLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
rowSpacing: 20
|
||||
columnSpacing: 20
|
||||
columns: 4
|
||||
Text {
|
||||
text: Backend.translate("Player num")
|
||||
}
|
||||
Text {
|
||||
text: Backend.translate("Select generals num")
|
||||
}
|
||||
Text {
|
||||
text: Backend.translate("Operation timeout")
|
||||
}
|
||||
Text {
|
||||
text: Backend.translate("Luck Card Times")
|
||||
}
|
||||
SpinBox {
|
||||
id: playerNum
|
||||
from: 2
|
||||
to: 12
|
||||
value: config.preferedPlayerNum
|
||||
|
||||
onValueChanged: {
|
||||
config.preferedPlayerNum = value;
|
||||
}
|
||||
}
|
||||
SpinBox {
|
||||
id: generalNum
|
||||
from: 3
|
||||
|
@ -85,6 +88,25 @@ Flickable {
|
|||
config.preferredGeneralNum = value;
|
||||
}
|
||||
}
|
||||
SpinBox {
|
||||
from: 10
|
||||
to: 60
|
||||
editable: true
|
||||
value: config.preferredTimeout
|
||||
|
||||
onValueChanged: {
|
||||
config.preferredTimeout = value;
|
||||
}
|
||||
}
|
||||
SpinBox {
|
||||
from: 0
|
||||
to: 8
|
||||
value: config.preferredLuckTime
|
||||
|
||||
onValueChanged: {
|
||||
config.preferredLuckTime = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
|
@ -100,41 +122,6 @@ Flickable {
|
|||
color: "red"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
Text {
|
||||
text: Backend.translate("Operation timeout")
|
||||
}
|
||||
SpinBox {
|
||||
from: 10
|
||||
to: 60
|
||||
editable: true
|
||||
value: config.preferredTimeout
|
||||
|
||||
onValueChanged: {
|
||||
config.preferredTimeout = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
Text {
|
||||
text: Backend.translate("Luck Card Times")
|
||||
}
|
||||
SpinBox {
|
||||
from: 0
|
||||
to: 8
|
||||
value: config.preferredLuckTime
|
||||
|
||||
onValueChanged: {
|
||||
config.preferredLuckTime = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
|
@ -150,6 +137,9 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
spacing: 16
|
||||
Switch {
|
||||
id: freeAssignCheck
|
||||
checked: Debugging ? true : false
|
||||
|
@ -161,6 +151,7 @@ Flickable {
|
|||
checked: Debugging ? true : false
|
||||
text: Backend.translate("Enable deputy general")
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.rightMargin: 8
|
||||
|
|
|
@ -52,7 +52,7 @@ Flickable {
|
|||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
columns: 4
|
||||
|
||||
Repeater {
|
||||
id: gpacks
|
||||
|
@ -100,7 +100,7 @@ Flickable {
|
|||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
columns: 4
|
||||
|
||||
Repeater {
|
||||
id: cpacks
|
||||
|
|
|
@ -224,19 +224,25 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Drawer {
|
||||
Popup {
|
||||
id: lobby_drawer
|
||||
width: parent.width * 0.4 / mainWindow.scale
|
||||
height: parent.height / mainWindow.scale
|
||||
dim: false
|
||||
clip: true
|
||||
dragMargin: 0
|
||||
scale: mainWindow.scale
|
||||
transformOrigin: Item.TopLeft
|
||||
width: realMainWin.width * 0.8
|
||||
height: realMainWin.height * 0.8
|
||||
anchors.centerIn: parent
|
||||
background: Rectangle {
|
||||
color: "#EEEEEEEE"
|
||||
radius: 5
|
||||
border.color: "#A6967A"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: lobby_dialog
|
||||
anchors.fill: parent
|
||||
anchors.centerIn: parent
|
||||
width: parent.width / mainWindow.scale
|
||||
height: parent.height / mainWindow.scale
|
||||
scale: mainWindow.scale
|
||||
clip: true
|
||||
onSourceChanged: {
|
||||
if (item === null)
|
||||
return;
|
||||
|
|
|
@ -41,6 +41,9 @@ Item {
|
|||
|
||||
TapHandler {
|
||||
id: mouse
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.NoButton
|
||||
gesturePolicy: TapHandler.WithinBounds
|
||||
|
||||
onTapped: if (parent.enabled) parent.clicked()
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import QtMultimedia
|
|||
import Fk
|
||||
import Fk.Common
|
||||
import Fk.RoomElement
|
||||
import Fk.PhotoElement as PhotoElement
|
||||
import "RoomLogic.js" as Logic
|
||||
|
||||
Item {
|
||||
|
@ -37,6 +38,7 @@ Item {
|
|||
property alias drawPile: drawPile
|
||||
property alias skillInteraction: skillInteraction
|
||||
property alias miscStatus: miscStatus
|
||||
property alias banner: banner
|
||||
|
||||
property var selected_targets: []
|
||||
property string responding_card
|
||||
|
@ -55,7 +57,6 @@ Item {
|
|||
fillMode: Image.PreserveAspectCrop
|
||||
}
|
||||
|
||||
/*
|
||||
MediaPlayer {
|
||||
id: bgm
|
||||
source: config.bgmFile
|
||||
|
@ -69,15 +70,14 @@ Item {
|
|||
volume: config.bgmVolume / 100
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
onIsStartedChanged: {
|
||||
if (isStarted) {
|
||||
// bgm.play();
|
||||
bgm.play();
|
||||
canKickOwner = false;
|
||||
kickOwnerTimer.stop();
|
||||
} else {
|
||||
// bgm.stop();
|
||||
bgm.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,14 +533,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
GlowText {
|
||||
text: Backend.translate("Observing ...")
|
||||
visible: config.observing && !config.replaying
|
||||
color: "#4B83CD"
|
||||
font.family: fontLi2.name
|
||||
font.pixelSize: 48
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: replayControls
|
||||
visible: config.replaying
|
||||
|
@ -855,7 +847,7 @@ Item {
|
|||
|
||||
Drawer {
|
||||
id: roomDrawer
|
||||
width: parent.width * 0.3 / mainWindow.scale
|
||||
width: parent.width * 0.36 / mainWindow.scale
|
||||
height: parent.height / mainWindow.scale
|
||||
dim: false
|
||||
clip: true
|
||||
|
@ -901,20 +893,25 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Drawer {
|
||||
Popup {
|
||||
id: cheatDrawer
|
||||
edge: Qt.RightEdge
|
||||
width: parent.width * 0.4 / mainWindow.scale
|
||||
height: parent.height / mainWindow.scale
|
||||
dim: false
|
||||
clip: true
|
||||
dragMargin: 0
|
||||
scale: mainWindow.scale
|
||||
transformOrigin: Item.TopRight
|
||||
width: realMainWin.width * 0.60
|
||||
height: realMainWin.height * 0.8
|
||||
anchors.centerIn: parent
|
||||
background: Rectangle {
|
||||
color: "#CC2E2C27"
|
||||
radius: 5
|
||||
border.color: "#A6967A"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: cheatLoader
|
||||
anchors.fill: parent
|
||||
anchors.centerIn: parent
|
||||
width: parent.width / mainWindow.scale
|
||||
height: parent.height / mainWindow.scale
|
||||
scale: mainWindow.scale
|
||||
clip: true
|
||||
onSourceChanged: {
|
||||
if (item === null)
|
||||
return;
|
||||
|
@ -931,6 +928,20 @@ Item {
|
|||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: dashboard
|
||||
visible: config.observing && !config.replaying
|
||||
color: "transparent"
|
||||
GlowText {
|
||||
anchors.centerIn: parent
|
||||
text: Backend.translate("Observing ...")
|
||||
color: "#4B83CD"
|
||||
font.family: fontLi2.name
|
||||
font.pixelSize: 48
|
||||
}
|
||||
}
|
||||
|
||||
/* 这东西似乎一直不好使啊
|
||||
Rectangle {
|
||||
id: easyChat
|
||||
width: parent.width
|
||||
|
@ -967,6 +978,16 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: "T"
|
||||
onActivated: {
|
||||
easyChat.visible = true;
|
||||
easyChatEdit.enabled = true;
|
||||
easyChatEdit.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
MiscStatus {
|
||||
id: miscStatus
|
||||
anchors.right: menuButton.left
|
||||
|
@ -975,20 +996,20 @@ Item {
|
|||
anchors.topMargin: 8
|
||||
}
|
||||
|
||||
PhotoElement.MarkArea {
|
||||
id: banner
|
||||
x: 12; y: 12
|
||||
width: (roomScene.width - 175 * 0.75 * 7) / 4 + 175 - 16
|
||||
transformOrigin: Item.TopLeft
|
||||
scale: 0.75
|
||||
bgColor: "#BB838AEA"
|
||||
}
|
||||
|
||||
Danmaku {
|
||||
id: danmaku
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: "T"
|
||||
onActivated: {
|
||||
easyChat.visible = true;
|
||||
easyChatEdit.enabled = true;
|
||||
easyChatEdit.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: "D"
|
||||
property bool show_distance: false
|
||||
|
|
|
@ -1012,7 +1012,7 @@ callbacks["AskForChoice"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForCheck"] = (jsonData) => {
|
||||
callbacks["AskForChoices"] = (jsonData) => {
|
||||
// jsonData: [ string[] choices, string skill ]
|
||||
// TODO: multiple choices, e.g. benxi_ol
|
||||
const data = JSON.parse(jsonData);
|
||||
|
@ -1025,7 +1025,7 @@ callbacks["AskForCheck"] = (jsonData) => {
|
|||
const prompt = data[5];
|
||||
const detailed = data[6];
|
||||
if (prompt === "") {
|
||||
roomScene.promptText = Backend.translate("#AskForCheck")
|
||||
roomScene.promptText = Backend.translate("#AskForChoices")
|
||||
.arg(Backend.translate(skill_name));
|
||||
} else {
|
||||
roomScene.setPrompt(processPrompt(prompt), true);
|
||||
|
@ -1335,7 +1335,7 @@ callbacks["SetPlayerMark"] = (jsonData) => {
|
|||
const data = JSON.parse(jsonData);
|
||||
const player = getPhoto(data[0]);
|
||||
const mark = data[1];
|
||||
const value = data[2] instanceof Array ? data[2] : data[2].toString();
|
||||
const value = data[2] instanceof Object ? data[2] : data[2].toString();
|
||||
let area = mark.startsWith("@!") ? player.picMarkArea : player.markArea;
|
||||
if (data[2] === 0) {
|
||||
area.removeMark(mark);
|
||||
|
@ -1344,6 +1344,18 @@ callbacks["SetPlayerMark"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["SetBanner"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
const mark = data[0];
|
||||
const value = data[1] instanceof Object ? data[1] : data[1].toString();
|
||||
let area = roomScene.banner;
|
||||
if (data[1] === 0) {
|
||||
area.removeMark(mark);
|
||||
} else {
|
||||
area.setMark(mark, mark.startsWith("@@") ? "" : value);
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["Animate"] = (jsonData) => {
|
||||
// jsonData: [Object object]
|
||||
const data = JSON.parse(jsonData);
|
||||
|
@ -1581,7 +1593,7 @@ callbacks["ChangeSelf"] = (j) => {
|
|||
|
||||
callbacks["AskForLuckCard"] = (j) => {
|
||||
// jsonData: int time
|
||||
if (config.replaying) return;
|
||||
if (config.observing || config.replaying) return;
|
||||
const time = parseInt(j);
|
||||
roomScene.setPrompt(Backend.translate("#AskForLuckCard").arg(time), true);
|
||||
roomScene.state = "replying";
|
||||
|
|
|
@ -6,6 +6,7 @@ import QtQuick.Layouts
|
|||
Item {
|
||||
id: root
|
||||
width: 138
|
||||
property var bgColor: "#3C3229"
|
||||
|
||||
ListModel {
|
||||
id: markList
|
||||
|
@ -15,7 +16,7 @@ Item {
|
|||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: "#3C3229"
|
||||
color: bgColor
|
||||
opacity: 0.8
|
||||
radius: 4
|
||||
border.color: "white"
|
||||
|
@ -68,7 +69,21 @@ Item {
|
|||
} else {
|
||||
params.cardNames = data;
|
||||
}
|
||||
} else if (mark_name.startsWith('@[')) {
|
||||
// @[xxx]yyy 怀疑是不是qml标记
|
||||
const close_br = mark_name.indexOf(']');
|
||||
if (close_br === -1) return;
|
||||
|
||||
const mark_type = mark_name.slice(2, close_br);
|
||||
const _data = (mark_extra);
|
||||
let data = JSON.parse(Backend.callLuaFunction("GetQmlMark", [mark_type, mark_name, JSON.stringify(_data)]));
|
||||
if (data && data.qml_path) {
|
||||
params.data = _data;
|
||||
roomScene.startCheat("../../" + data.qml_path, params);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (!root.parent.playerid) return;
|
||||
let data = JSON.parse(Backend.callLuaFunction("GetPile", [root.parent.playerid, mark_name]));
|
||||
data = data.filter((e) => e !== -1);
|
||||
if (data.length === 0)
|
||||
|
@ -103,6 +118,15 @@ Item {
|
|||
if (mark.startsWith('@$') || mark.startsWith('@&')) {
|
||||
special_value += data.length;
|
||||
data = data.join(',');
|
||||
} else if (mark.startsWith('@[')) {
|
||||
const close_br = mark.indexOf(']');
|
||||
if (close_br !== -1) {
|
||||
const mark_type = mark.slice(2, close_br);
|
||||
const _data = JSON.parse(Backend.callLuaFunction("GetQmlMark", [mark_type, mark, JSON.stringify(data)]));
|
||||
if (_data && _data.text) {
|
||||
special_value = _data.text;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data = data instanceof Array ? data.map((markText) => Backend.translate(markText)).join(' ') : Backend.translate(data);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
Item {
|
||||
property alias text: pileName.text
|
||||
GlowText {
|
||||
id: pileName
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
width: parent.width
|
||||
font.family: fontLibian.name
|
||||
color: "#E4D5A0"
|
||||
font.pixelSize: 30
|
||||
font.weight: Font.Medium
|
||||
glow.color: "black"
|
||||
glow.spread: 0.3
|
||||
glow.radius: 5
|
||||
}
|
||||
|
||||
LinearGradient {
|
||||
anchors.fill: pileName
|
||||
source: pileName
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#FEF7C2"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 0.5
|
||||
color: "#D2AD4A"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#BE9878"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import QtQuick.Layouts
|
|||
import QtQuick.Controls
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
property var extra_data: ({}) // unused
|
||||
|
@ -14,33 +14,24 @@ Item {
|
|||
|
||||
Text {
|
||||
text: Backend.translate("Handcard selector")
|
||||
width: parent.width
|
||||
anchors.topMargin: 6
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 16
|
||||
font.pixelSize: 18
|
||||
color: "#E4D5A0"
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickableContainer
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 40
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
width: parent.width - 20
|
||||
height: parent.height - 40
|
||||
contentWidth: cardsList.width
|
||||
contentHeight: cardsList.height
|
||||
GridView {
|
||||
id: cardsList
|
||||
cellWidth: 93 * 0.9 + 4
|
||||
cellHeight: 130 * 0.9 + 4
|
||||
Layout.preferredWidth: root.width - root.width % 88
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
clip: true
|
||||
|
||||
GridLayout {
|
||||
id: cardsList
|
||||
columns: Math.floor(flickableContainer.width / 90)
|
||||
|
||||
Repeater {
|
||||
model: cards
|
||||
|
||||
CardItem {
|
||||
delegate: CardItem {
|
||||
width: 93 * 0.9
|
||||
height: 130 * 0.9
|
||||
chosenInBox: modelData.chosen
|
||||
|
@ -59,8 +50,6 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
cards = roomScene.dashboard.handcardArea.cards
|
||||
|
|
|
@ -153,7 +153,7 @@ CardItem {
|
|||
height: 80
|
||||
x: 2
|
||||
y: lineCount > 6 ? 30 : 34
|
||||
text: Backend.translate(name)
|
||||
text: name !== "" ? Backend.translate(name) : "nil"
|
||||
visible: Backend.translate(name).length <= 6 && detailed
|
||||
color: "white"
|
||||
font.family: fontLibian.name
|
||||
|
|
|
@ -2,87 +2,34 @@
|
|||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
property var extra_data: ({})
|
||||
signal finish()
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
BigGlowText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height + 4
|
||||
|
||||
GlowText {
|
||||
id: pileName
|
||||
text: Backend.translate(extra_data.name)
|
||||
width: parent.width
|
||||
anchors.topMargin: 10
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.family: fontLibian.name
|
||||
color: "#E4D5A0"
|
||||
font.pixelSize: 30
|
||||
font.weight: Font.Medium
|
||||
glow.color: "black"
|
||||
glow.spread: 0.3
|
||||
glow.radius: 5
|
||||
}
|
||||
|
||||
LinearGradient {
|
||||
anchors.fill: pileName
|
||||
source: pileName
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#FEF7C2"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 0.5
|
||||
color: "#D2AD4A"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#BE9878"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickableContainer
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 40
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
width: parent.width - 20
|
||||
height: parent.height - 40
|
||||
contentWidth: cardsList.width
|
||||
contentHeight: cardsList.height
|
||||
GridView {
|
||||
cellWidth: 93 + 4
|
||||
cellHeight: 130 + 4
|
||||
Layout.preferredWidth: root.width - root.width % 97
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
clip: true
|
||||
|
||||
ColumnLayout {
|
||||
id: cardsList
|
||||
|
||||
GridLayout {
|
||||
columns: Math.floor(flickableContainer.width / 100)
|
||||
|
||||
Repeater {
|
||||
model: extra_data.ids || extra_data.cardNames
|
||||
|
||||
GeneralCardItem {
|
||||
delegate: GeneralCardItem {
|
||||
id: cardItem
|
||||
// width: (flickableContainer.width - 15) / 4
|
||||
// height: cardItem.width * 1.4
|
||||
autoBack: false
|
||||
name: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,81 +2,32 @@
|
|||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
property var extra_data: ({})
|
||||
signal finish()
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
BigGlowText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height + 4
|
||||
|
||||
GlowText {
|
||||
id: pileName
|
||||
text: Backend.translate(extra_data.name)
|
||||
width: parent.width
|
||||
anchors.topMargin: 10
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.family: fontLibian.name
|
||||
color: "#E4D5A0"
|
||||
font.pixelSize: 30
|
||||
font.weight: Font.Medium
|
||||
glow.color: "black"
|
||||
glow.spread: 0.3
|
||||
glow.radius: 5
|
||||
}
|
||||
|
||||
LinearGradient {
|
||||
anchors.fill: pileName
|
||||
source: pileName
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#FEF7C2"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 0.5
|
||||
color: "#D2AD4A"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#BE9878"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickableContainer
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 40
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
width: parent.width - 20
|
||||
height: parent.height - 40
|
||||
contentWidth: cardsList.width
|
||||
contentHeight: cardsList.height
|
||||
GridView {
|
||||
cellWidth: 93 + 4
|
||||
cellHeight: 130 + 4
|
||||
Layout.preferredWidth: root.width - root.width % 97
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
clip: true
|
||||
|
||||
ColumnLayout {
|
||||
id: cardsList
|
||||
|
||||
GridLayout {
|
||||
columns: 4
|
||||
|
||||
Repeater {
|
||||
model: extra_data.ids || extra_data.cardNames
|
||||
|
||||
CardItem {
|
||||
delegate: CardItem {
|
||||
id: cardItem
|
||||
width: (flickableContainer.width - 15) / 4
|
||||
height: cardItem.width * 1.4
|
||||
autoBack: false
|
||||
Component.onCompleted: {
|
||||
let data = {}
|
||||
|
@ -94,7 +45,3 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ Dashboard 1.0 Dashboard.qml
|
|||
GameOverBox 1.0 GameOverBox.qml
|
||||
GeneralCardItem 1.0 GeneralCardItem.qml
|
||||
GlowText 1.0 GlowText.qml
|
||||
BigGlowText 1.0 BigGlowText.qml
|
||||
GraphicsBox 1.0 GraphicsBox.qml
|
||||
GuanxingBox 1.0 GuanxingBox.qml
|
||||
HandcardArea 1.0 HandcardArea.qml
|
||||
|
|
|
@ -334,6 +334,10 @@
|
|||
<source>Room is full or already started!</source>
|
||||
<translation>房间已满!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>rejected your demand of joining room</source>
|
||||
<translation>房主拒绝你加入。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>server is full!</source>
|
||||
<translation>服务器已满!</translation>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
---@field public current ClientPlayer @ 当前回合玩家
|
||||
---@field public discard_pile integer[] @ 弃牌堆
|
||||
---@field public status_skills Skill[] @ 状态技总和
|
||||
---@field public banners table<string, any> @ 左上角显示的东西
|
||||
---@field public observing boolean
|
||||
Client = class('Client')
|
||||
|
||||
|
@ -57,6 +58,8 @@ function Client:initialize()
|
|||
self.status_skills[class] = {table.unpack(skills)}
|
||||
end
|
||||
|
||||
self.banners = {}
|
||||
|
||||
self.skill_costs = {}
|
||||
self.card_marks = {}
|
||||
self.filtered_cards = {}
|
||||
|
@ -234,6 +237,15 @@ function Client:setCardNote(ids, msg)
|
|||
end
|
||||
end
|
||||
|
||||
function Client:setBanner(name, value)
|
||||
if value == 0 then value = nil end
|
||||
self.banners[name] = value
|
||||
end
|
||||
|
||||
function Client:getBanner(name)
|
||||
return self.banners[name]
|
||||
end
|
||||
|
||||
fk.client_callback["SetCardFootnote"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
ClientInstance:setCardNote(data[1], data[2]);
|
||||
|
@ -769,6 +781,17 @@ fk.client_callback["SetPlayerMark"] = function(jsonData)
|
|||
end
|
||||
end
|
||||
|
||||
fk.client_callback["SetBanner"] = function(jsonData)
|
||||
-- jsonData: [ int id, string mark, int value ]
|
||||
local data = json.decode(jsonData)
|
||||
local mark, value = data[1], data[2]
|
||||
ClientInstance:setBanner(mark, value)
|
||||
|
||||
if string.sub(mark, 1, 1) == "@" then
|
||||
ClientInstance:notifyUI("SetBanner", jsonData)
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["SetCardMark"] = function(jsonData)
|
||||
-- jsonData: [ int id, string mark, int value ]
|
||||
local data = json.decode(jsonData)
|
||||
|
|
|
@ -734,4 +734,14 @@ function PoxiFeasible(poxi_type, selected, data, extra_data)
|
|||
return json.encode(poxi.feasible(selected, data, extra_data))
|
||||
end
|
||||
|
||||
function GetQmlMark(mtype, name, value)
|
||||
local spec = Fk.qml_marks[mtype]
|
||||
if not spec then return "{}" end
|
||||
value = json.decode(value)
|
||||
return json.encode {
|
||||
qml_path = spec.qml_path,
|
||||
text = spec.how_to_show(name, value)
|
||||
}
|
||||
end
|
||||
|
||||
dofile "lua/client/i18n/init.lua"
|
||||
|
|
|
@ -159,7 +159,7 @@ Fk:loadTranslationTable({
|
|||
["#AskForLuckCard"] = "Do you want to use luck card (%1 times left)?",
|
||||
["AskForLuckCard"] = "Luck card",
|
||||
["#AskForChoice"] = "%1: Please choose",
|
||||
["#AskForCheck"] = "%1: Please choose",
|
||||
["#AskForChoices"] = "%1: Please choose",
|
||||
["#choose-trigger"] = "Please choose the skill to use",
|
||||
["trigger"] = "Trigger skill",
|
||||
-- ["Please arrange cards"] = "请拖拽移动卡牌",
|
||||
|
@ -170,7 +170,7 @@ Fk:loadTranslationTable({
|
|||
["AskForGuanxing"] = "Stargazing",
|
||||
["AskForExchange"] = "Exchaging",
|
||||
["AskForChoice"] = "Making choice",
|
||||
["AskForCheck"] = "Making choice",
|
||||
["AskForChoices"] = "Making choice",
|
||||
["AskForKingdom"] = "Choosing kingdom",
|
||||
["AskForPindian"] = "Point fight",
|
||||
["AskForMoveCardInBoard"] = "Moving cards",
|
||||
|
|
|
@ -206,7 +206,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["#AskForLuckCard"] = "你想使用手气卡吗?还可以使用 %1 次,剩余手气卡∞张",
|
||||
["AskForLuckCard"] = "手气卡",
|
||||
["#AskForChoice"] = "%1:请选择",
|
||||
["#AskForCheck"] = "%1:请选择",
|
||||
["#AskForChoices"] = "%1:请选择",
|
||||
["#choose-trigger"] = "请选择一项技能发动",
|
||||
["trigger"] = "选择技能",
|
||||
["Please arrange cards"] = "请拖拽移动卡牌",
|
||||
|
@ -217,7 +217,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["AskForGuanxing"] = "观星",
|
||||
["AskForExchange"] = "换牌",
|
||||
["AskForChoice"] = "选择",
|
||||
["AskForCheck"] = "选择",
|
||||
["AskForChoices"] = "选择",
|
||||
["AskForKingdom"] = "选择势力",
|
||||
["AskForPindian"] = "拼点",
|
||||
["AskForMoveCardInBoard"] = "移动卡牌",
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
---@field public printed_cards table<integer, Card> @ 被某些房间现场打印的卡牌,id都是负数且从-2开始
|
||||
---@field private _custom_events any[] @ 自定义事件列表
|
||||
---@field public poxi_methods table<string, PoxiSpec> @ “魄袭”框操作方法表
|
||||
---@field public qml_marks table<string, QmlMarkSpec> @ 自定义Qml标记的表
|
||||
local Engine = class("Engine")
|
||||
|
||||
--- Engine的构造函数。
|
||||
|
@ -59,6 +60,7 @@ function Engine:initialize()
|
|||
self.kingdoms = {}
|
||||
self._custom_events = {}
|
||||
self.poxi_methods = {}
|
||||
self.qml_marks = {}
|
||||
|
||||
self:loadPackages()
|
||||
self:loadDisabled()
|
||||
|
@ -345,11 +347,22 @@ function Engine:addPoxiMethod(spec)
|
|||
assert(type(spec.name) == "string")
|
||||
assert(type(spec.card_filter) == "function")
|
||||
assert(type(spec.feasible) == "function")
|
||||
if self.poxi_methods[spec.name] then
|
||||
fk.qCritical("Warning: duplicated poxi_method " .. spec.name)
|
||||
end
|
||||
self.poxi_methods[spec.name] = spec
|
||||
spec.default_choice = spec.default_choice or function() return {} end
|
||||
spec.post_select = spec.post_select or function(s) return s end
|
||||
end
|
||||
|
||||
function Engine:addQmlMark(spec)
|
||||
assert(type(spec.name) == "string")
|
||||
if self.qml_marks[spec.name] then
|
||||
fk.qCritical("Warning: duplicated qml mark type " .. spec.name)
|
||||
end
|
||||
self.qml_marks[spec.name] = spec
|
||||
end
|
||||
|
||||
--- 从已经开启的拓展包中,随机选出若干名武将。
|
||||
---
|
||||
--- 对于同名武将不会重复选取。
|
||||
|
|
|
@ -598,3 +598,8 @@ end
|
|||
---@field post_select? fun(selected: int[], data: any, extra_data: any): int[]
|
||||
---@field default_choice? fun(data: any, extra_data: any): int[]
|
||||
---@field prompt? string | fun(data: any, extra_data: any): string
|
||||
|
||||
---@class QmlMarkSpec
|
||||
---@field name string
|
||||
---@field qml_path string
|
||||
---@field how_to_show function(name: string, value?: any): string?
|
||||
|
|
|
@ -41,6 +41,11 @@ local function tellRoomToObserver(self, player)
|
|||
end
|
||||
end
|
||||
|
||||
-- send banners
|
||||
for k, v in pairs(self.banners) do
|
||||
player:doNotify("SetBanner", json.encode{ k, v })
|
||||
end
|
||||
|
||||
for _, p in ipairs(self.players) do
|
||||
self:notifyProperty(player, p, "general")
|
||||
self:notifyProperty(player, p, "deputyGeneral")
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
---@field public game_finished boolean @ 游戏是否已经结束
|
||||
---@field public timeout integer @ 出牌时长上限
|
||||
---@field public tag table<string, any> @ Tag清单,其实跟Player的标记是差不多的东西
|
||||
---@field public banners table<string, any> @ 左上角显示点啥好呢?
|
||||
---@field public general_pile string[] @ 武将牌堆,这是可用武将名的数组
|
||||
---@field public draw_pile integer[] @ 摸牌堆,这是卡牌id的数组
|
||||
---@field public discard_pile integer[] @ 弃牌堆,也是卡牌id的数组
|
||||
|
@ -77,6 +78,7 @@ function Room:initialize(_room)
|
|||
self.game_finished = false
|
||||
self.timeout = _room:getTimeout()
|
||||
self.tag = {}
|
||||
self.banners = {}
|
||||
self.general_pile = {}
|
||||
self.draw_pile = {}
|
||||
self.discard_pile = {}
|
||||
|
@ -563,6 +565,16 @@ function Room:removeTag(tag_name)
|
|||
self.tag[tag_name] = nil
|
||||
end
|
||||
|
||||
function Room:setBanner(name, value)
|
||||
if value == 0 then value = nil end
|
||||
self.banners[name] = value
|
||||
self:doBroadcastNotify("SetBanner", json.encode{ name, value })
|
||||
end
|
||||
|
||||
function Room:getBanner(name)
|
||||
return self.banners[name]
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
local function execGameEvent(type, ...)
|
||||
local event = GameEvent:new(type, ...)
|
||||
|
@ -1338,9 +1350,9 @@ end
|
|||
---@param cancelable? boolean @ 能否点取消
|
||||
---@param no_indicate? boolean @ 是否不显示指示线
|
||||
---@return integer[], integer[]
|
||||
function Room:askForChooseBoth(player, minCardNum, maxCardNum, targets, minTargetNum, maxTargetNum, pattern, prompt, skillName, cancelable, no_indicate)
|
||||
function Room:askForChooseCardsAndPlayers(player, minCardNum, maxCardNum, targets, minTargetNum, maxTargetNum, pattern, prompt, skillName, cancelable, no_indicate)
|
||||
if minCardNum < 1 or minTargetNum < 1 then
|
||||
return table.unpack({}, {})
|
||||
return {}, {}
|
||||
end
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
no_indicate = no_indicate or false
|
||||
|
@ -1366,7 +1378,7 @@ function Room:askForChooseBoth(player, minCardNum, maxCardNum, targets, minTarge
|
|||
return ret.targets, ret.cards
|
||||
else
|
||||
if cancelable then
|
||||
return table.unpack({}, {})
|
||||
return {}, {}
|
||||
else
|
||||
return table.random(targets, minTargetNum), table.random(pcards, minCardNum)
|
||||
end
|
||||
|
@ -1675,12 +1687,12 @@ end
|
|||
---@param detailed? boolean @ 选项详细描述
|
||||
---@param all_choices? string[] @ 所有选项(不可选变灰)
|
||||
---@return string[] @ 选择的选项
|
||||
function Room:askForCheck(player, choices, minNum, maxNum, skill_name, prompt, cancelable, detailed, all_choices)
|
||||
function Room:askForChoices(player, choices, minNum, maxNum, skill_name, prompt, cancelable, detailed, all_choices)
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
if #choices <= minNum and not all_choices then return choices end
|
||||
assert(minNum <= maxNum)
|
||||
assert(not all_choices or table.every(choices, function(c) return table.contains(all_choices, c) end))
|
||||
local command = "AskForCheck"
|
||||
local command = "AskForChoices"
|
||||
skill_name = skill_name or ""
|
||||
prompt = prompt or ""
|
||||
all_choices = all_choices or choices
|
||||
|
|
|
@ -362,6 +362,11 @@ function ServerPlayer:reconnect()
|
|||
end
|
||||
end
|
||||
|
||||
-- send banners
|
||||
for k, v in pairs(room.banners) do
|
||||
self:doNotify("SetBanner", json.encode{ k, v })
|
||||
end
|
||||
|
||||
for _, p in ipairs(room.players) do
|
||||
room:notifyProperty(self, p, "general")
|
||||
room:notifyProperty(self, p, "deputyGeneral")
|
||||
|
|
|
@ -87,6 +87,10 @@ local control = fk.CreateActiveSkill{
|
|||
on_use = function(self, room, effect)
|
||||
--room:doSuperLightBox("packages/test/qml/Test.qml")
|
||||
local from = room:getPlayerById(effect.from)
|
||||
-- room:setPlayerMark(from, "@[test]test", {
|
||||
-- all = {3, 1, 6, 9, 5, 11, 10, 2, 8, 7, 12, 4, 13},
|
||||
-- ok = {10, 2},
|
||||
-- })
|
||||
-- room:swapSeat(from, to)
|
||||
for _, pid in ipairs(effect.tos) do
|
||||
local to = room:getPlayerById(pid)
|
||||
|
@ -145,6 +149,27 @@ Fk:addPoxiMethod{
|
|||
end,
|
||||
prompt = "魄袭:选你们俩手牌总共四个花色,或者不选直接按确定按钮"
|
||||
}
|
||||
Fk:loadTranslationTable{['@[test]test']='割圆'}
|
||||
Fk:addQmlMark{
|
||||
name = "test",
|
||||
how_to_show = function(name, value)
|
||||
local all_points = value.all
|
||||
local ok_points = value.ok
|
||||
-- 若没有点亮的就不显示
|
||||
if #ok_points == 0 then return "" end
|
||||
-- 否则,显示相邻的,逻辑上要构成循环
|
||||
local start_idx = table.indexOf(all_points, ok_points[1]) - 1
|
||||
local end_idx = table.indexOf(all_points, ok_points[#ok_points]) + 1
|
||||
if start_idx == 0 then start_idx = #all_points end
|
||||
if end_idx == #all_points + 1 then end_idx = 1 end
|
||||
if start_idx == end_idx then
|
||||
return Card:getNumberStr(all_points[start_idx])
|
||||
else
|
||||
return Card:getNumberStr(all_points[start_idx]) .. Card:getNumberStr(all_points[end_idx])
|
||||
end
|
||||
end,
|
||||
qml_path = "packages/test/qml/TestDialog"
|
||||
}
|
||||
--]]
|
||||
local test_vs = fk.CreateViewAsSkill{
|
||||
name = "test_vs",
|
||||
|
|
|
@ -1,38 +1,57 @@
|
|||
// 割圆的例子
|
||||
import QtQuick
|
||||
import "../../../qml/Pages/RoomElement"
|
||||
import "../../../qml/Pages"
|
||||
|
||||
GraphicsBox {
|
||||
property string custom_string: ""
|
||||
import QtQuick.Layouts
|
||||
import Fk.RoomElement
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
title.text: Backend.translate("Test")
|
||||
width: Math.max(140, body.width + 20)
|
||||
height: body.height + title.height + 20
|
||||
anchors.fill: parent
|
||||
property var extra_data: ({ name: "", data: {
|
||||
all: [1, 2, 4, 6],
|
||||
ok: [1, 4],
|
||||
} })
|
||||
signal finish()
|
||||
|
||||
Column {
|
||||
id: body
|
||||
x: 10
|
||||
y: title.height + 5
|
||||
spacing: 10
|
||||
BigGlowText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height + 4
|
||||
|
||||
text: Backend.translate(extra_data.name)
|
||||
}
|
||||
|
||||
PathView {
|
||||
id: pathView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: extra_data.data.all
|
||||
delegate: Rectangle{
|
||||
width: 42; height: 42
|
||||
color: extra_data.data.ok.includes(modelData) ? "yellow" : "#CCEEEEEE"
|
||||
radius: 2
|
||||
Text {
|
||||
text: root.custom_string
|
||||
color: "#E4D5A0"
|
||||
anchors.centerIn: parent
|
||||
text: modelData
|
||||
font.pixelSize: 24
|
||||
}
|
||||
|
||||
MetroButton {
|
||||
text: Backend.translate("OKOK")
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
onClicked: {
|
||||
close();
|
||||
ClientInstance.replyToServer("", "Hello from test dialog");
|
||||
}
|
||||
path: Path {
|
||||
// 默认横屏了,应该没人用竖屏玩这游戏
|
||||
startX: pathView.width / 2
|
||||
startY: 40
|
||||
PathArc {
|
||||
x: pathView.width / 2
|
||||
y: pathView.height - 40
|
||||
radiusX: (pathView.height - 80) / 2
|
||||
radiusY: (pathView.height - 80) / 2
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
PathArc {
|
||||
x: pathView.width / 2
|
||||
y: 40
|
||||
radiusX: (pathView.height - 80) / 2
|
||||
radiusY: (pathView.height - 80) / 2
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadData(data) {
|
||||
custom_string = data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -284,7 +284,13 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
|||
} else if (command == "KickPlayer") {
|
||||
int i = jsonData.toInt();
|
||||
auto p = room->findPlayer(i);
|
||||
if (p && !room->isStarted()) room->removePlayer(p);
|
||||
if (p && !room->isStarted()) {
|
||||
room->removePlayer(p);
|
||||
room->addRejectId(i);
|
||||
QTimer::singleShot(30000, this, [=]() {
|
||||
room->removeRejectId(i);
|
||||
});
|
||||
}
|
||||
} else if (command == "Ready") {
|
||||
player->setReady(!player->isReady());
|
||||
room->doBroadcastNotify(room->getPlayers(), "ReadyChanged",
|
||||
|
|
|
@ -125,6 +125,11 @@ void Room::addPlayer(ServerPlayer *player) {
|
|||
if (!player)
|
||||
return;
|
||||
|
||||
if (rejected_players.contains(player->getId())) {
|
||||
player->doNotify("ErrorMsg", "rejected your demand of joining room");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果要加入的房间满员了,或者已经开战了,就不能再加入
|
||||
if (isFull() || gameStarted) {
|
||||
player->doNotify("ErrorMsg", "Room is full or already started!");
|
||||
|
@ -322,6 +327,11 @@ void Room::addObserver(ServerPlayer *player) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (rejected_players.contains(player->getId())) {
|
||||
player->doNotify("ErrorMsg", "rejected your demand of joining room");
|
||||
return;
|
||||
}
|
||||
|
||||
// 向observers中追加player,并从大厅移除player,然后将player的room设为this
|
||||
observers.append(player);
|
||||
player->setRoom(this);
|
||||
|
@ -573,3 +583,12 @@ void Room::pushRequest(const QString &req) {
|
|||
m_thread->pushRequest(QString("%1,%2").arg(QString::number(id), req));
|
||||
}
|
||||
}
|
||||
|
||||
void Room::addRejectId(int id) {
|
||||
if (isLobby()) return;
|
||||
rejected_players << id;
|
||||
}
|
||||
|
||||
void Room::removeRejectId(int id) {
|
||||
rejected_players.removeOne(id);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ class Room : public QObject {
|
|||
void manuallyStart();
|
||||
void pushRequest(const QString &req);
|
||||
|
||||
void addRejectId(int id);
|
||||
void removeRejectId(int id);
|
||||
signals:
|
||||
void abandoned();
|
||||
|
||||
|
@ -82,6 +84,7 @@ class Room : public QObject {
|
|||
QList<ServerPlayer *> players;
|
||||
QList<ServerPlayer *> observers;
|
||||
QList<int> runned_players;
|
||||
QList<int> rejected_players;
|
||||
int robot_id;
|
||||
bool gameStarted;
|
||||
bool m_ready;
|
||||
|
|
|
@ -60,7 +60,7 @@ Server::Server(QObject *parent) : QObject(parent) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
if (!this->isListening) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue