diff --git a/.gitignore b/.gitignore
index 9f7c107f..4e7279dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,8 @@ freekill-wrap.cxx
/server/rsa_pub
/freekill.client.config.json
/freekill.server.config.json
+/freekill.server.error.log
+/freekill.server.info.log
/flist.txt
# windeployqt
diff --git a/Fk/Cheat/PlayerDetail.qml b/Fk/Cheat/PlayerDetail.qml
index 55681380..e281fb50 100644
--- a/Fk/Cheat/PlayerDetail.qml
+++ b/Fk/Cheat/PlayerDetail.qml
@@ -43,12 +43,22 @@ Flickable {
Button {
text: Backend.translate("Give Shoe")
- enabled: Math.random() < 0.5
+ enabled: Math.random() < 0.3
onClicked: {
root.givePresent("Shoe");
root.finish();
}
}
+
+ Button {
+ text: Backend.translate("Kick From Room")
+ visible: !roomScene.isStarted && roomScene.isOwner
+ enabled: pid !== Self.id
+ onClicked: {
+ ClientInstance.notifyServer("KickPlayer", pid.toString());
+ root.finish();
+ }
+ }
}
// TODO: player details
diff --git a/Fk/LobbyElement/RoomGeneralSettings.qml b/Fk/LobbyElement/RoomGeneralSettings.qml
index f0b676a4..b49a5297 100644
--- a/Fk/LobbyElement/RoomGeneralSettings.qml
+++ b/Fk/LobbyElement/RoomGeneralSettings.qml
@@ -4,194 +4,201 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
-ColumnLayout {
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Room Name")
- }
- TextField {
- id: roomName
- maximumLength: 64
- font.pixelSize: 18
- text: Backend.translate("$RoomName").arg(Self.screenName)
- }
- }
+Flickable {
+ flickableDirection: Flickable.AutoFlickIfNeeded
+ clip: true
+ contentHeight: layout.height
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Player num")
- }
- SpinBox {
- id: playerNum
- from: 2
- to: 8
- value: config.preferedPlayerNum
-
- onValueChanged: {
- config.preferedPlayerNum = value;
+ ColumnLayout {
+ id: layout
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Text {
+ text: Backend.translate("Room Name")
+ }
+ TextField {
+ id: roomName
+ maximumLength: 64
+ font.pixelSize: 18
+ text: Backend.translate("$RoomName").arg(Self.screenName)
}
}
- }
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Game Mode")
- }
- ComboBox {
- id: gameModeCombo
- textRole: "name"
- model: ListModel {
- id: gameModeList
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Text {
+ text: Backend.translate("Player num")
}
+ SpinBox {
+ id: playerNum
+ from: 2
+ to: 8
+ value: config.preferedPlayerNum
- onCurrentIndexChanged: {
- let data = gameModeList.get(currentIndex);
- playerNum.from = data.minPlayer;
- playerNum.to = data.maxPlayer;
-
- config.preferedMode = data.orig_name;
+ onValueChanged: {
+ config.preferedPlayerNum = value;
+ }
}
}
- }
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Select general num")
- }
- SpinBox {
- id: generalNum
- from: 3
- to: 18
- value: config.preferredGeneralNum
-
- onValueChanged: {
- config.preferredGeneralNum = value;
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Text {
+ text: Backend.translate("Game Mode")
}
- }
- }
-
- 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
- Text {
- text: Backend.translate("Room Password")
- }
- TextField {
- id: roomPassword
- maximumLength: 16
- font.pixelSize: 18
- }
- }
-
- Switch {
- id: freeAssignCheck
- checked: Debugging ? true : false
- text: Backend.translate("Enable free assign")
- }
-
- Switch {
- id: deputyCheck
- checked: Debugging ? true : false
- text: Backend.translate("Enable deputy general")
- }
-
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Button {
- text: Backend.translate("OK")
- onClicked: {
- root.finished();
- mainWindow.busy = true;
-
- let disabledGenerals = config.disabledGenerals.slice();
- if (disabledGenerals.length) {
- const availablePack = JSON.parse(Backend.callLuaFunction("GetAllGeneralPack", [])).
- filter((pack) => !config.disabledPack.includes(pack));
- disabledGenerals = disabledGenerals.filter((general) => {
- return availablePack.find((pack) => JSON.parse(Backend.callLuaFunction("GetGenerals", [pack])).includes(general));
- });
-
- disabledGenerals = Array.from(new Set(disabledGenerals));
+ ComboBox {
+ id: gameModeCombo
+ textRole: "name"
+ model: ListModel {
+ id: gameModeList
}
- ClientInstance.notifyServer(
- "CreateRoom",
- JSON.stringify([roomName.text, playerNum.value, config.preferredTimeout, {
- enableFreeAssign: freeAssignCheck.checked,
- enableDeputy: deputyCheck.checked,
- gameMode: config.preferedMode,
- disabledPack: config.disabledPack,
- generalNum: config.preferredGeneralNum,
- luckTime: config.preferredLuckTime,
- password: roomPassword.text,
- disabledGenerals,
- }])
- );
- }
- }
- Button {
- text: Backend.translate("Cancel")
- onClicked: {
- root.finished();
- }
- }
- }
+ onCurrentIndexChanged: {
+ let data = gameModeList.get(currentIndex);
+ playerNum.from = data.minPlayer;
+ playerNum.to = data.maxPlayer;
- Component.onCompleted: {
- let mode_data = JSON.parse(Backend.callLuaFunction("GetGameModes", []));
- let i = 0;
- for (let d of mode_data) {
- gameModeList.append(d);
- if (d.orig_name == config.preferedMode) {
- gameModeCombo.currentIndex = i;
+ config.preferedMode = data.orig_name;
+ }
}
- i += 1;
}
- playerNum.value = config.preferedPlayerNum;
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Text {
+ text: Backend.translate("Select general num")
+ }
+ SpinBox {
+ id: generalNum
+ from: 3
+ to: 18
+ value: config.preferredGeneralNum
+
+ onValueChanged: {
+ config.preferredGeneralNum = value;
+ }
+ }
+ }
+
+ 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
+ Text {
+ text: Backend.translate("Room Password")
+ }
+ TextField {
+ id: roomPassword
+ maximumLength: 16
+ font.pixelSize: 18
+ }
+ }
+
+ Switch {
+ id: freeAssignCheck
+ checked: Debugging ? true : false
+ text: Backend.translate("Enable free assign")
+ }
+
+ Switch {
+ id: deputyCheck
+ checked: Debugging ? true : false
+ text: Backend.translate("Enable deputy general")
+ }
+
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Button {
+ text: Backend.translate("OK")
+ onClicked: {
+ root.finished();
+ mainWindow.busy = true;
+
+ let disabledGenerals = config.disabledGenerals.slice();
+ if (disabledGenerals.length) {
+ const availablePack = JSON.parse(Backend.callLuaFunction("GetAllGeneralPack", [])).
+ filter((pack) => !config.disabledPack.includes(pack));
+ disabledGenerals = disabledGenerals.filter((general) => {
+ return availablePack.find((pack) => JSON.parse(Backend.callLuaFunction("GetGenerals", [pack])).includes(general));
+ });
+
+ disabledGenerals = Array.from(new Set(disabledGenerals));
+ }
+
+ ClientInstance.notifyServer(
+ "CreateRoom",
+ JSON.stringify([roomName.text, playerNum.value, config.preferredTimeout, {
+ enableFreeAssign: freeAssignCheck.checked,
+ enableDeputy: deputyCheck.checked,
+ gameMode: config.preferedMode,
+ disabledPack: config.disabledPack,
+ generalNum: config.preferredGeneralNum,
+ luckTime: config.preferredLuckTime,
+ password: roomPassword.text,
+ disabledGenerals,
+ }])
+ );
+ }
+ }
+ Button {
+ text: Backend.translate("Cancel")
+ onClicked: {
+ root.finished();
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ let mode_data = JSON.parse(Backend.callLuaFunction("GetGameModes", []));
+ let i = 0;
+ for (let d of mode_data) {
+ gameModeList.append(d);
+ if (d.orig_name == config.preferedMode) {
+ gameModeCombo.currentIndex = i;
+ }
+ i += 1;
+ }
+
+ playerNum.value = config.preferedPlayerNum;
+ }
}
}
diff --git a/Fk/Pages/PackageManage.qml b/Fk/Pages/PackageManage.qml
index 6c15ab13..d008250d 100644
--- a/Fk/Pages/PackageManage.qml
+++ b/Fk/Pages/PackageManage.qml
@@ -6,195 +6,170 @@ import QtQuick.Layouts
Item {
id: root
- Button {
- text: qsTr("Quit")
- anchors.right: parent.right
- onClicked: {
- mainStack.pop();
- }
- }
- Component {
- id: packageDelegate
-
- Item {
- height: 22
- width: packageList.width
-
- RowLayout {
- anchors.fill: parent
- spacing: 16
- Text {
- font.pixelSize: 20
- text: pkgName
- }
-
- Text {
- font.pixelSize: 20
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- text: pkgURL
- }
-
- Text {
- font.pixelSize: 20
- text: pkgVersion
- }
-
- Text {
- font.pixelSize: 20
- color: pkgEnabled === "1" ? "green" : "red"
- text: pkgEnabled === "1" ? qsTr("Enabled") : qsTr("Disabled")
- }
+ ToolBar {
+ id: bar
+ width: parent.width
+ RowLayout {
+ anchors.fill: parent
+ ToolButton {
+ icon.source: AppPath + "/image/modmaker/back"
+ onClicked: mainStack.pop();
}
+ Label {
+ text: qsTr("Package Manager")
+ horizontalAlignment: Qt.AlignHCenter
+ Layout.fillWidth: true
+ }
+ ToolButton {
+ icon.source: AppPath + "/image/modmaker/menu"
+ onClicked: menu.open()
- TapHandler {
- onTapped: {
- if (packageList.currentIndex === index) {
- packageList.currentIndex = -1;
- } else {
- packageList.currentIndex = index;
+ Menu {
+ id: menu
+ y: bar.height
+
+ MenuItem {
+ text: qsTr("Enable All")
+ onTriggered: {
+ for (let i = 0; i < packageModel.count; i++) {
+ let name = packageModel.get(i).pkgName;
+ Pacman.enablePack(name);
+ }
+ updatePackageList();
+ }
+ }
+ MenuItem {
+ text: qsTr("Disable All")
+ onTriggered: {
+ for (let i = 0; i < packageModel.count; i++) {
+ let name = packageModel.get(i).pkgName;
+ Pacman.disablePack(name);
+ }
+ updatePackageList();
+ }
+ }
+ MenuItem {
+ text: qsTr("Upgrade All")
+ onTriggered: {
+ for (let i = 0; i < packageModel.count; i++) {
+ let name = packageModel.get(i).pkgName;
+ Pacman.upgradePack(name);
+ }
+ updatePackageList();
+ }
}
}
}
}
}
- ListModel {
- id: packageModel
- }
+ Rectangle {
+ width: parent.width
+ height: parent.height - bar.height - urlInstaller.height
+ anchors.top: bar.bottom
+ color: "snow"
+ opacity: 0.75
+ clip: true
- ColumnLayout {
- anchors.fill: parent
-
- RowLayout {
- Layout.fillHeight: true
- Layout.alignment: Qt.AlignHCenter
- Item {
- Layout.preferredWidth: root.width * 0.9
- Layout.fillHeight: true
- Rectangle {
- anchors.fill: parent
- color: "#88EEEEEE"
+ ListView {
+ id: packageList
+ anchors.fill: parent
+ model: ListModel {
+ id: packageModel
}
- ListView {
- id: packageList
- anchors.fill: parent
+ delegate: ItemDelegate {
+ width: root.width
+ height: 64
- contentHeight: packageDelegate.height * count
- ScrollBar.vertical: ScrollBar {}
- header: RowLayout {
- height: 22
- width: packageList.width
- spacing: 16
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.margins: 8
Text {
- font.pixelSize: 20
- text: qsTr("Name")
+ text: "" + pkgName + " (" + pkgVersion + ")"
+ font.pixelSize: 18
+ textFormat: Text.RichText
+ color: pkgEnabled === "1" ? "black" : "grey"
}
-
Text {
- font.pixelSize: 20
- Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- text: "URL"
- }
-
- Text {
- font.pixelSize: 20
- text: qsTr("Version")
- }
-
- Text {
- font.pixelSize: 20
- text: qsTr("Enable")
+ text: pkgURL
+ color: pkgEnabled === "1" ? "black" : "grey"
}
}
- delegate: packageDelegate
- model: packageModel
- highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
- Component.onCompleted: { currentIndex = -1; }
- }
- }
- ColumnLayout {
- Button {
- enabled: packageList.currentItem
- text: qsTr("Enable")
- onClicked: {
- let idx = packageList.currentIndex;
- let name = packageModel.get(idx).pkgName;
- Pacman.enablePack(name);
- updatePackageList();
- packageList.currentIndex = idx;
+ Button {
+ id: enableBtn
+ text: pkgEnabled === "0" ? qsTr("Enable") : qsTr("Disable")
+ anchors.right: upgradeBtn.left
+ anchors.rightMargin: 8
+ onClicked: {
+ if (pkgEnabled === "0") {
+ Pacman.enablePack(pkgName);
+ } else {
+ Pacman.disablePack(pkgName);
+ }
+ updatePackageList();
+ }
}
- }
- Button {
- enabled: packageList.currentItem
- text: qsTr("Disable")
- onClicked: {
- let idx = packageList.currentIndex;
- let name = packageModel.get(idx).pkgName;
- Pacman.disablePack(name);
- updatePackageList();
- packageList.currentIndex = idx;
+
+ Button {
+ id: upgradeBtn
+ text: qsTr("Upgrade")
+ anchors.right: delBtn.left
+ anchors.rightMargin: 8
+ onClicked: {
+ Pacman.upgradePack(pkgName);
+ updatePackageList();
+ }
}
- }
- Button {
- enabled: packageList.currentItem
- text: qsTr("Upgrade")
- onClicked: {
- let idx = packageList.currentIndex;
- let name = packageModel.get(idx).pkgName;
- Pacman.upgradePack(name);
- updatePackageList();
- packageList.currentIndex = idx;
+
+ Button {
+ id: delBtn
+ text: qsTr("Remove")
+ anchors.right: parent.right
+ anchors.rightMargin: 8
+ onClicked: {
+ Pacman.removePack(pkgName);
+ updatePackageList();
+ }
}
- }
- Button {
- enabled: packageList.currentItem
- text: qsTr("Remove")
+
onClicked: {
- let idx = packageList.currentIndex;
- let name = packageModel.get(idx).pkgName;
- Pacman.removePack(name);
- updatePackageList();
- packageList.currentIndex = idx;
- }
- }
- Button {
- enabled: packageList.currentItem
- text: qsTr("Copy URL")
- onClicked: {
- let idx = packageList.currentIndex;
- let name = packageModel.get(idx).pkgURL;
- Backend.copyToClipboard(name);
- toast.show(qsTr("Copied."));
+ Backend.copyToClipboard(pkgURL);
+ toast.show(qsTr("Copied %1.").arg(pkgURL));
}
}
}
}
- RowLayout {
- Layout.fillWidth: true
- TextField {
- id: urlEdit
- Layout.fillWidth: true
- clip: true
- }
+ Rectangle {
+ id: urlInstaller
+ width: parent.width
+ height: childrenRect.height
+ color: "snow"
+ opacity: 0.75
+ anchors.bottom: parent.bottom
- Button {
- text: qsTr("Install From URL")
- enabled: urlEdit.text !== ""
- onClicked: {
- let url = urlEdit.text;
- mainWindow.busy = true;
- Pacman.downloadNewPack(url, true);
+ RowLayout {
+ width: parent.width
+ TextField {
+ id: urlEdit
+ Layout.fillWidth: true
+ clip: true
+ }
+
+ Button {
+ text: qsTr("Install From URL")
+ enabled: urlEdit.text !== ""
+ onClicked: {
+ let url = urlEdit.text;
+ mainWindow.busy = true;
+ Pacman.downloadNewPack(url, true);
+ }
}
}
}
- }
-
function updatePackageList() {
packageModel.clear();
let data = JSON.parse(Pacman.listPackages());
diff --git a/Fk/Pages/Room.qml b/Fk/Pages/Room.qml
index 921022ab..1c0e4d9a 100644
--- a/Fk/Pages/Room.qml
+++ b/Fk/Pages/Room.qml
@@ -17,6 +17,9 @@ Item {
property bool isOwner: false
property bool isStarted: false
+ property bool isFull: false
+ property bool isAllReady: false
+ property bool isReady: false
property alias popupBox: popupBox
property alias manualBox: manualBox
@@ -79,13 +82,36 @@ Item {
}
}
Button {
- text: "add robot"
- visible: isOwner && !isStarted
+ text: Backend.translate("Add Robot")
+ visible: isOwner && !isStarted && !isFull
anchors.centerIn: parent
onClicked: {
ClientInstance.notifyServer("AddRobot", "[]");
}
}
+ Button {
+ text: Backend.translate("Start Game")
+ visible: isOwner && !isStarted && isFull
+ enabled: isAllReady
+ anchors.centerIn: parent
+ onClicked: {
+ ClientInstance.notifyServer("StartGame", "[]");
+ }
+ }
+ Timer {
+ id: opTimer
+ interval: 1000
+ }
+ Button {
+ text: isReady ? Backend.translate("Cancel Ready") : Backend.translate("Ready")
+ visible: !isOwner && !isStarted
+ enabled: !opTimer.running
+ anchors.centerIn: parent
+ onClicked: {
+ opTimer.start();
+ ClientInstance.notifyServer("Ready", "");
+ }
+ }
states: [
State { name: "notactive" }, // Normal status
@@ -195,6 +221,7 @@ Item {
Photo {
playerid: model.id
general: model.general
+ avatar: model.avatar
deputyGeneral: model.deputyGeneral
screenName: model.screenName
role: model.role
@@ -210,6 +237,7 @@ Item {
chained: model.chained
drank: model.drank
isOwner: model.isOwner
+ ready: model.ready
onSelectedChanged: {
Logic.updateSelectedTargets(playerid, selected);
@@ -830,6 +858,36 @@ Item {
cheatDrawer.open();
}
+ function resetToInit() {
+ let datalist = [];
+ for (let i = 0; i < photoModel.count; i++) {
+ let item = photoModel.get(i);
+ if (item.id > 0) {
+ datalist.push({
+ id: item.id,
+ avatar: item.avatar,
+ name: item.screenName,
+ isOwner: item.isOwner,
+ ready: item.ready,
+ });
+ }
+ }
+ mainStack.pop();
+ mainStack.push(room);
+ mainStack.currentItem.loadPlayerData(datalist);
+ }
+
+ function loadPlayerData(datalist) {
+ datalist.forEach(d => {
+ if (d.id == Self.id) {
+ roomScene.isOwner = d.isOwner;
+ } else {
+ callbacks["AddPlayer"](JSON.stringify([d.id, d.name, d.avatar, d.ready]));
+ }
+ Logic.getPhotoModel(d.id).isOwner = d.isOwner;
+ });
+ }
+
Component.onCompleted: {
toast.show(Backend.translate("$EnterRoom"));
playerNum = config.roomCapacity;
@@ -839,6 +897,7 @@ Item {
id: i ? -1 : Self.id,
index: i, // For animating seat swap
general: i ? "" : Self.avatar,
+ avatar: i ? "" : Self.avatar,
deputyGeneral: "",
screenName: i ? "" : Self.screenName,
role: "unknown",
@@ -853,7 +912,8 @@ Item {
faceup: true,
chained: false,
drank: 0,
- isOwner: false
+ isOwner: false,
+ ready: false,
});
}
diff --git a/Fk/Pages/RoomLogic.js b/Fk/Pages/RoomLogic.js
index e3334230..61befd6e 100644
--- a/Fk/Pages/RoomLogic.js
+++ b/Fk/Pages/RoomLogic.js
@@ -334,7 +334,7 @@ function changeSelf(id) {
}
callbacks["AddPlayer"] = function(jsonData) {
- // jsonData: int id, string screenName, string avatar
+ // jsonData: int id, string screenName, string avatar, bool ready
for (let i = 0; i < photoModel.count; i++) {
let item = photoModel.get(i);
if (item.id === -1) {
@@ -342,9 +342,22 @@ callbacks["AddPlayer"] = function(jsonData) {
let uid = data[0];
let name = data[1];
let avatar = data[2];
+ let ready = data[3];
+
item.id = uid;
item.screenName = name;
item.general = avatar;
+ item.avatar = avatar;
+ item.ready = ready;
+
+ checkAllReady();
+
+ if (getPhoto(-1)) {
+ roomScene.isFull = false;
+ } else {
+ roomScene.isFull = true;
+ }
+
return;
}
}
@@ -485,6 +498,8 @@ callbacks["RemovePlayer"] = function(jsonData) {
model.id = -1;
model.screenName = "";
model.general = "";
+ model.isOwner = false;
+ roomScene.isFull = false;
}
}
@@ -492,9 +507,7 @@ callbacks["RoomOwner"] = function(jsonData) {
// jsonData: int uid of the owner
let uid = JSON.parse(jsonData)[0];
- if (Self.id === uid) {
- roomScene.isOwner = true;
- }
+ roomScene.isOwner = (Self.id === uid);
let model = getPhotoModel(uid);
if (typeof(model) !== "undefined") {
@@ -502,6 +515,46 @@ callbacks["RoomOwner"] = function(jsonData) {
}
}
+function checkAllReady() {
+ let allReady = true;
+ for (let i = 0; i < photoModel.count; i++) {
+ let item = photoModel.get(i);
+ if (!item.isOwner && !item.ready) {
+ allReady = false;
+ break;
+ }
+ }
+ roomScene.isAllReady = allReady;
+}
+
+callbacks["ReadyChanged"] = (j) => {
+ const data = JSON.parse(j);
+ const id = data[0];
+ const ready = data[1];
+
+ if (id === Self.id) {
+ roomScene.isReady = ready === 1;
+ }
+
+ let model = getPhotoModel(id);
+ if (typeof(model) !== "undefined") {
+ model.ready = ready ? true : false;
+ checkAllReady();
+ }
+}
+
+callbacks["NetStateChanged"] = (j) => {
+ const data = JSON.parse(j);
+ const id = data[0];
+ let state = data[1];
+
+ let model = getPhotoModel(id);
+ if (state == "run" && model.dead) {
+ state = "leave";
+ }
+ model.netstate = state;
+}
+
callbacks["PropertyUpdate"] = function(jsonData) {
// jsonData: int id, string property_name, value
let data = JSON.parse(jsonData);
@@ -510,6 +563,7 @@ callbacks["PropertyUpdate"] = function(jsonData) {
let value = data[2];
let model = getPhotoModel(uid);
+
if (typeof(model) !== "undefined") {
model[property_name] = value;
}
@@ -520,6 +574,7 @@ callbacks["StartGame"] = function(jsonData) {
for (let i = 0; i < photoModel.count; i++) {
let item = photoModel.get(i);
+ item.ready = false;
item.general = "";
}
}
@@ -1013,6 +1068,12 @@ callbacks["LogEvent"] = function(jsonData) {
Backend.playSound("./audio/system/losehp");
break;
}
+ case "ChangeMaxHp": {
+ if (data.num < 0) {
+ Backend.playSound("./audio/system/losemaxhp");
+ }
+ break;
+ }
case "PlaySkillSound": {
let skill = data.name;
let extension = data.extension;
@@ -1042,7 +1103,7 @@ callbacks["GameOver"] = function(jsonData) {
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/GameOverBox.qml");
let box = roomScene.popupBox.item;
box.winner = jsonData;
- roomScene.isStarted = false;
+ // roomScene.isStarted = false;
}
callbacks["FillAG"] = (j) => {
diff --git a/Fk/PhotoElement/DelayedTrickArea.qml b/Fk/PhotoElement/DelayedTrickArea.qml
index b1db9b20..37a630f5 100644
--- a/Fk/PhotoElement/DelayedTrickArea.qml
+++ b/Fk/PhotoElement/DelayedTrickArea.qml
@@ -25,7 +25,7 @@ Item {
Image {
height: 55 * 0.8
width: 47 * 0.8
- source: SkinBank.DELAYED_TRICK_DIR + name
+ source: SkinBank.getDelayedTrickPicture(name) // SkinBank.DELAYED_TRICK_DIR + name
}
}
}
diff --git a/Fk/RoomElement/ChooseGeneralBox.qml b/Fk/RoomElement/ChooseGeneralBox.qml
index bbf4c924..71cf7f9c 100644
--- a/Fk/RoomElement/ChooseGeneralBox.qml
+++ b/Fk/RoomElement/ChooseGeneralBox.qml
@@ -18,7 +18,8 @@ GraphicsBox {
}
id: root
- title.text: Backend.translate("$ChooseGeneral").arg(choiceNum)
+ title.text: Backend.translate("$ChooseGeneral").arg(choiceNum) +
+ (config.enableFreeAssign ? "(" + Backend.translate("Enable free assign") + ")" : "")
width: generalArea.width + body.anchors.leftMargin + body.anchors.rightMargin
height: body.implicitHeight + body.anchors.topMargin + body.anchors.bottomMargin
diff --git a/Fk/RoomElement/GameOverBox.qml b/Fk/RoomElement/GameOverBox.qml
index 79af281e..d7b74e34 100644
--- a/Fk/RoomElement/GameOverBox.qml
+++ b/Fk/RoomElement/GameOverBox.qml
@@ -22,6 +22,16 @@ GraphicsBox {
color: "#E4D5A0"
}
+ MetroButton {
+ text: Backend.translate("Back To Room")
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ onClicked: {
+ roomScene.resetToInit();
+ finished();
+ }
+ }
+
MetroButton {
text: Backend.translate("Back To Lobby")
anchors.horizontalCenter: parent.horizontalCenter
diff --git a/Fk/RoomElement/Photo.qml b/Fk/RoomElement/Photo.qml
index c8792fab..30831920 100644
--- a/Fk/RoomElement/Photo.qml
+++ b/Fk/RoomElement/Photo.qml
@@ -13,6 +13,7 @@ Item {
scale: 0.75
property int playerid: 0
property string general: ""
+ property string avatar: ""
property string deputyGeneral: ""
property string screenName: ""
property string role: "unknown"
@@ -29,6 +30,7 @@ Item {
property bool chained: false
property int drank: 0
property bool isOwner: false
+ property bool ready: false
property int distance: 0
property string status: "normal"
property int maxCard: 0
@@ -249,7 +251,7 @@ Item {
anchors.right: parent.right
anchors.bottomMargin: 8
anchors.rightMargin: 4
- source: SkinBank.PHOTO_DIR + (isOwner ? "owner" : "ready")
+ source: SkinBank.PHOTO_DIR + (isOwner ? "owner" : (ready ? "ready" : "notready"))
visible: screenName != "" && !roomScene.isStarted
}
@@ -342,6 +344,8 @@ Item {
source: SkinBank.STATE_DIR + root.netstate
x: photoMask.x
y: photoMask.y
+ scale: 0.9
+ transformOrigin: Item.TopLeft
}
Image {
@@ -596,6 +600,10 @@ Item {
}
function showDetail() {
+ if (playerid === 0 || playerid === -1) {
+ return;
+ }
+
roomScene.startCheat("PlayerDetail", { photo: this });
}
}
diff --git a/Fk/skin-bank.js b/Fk/skin-bank.js
index b7db7a3b..f1c7c875 100644
--- a/Fk/skin-bank.js
+++ b/Fk/skin-bank.js
@@ -53,6 +53,22 @@ function getCardPicture(cidOrName) {
return CARD_DIR + "unknown.png";
}
+function getDelayedTrickPicture(name) {
+ let extension = Backend.callLuaFunction("GetCardExtensionByName", [name]);
+
+ let path = AppPath + "/packages/" + extension + "/image/card/delayedTrick/" + name + ".png";
+ if (Backend.exists(path)) {
+ return path;
+ } else {
+ for (let dir of Backend.ls(AppPath + "/packages/")) {
+ path = AppPath + "/packages/" + dir + "/image/card/delayedTrick/" + name + ".png";
+ if (Backend.exists(path)) return path;
+ }
+ }
+ return DELAYED_TRICK_DIR + "unknown.png";
+}
+
+
function getEquipIcon(cid, icon) {
let data = JSON.parse(Backend.callLuaFunction("GetCardData", [cid]));
let extension = data.extension;
diff --git a/audio/system/losemaxhp.mp3 b/audio/system/losemaxhp.mp3
new file mode 100644
index 00000000..e28f1296
Binary files /dev/null and b/audio/system/losemaxhp.mp3 differ
diff --git a/image/card/delayedTrick/lightning.png b/image/card/delayedTrick/unknown.png
similarity index 100%
rename from image/card/delayedTrick/lightning.png
rename to image/card/delayedTrick/unknown.png
diff --git a/image/photo/notready.png b/image/photo/notready.png
new file mode 100644
index 00000000..c0774756
Binary files /dev/null and b/image/photo/notready.png differ
diff --git a/image/photo/state/run.png b/image/photo/state/run.png
new file mode 100644
index 00000000..d04b605a
Binary files /dev/null and b/image/photo/state/run.png differ
diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts
index b6d68107..fb4ccdf5 100644
--- a/lang/zh_CN.ts
+++ b/lang/zh_CN.ts
@@ -15,7 +15,59 @@