diff --git a/android/copy_assets.sh b/android/copy_assets.sh
index f0bdef48..0354b04f 100755
--- a/android/copy_assets.sh
+++ b/android/copy_assets.sh
@@ -32,6 +32,7 @@ cp ../server/init.sql assets/res/server
cp ../LICENSE assets/res
cp ../zh_CN.qm assets/res
cp ../fk_ver assets/res
+cp ../waiting_tips.txt assets/res
# Due to Qt Android's bug, we need make sure every directory has a subfile (not subdir)
function fixDir() {
diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua
index 8161e614..079e26b3 100644
--- a/lua/client/i18n/zh_CN.lua
+++ b/lua/client/i18n/zh_CN.lua
@@ -31,6 +31,7 @@ Fk:loadTranslationTable{
["Player num"] = "玩家数目",
["Select general num"] = "选将数目",
["Operation timeout"] = "操作时长(秒)",
+ ["Luck Card Times"] = "手气卡次数",
["Game Mode"] = "游戏模式",
["Enable free assign"] = "自由选将",
["Enable deputy general"] = "启用副将机制",
@@ -128,10 +129,13 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
["$ChooseGeneral"] = "请选择 %1 名武将",
["Same General Convert"] = "替换武将",
["Fight"] = "出战",
+ ["Show General Detail"] = "查看技能",
["#PlayCard"] = "出牌阶段,请使用一张牌",
["#AskForGeneral"] = "请选择 1 名武将",
["#AskForSkillInvoke"] = "你想发动技能“%1”吗?",
+ ["#AskForLuckCard"] = "你想使用手气卡吗?还可以使用 %1 次,剩余手气卡∞张",
+ ["AskForLuckCard"] = "手气卡",
["#AskForChoice"] = "%1:请选择",
["#choose-trigger"] = "请选择一项技能发动",
["trigger"] = "选择技能",
diff --git a/lua/server/events/gameflow.lua b/lua/server/events/gameflow.lua
index 71bca5aa..c1f948f9 100644
--- a/lua/server/events/gameflow.lua
+++ b/lua/server/events/gameflow.lua
@@ -1,35 +1,113 @@
-- SPDX-License-Identifier: GPL-3.0-or-later
+local function drawInit(room, player, n)
+ -- TODO: need a new function to call the UI
+ local cardIds = room:getNCards(n)
+ player:addCards(Player.Hand, cardIds)
+ for _, id in ipairs(cardIds) do
+ Fk:filterCard(id, player)
+ end
+ local move_to_notify = {} ---@type CardsMoveStruct
+ move_to_notify.toArea = Card.PlayerHand
+ move_to_notify.to = player.id
+ move_to_notify.moveInfo = {}
+ move_to_notify.moveReason = fk.ReasonDraw
+ for _, id in ipairs(cardIds) do
+ table.insert(move_to_notify.moveInfo,
+ { cardId = id, fromArea = Card.DrawPile })
+ end
+ room:notifyMoveCards(nil, {move_to_notify})
+
+ for _, id in ipairs(cardIds) do
+ room:setCardArea(id, Card.PlayerHand, player.id)
+ end
+end
+
+local function discardInit(room, player)
+ local cardIds = player:getCardIds(Player.Hand)
+ player:removeCards(Player.Hand, cardIds)
+ table.insertTable(room.draw_pile, cardIds)
+ for _, id in ipairs(cardIds) do
+ Fk:filterCard(id, nil)
+ end
+
+ local move_to_notify = {} ---@type CardsMoveStruct
+ move_to_notify.from = player.id
+ move_to_notify.toArea = Card.DrawPile
+ move_to_notify.moveInfo = {}
+ move_to_notify.moveReason = fk.ReasonJustMove
+ for _, id in ipairs(cardIds) do
+ table.insert(move_to_notify.moveInfo,
+ { cardId = id, fromArea = Card.PlayerHand })
+ end
+ room:notifyMoveCards(nil, {move_to_notify})
+
+ for _, id in ipairs(cardIds) do
+ room:setCardArea(id, Card.DrawPile, nil)
+ end
+end
+
GameEvent.functions[GameEvent.DrawInitial] = function(self)
local room = self.room
+
+ local luck_data = {
+ drawInit = drawInit,
+ discardInit = discardInit,
+ playerList = table.map(room.alive_players, Util.IdMapper),
+ }
+
for _, player in ipairs(room.alive_players) do
local draw_data = { num = 4 }
room.logic:trigger(fk.DrawInitialCards, player, draw_data)
+ luck_data[player.id] = draw_data
+ luck_data[player.id].luckTime = room.settings.luckTime
+ if player.id < 0 then -- Robot
+ luck_data[player.id].luckTime = 0
+ end
if draw_data.num > 0 then
- -- TODO: need a new function to call the UI
- local cardIds = room:getNCards(draw_data.num)
- player:addCards(Player.Hand, cardIds)
- for _, id in ipairs(cardIds) do
- Fk:filterCard(id, player)
- end
- local move_to_notify = {} ---@type CardsMoveStruct
- move_to_notify.toArea = Card.PlayerHand
- move_to_notify.to = player.id
- move_to_notify.moveInfo = {}
- move_to_notify.moveReason = fk.ReasonDraw
- for _, id in ipairs(cardIds) do
- table.insert(move_to_notify.moveInfo,
- { cardId = id, fromArea = Card.DrawPile })
- end
- room:notifyMoveCards(nil, {move_to_notify})
-
- for _, id in ipairs(cardIds) do
- room:setCardArea(id, Card.PlayerHand, player.id)
- end
-
- room.logic:trigger(fk.AfterDrawInitialCards, player, data)
+ drawInit(room, player, draw_data.num)
end
end
+
+ if room.settings.luckTime <= 0 then
+ for _, player in ipairs(room.alive_players) do
+ local draw_data = luck_data[player.id]
+ draw_data.luckTime = nil
+ room.logic:trigger(fk.AfterDrawInitialCards, player, data)
+ end
+ return
+ end
+
+ room:setTag("LuckCardData", luck_data)
+ room:notifyMoveFocus(room.alive_players, "AskForLuckCard")
+ room:doBroadcastNotify("AskForLuckCard", room.settings.luckTime or 4)
+
+ local remainTime = room.timeout
+ local currentTime = os.time()
+ local elapsed = 0
+
+ while true do
+ elapsed = os.time() - currentTime
+ if remainTime - elapsed <= 0 then
+ break
+ end
+
+ if table.every(room:getTag("LuckCardData").playerList, function(id)
+ return room:getTag("LuckCardData")[id].luckTime == 0
+ end) then
+ break
+ end
+
+ coroutine.yield("__handleRequest", (remainTime - elapsed) * 1000)
+ end
+
+ for _, player in ipairs(room.alive_players) do
+ local draw_data = luck_data[player.id]
+ draw_data.luckTime = nil
+ room.logic:trigger(fk.AfterDrawInitialCards, player, data)
+ end
+
+ room:removeTag("LuckCardData")
end
GameEvent.functions[GameEvent.Round] = function(self)
diff --git a/lua/server/request.lua b/lua/server/request.lua
index 6bf30ca6..a7469872 100644
--- a/lua/server/request.lua
+++ b/lua/server/request.lua
@@ -85,6 +85,27 @@ request_handlers["prelight"] = function(room, id, reqlist)
p:prelightSkill(reqlist[3], reqlist[4] == "true")
end
+request_handlers["luckcard"] = function(room, id, reqlist)
+ local p = room:getPlayerById(id)
+ local cancel = reqlist[3] == "false"
+ local luck_data = room:getTag("LuckCardData")
+ local pdata = luck_data[id]
+
+ if not cancel then
+ pdata.luckTime = pdata.luckTime - 1
+ luck_data.discardInit(room, p)
+ luck_data.drawInit(room, p, pdata.num)
+ else
+ pdata.luckTime = 0
+ end
+
+ if pdata.luckTime > 0 then
+ p:doNotify("AskForLuckCard", pdata.luckTime)
+ end
+
+ room:setTag("LuckCardData", luck_data)
+end
+
request_handlers["changeself"] = function(room, id, reqlist)
local p = room:getPlayerById(id)
local toId = tonumber(reqlist[3])
@@ -107,7 +128,8 @@ request_handlers["changeself"] = function(room, id, reqlist)
})
end
-local function requestLoop(self, rest_time)
+local function requestLoop(self)
+ local rest_time = 0
while true do
local ret = false
local request = self.room:fetchRequest()
@@ -122,7 +144,7 @@ local function requestLoop(self, rest_time)
-- otherwise CPU usage will be 100% (infinite yield <-> resume loop)
fk.QThread_msleep(10)
end
- coroutine.yield(ret)
+ rest_time = coroutine.yield(ret)
end
end
diff --git a/lua/server/room.lua b/lua/server/room.lua
index 233a1794..2759cbd7 100644
--- a/lua/server/room.lua
+++ b/lua/server/room.lua
@@ -71,8 +71,8 @@ function Room:initialize(_room)
local main_co = coroutine.create(function()
self:run()
end)
- local request_co = coroutine.create(function(rest)
- self:requestLoop(rest)
+ local request_co = coroutine.create(function()
+ self:requestLoop()
end)
local ret, err_msg, rest_time = true, true
while not self.game_finished do
@@ -642,8 +642,7 @@ function Room:doRaceRequest(command, players, jsonData)
break
end
- coroutine.yield("__handleRequest", remainTime - elapsed)
- fk.QThread_msleep(10)
+ coroutine.yield("__handleRequest", (remainTime - elapsed) * 1000)
end
for _, p in ipairs(self.players) do
@@ -2525,7 +2524,7 @@ function Room:gameOver(winner)
end
self.room:gameOver()
- coroutine.yield("__handleRequest")
+ coroutine.yield("__handleRequest", 0)
end
---@param card Card
diff --git a/qml/Config.qml b/qml/Config.qml
index e51b21e0..c854bc20 100644
--- a/qml/Config.qml
+++ b/qml/Config.qml
@@ -25,6 +25,7 @@ QtObject {
property var disabledGenerals: []
property int preferredTimeout
+ property int preferredLuckTime
// Player property of client
property string serverAddr
@@ -60,6 +61,7 @@ QtObject {
bgmVolume = conf.bgmVolume ?? 50.;
disableMsgAudio = conf.disableMsgAudio ?? false;
preferredTimeout = conf.preferredTimeout ?? 15;
+ preferredLuckTime = conf.preferredLuckTime ?? 0;
disabledGenerals = conf.disabledGenerals ?? [];
}
@@ -83,6 +85,7 @@ QtObject {
conf.bgmVolume = bgmVolume;
conf.disableMsgAudio = disableMsgAudio;
conf.preferredTimeout = preferredTimeout;
+ conf.preferredLuckTime = preferredLuckTime;
conf.disabledGenerals = disabledGenerals;
Backend.saveConf(JSON.stringify(conf, undefined, 2));
diff --git a/qml/Pages/Common/LogEdit.qml b/qml/Pages/Common/LogEdit.qml
index 3735e77c..e9607baa 100644
--- a/qml/Pages/Common/LogEdit.qml
+++ b/qml/Pages/Common/LogEdit.qml
@@ -5,15 +5,12 @@ import QtQuick.Controls
ListView {
id: root
- //property alias font: textEdit.font
- //property alias text: textEdit.text
- //property alias color: textEdit.color
- //property alias textFormat: textEdit.textFormat
- //flickableDirection: Flickable.VerticalFlick
- //contentWidth: textEdit.width
- //contentHeight: textEdit.height
clip: true
+
+ highlight: Rectangle { color: "#EEEEEE"; radius: 5 }
+ highlightMoveDuration: 500
+
ScrollBar.vertical: ScrollBar {
parent: root.parent
anchors.top: root.top
@@ -30,17 +27,27 @@ ListView {
clip: true
readOnly: true
selectByKeyboard: true
- selectByMouse: true
+ selectByMouse: false
wrapMode: TextEdit.WrapAnywhere
textFormat: TextEdit.RichText
font.pixelSize: 16
+
+ TapHandler {
+ onTapped: root.currentIndex = index;
+ }
+ }
+
+ Button {
+ text: "Return to Bottom"
+ visible: root.currentIndex !== logModel.count - 1
+ onClicked: root.currentIndex = logModel.count - 1;
}
function append(text) {
- let autoScroll = atYEnd;
+ let autoScroll = root.currentIndex === logModel.count - 1;
logModel.append({ logText: text });
- if (autoScroll && contentHeight > contentY + height) {
- contentY = contentHeight - height;
+ if (autoScroll) {
+ root.currentIndex = logModel.count - 1;
}
}
}
diff --git a/qml/Pages/LobbyElement/RoomGeneralSettings.qml b/qml/Pages/LobbyElement/RoomGeneralSettings.qml
index d723f823..7d3044c2 100644
--- a/qml/Pages/LobbyElement/RoomGeneralSettings.qml
+++ b/qml/Pages/LobbyElement/RoomGeneralSettings.qml
@@ -96,6 +96,23 @@ ColumnLayout {
}
}
+ 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;
+ }
+ }
+ }
+
Switch {
id: freeAssignCheck
checked: Debugging ? true : false
@@ -136,6 +153,7 @@ ColumnLayout {
gameMode: config.preferedMode,
disabledPack: config.disabledPack,
generalNum: config.preferredGeneralNum,
+ luckTime: config.preferredLuckTime,
disabledGenerals,
}])
);
diff --git a/qml/Pages/RoomElement/CardItem.qml b/qml/Pages/RoomElement/CardItem.qml
index de7a821e..7b36516a 100644
--- a/qml/Pages/RoomElement/CardItem.qml
+++ b/qml/Pages/RoomElement/CardItem.qml
@@ -46,6 +46,7 @@ Item {
property bool selected: false
property bool draggable: false
property bool autoBack: true
+ property bool showDetail: false
property int origX: 0
property int origY: 0
property real origOpacity: 1
@@ -67,6 +68,11 @@ Item {
signal generalChanged() // For choose general freely
signal hoverChanged(bool enter)
+ onRightClicked: {
+ if (!showDetail) return;
+ roomScene.startCheat("RoomElement/Cheat/CardDetail.qml", { card: this });
+ }
+
RectangularGlow {
id: glowItem
anchors.fill: parent
diff --git a/qml/Pages/RoomElement/Cheat/CardDetail.qml b/qml/Pages/RoomElement/Cheat/CardDetail.qml
new file mode 100644
index 00000000..7f5c33d4
--- /dev/null
+++ b/qml/Pages/RoomElement/Cheat/CardDetail.qml
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Flickable {
+ id: root
+ anchors.fill: parent
+ property var extra_data: ({})
+
+ signal finish()
+
+ contentHeight: details.height
+ ScrollBar.vertical: ScrollBar {}
+
+ ColumnLayout {
+ id: details
+ width: parent.width - 40
+ x: 20
+
+ // TODO: player details
+ Text {
+ id: screenName
+ 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
+ }
+ }
+
+ onExtra_dataChanged: {
+ const card = extra_data.card;
+ if (!card) return;
+ const name = card.virt_name ? card.virt_name : card.name;
+ screenName.text = Backend.translate(name);
+ skillDesc.text = Backend.translate(":" + name);
+ }
+}
diff --git a/qml/Pages/RoomElement/Cheat/GeneralDetail.qml b/qml/Pages/RoomElement/Cheat/GeneralDetail.qml
new file mode 100644
index 00000000..1fef8880
--- /dev/null
+++ b/qml/Pages/RoomElement/Cheat/GeneralDetail.qml
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Flickable {
+ id: root
+ anchors.fill: parent
+ property var extra_data: ({})
+
+ signal finish()
+
+ contentHeight: details.height
+ ScrollBar.vertical: ScrollBar {}
+
+ ColumnLayout {
+ id: details
+ width: parent.width - 40
+ x: 20
+
+ TextEdit {
+ id: skillDesc
+
+ Layout.fillWidth: true
+ font.pixelSize: 18
+
+ readOnly: true
+ selectByKeyboard: true
+ selectByMouse: false
+ wrapMode: TextEdit.WordWrap
+ textFormat: TextEdit.RichText
+ }
+ }
+
+ onExtra_dataChanged: {
+ if (!extra_data.generals) return;
+ skillDesc.text = "";
+
+ extra_data.generals.forEach((g) => {
+ let data = JSON.parse(Backend.callLuaFunction("GetGeneralDetail", [g]));
+ skillDesc.append(Backend.translate(data.kingdom) + " " + Backend.translate(g) + " " + data.hp + "/" + data.maxHp);
+ data.skill.forEach(t => {
+ skillDesc.append("" + Backend.translate(t.name) + ": " + t.description)
+ });
+ data.related_skill.forEach(t => {
+ skillDesc.append("" + Backend.translate(t.name) + ": " + t.description + "")
+ });
+ skillDesc.append("\n");
+ });
+ }
+}
diff --git a/qml/Pages/RoomElement/Cheat/PlayerDetail.qml b/qml/Pages/RoomElement/Cheat/PlayerDetail.qml
index a0116aad..510925c6 100644
--- a/qml/Pages/RoomElement/Cheat/PlayerDetail.qml
+++ b/qml/Pages/RoomElement/Cheat/PlayerDetail.qml
@@ -16,7 +16,8 @@ Flickable {
ColumnLayout {
id: details
- width: parent.width - 16
+ width: parent.width - 40
+ x: 20
// TODO: player details
Text {
diff --git a/qml/Pages/RoomElement/ChooseGeneralBox.qml b/qml/Pages/RoomElement/ChooseGeneralBox.qml
index 090b4af9..379f257d 100644
--- a/qml/Pages/RoomElement/ChooseGeneralBox.qml
+++ b/qml/Pages/RoomElement/ChooseGeneralBox.qml
@@ -106,6 +106,16 @@ GraphicsBox {
onClicked: close();
}
+
+ MetroButton {
+ id: detailBtn
+ enabled: choices.length > 0
+ text: Backend.translate("Show General Detail")
+ onClicked: roomScene.startCheat(
+ "RoomElement/Cheat/GeneralDetail.qml",
+ { generals: choices }
+ );
+ }
}
}
}
@@ -179,6 +189,7 @@ GraphicsBox {
item.goBack(true);
}
}
+ root.choicesChanged();
fightButton.enabled = (choices.length == choiceNum);
@@ -201,10 +212,10 @@ GraphicsBox {
if (JSON.parse(Backend.callLuaFunction(
"GetSameGenerals", [generalList.get(i).name])
).length > 0) {
- convertBtn.visible = true;
+ convertBtn.enabled = true;
return;
}
}
- convertBtn.visible = false;
+ convertBtn.enabled = false;
}
}
diff --git a/qml/Pages/RoomElement/GeneralCardItem.qml b/qml/Pages/RoomElement/GeneralCardItem.qml
index 916ff71e..23aa89b1 100644
--- a/qml/Pages/RoomElement/GeneralCardItem.qml
+++ b/qml/Pages/RoomElement/GeneralCardItem.qml
@@ -111,7 +111,7 @@ CardItem {
color: "white"
font.family: fontLibian.name
font.pixelSize: 18
- lineHeight: Math.max(1.4 - lineCount / 10, 0.6)
+ lineHeight: Math.max(1.4 - lineCount / 8, 0.6)
style: Text.Outline
wrapMode: Text.WrapAnywhere
}
diff --git a/qml/Pages/RoomElement/HandcardArea.qml b/qml/Pages/RoomElement/HandcardArea.qml
index 7a85c8cd..8d995a51 100644
--- a/qml/Pages/RoomElement/HandcardArea.qml
+++ b/qml/Pages/RoomElement/HandcardArea.qml
@@ -34,6 +34,7 @@ Item {
card.autoBack = true;
card.draggable = true;
card.selectable = false;
+ card.showDetail = true;
card.clicked.connect(adjustCards);
}
@@ -45,6 +46,7 @@ Item {
card = result[i];
card.draggable = false;
card.selectable = false;
+ card.showDetail = false;
card.selectedChanged.disconnect(adjustCards);
}
return result;
diff --git a/qml/Pages/RoomElement/Photo.qml b/qml/Pages/RoomElement/Photo.qml
index bb9fb5d4..1df8ebc5 100644
--- a/qml/Pages/RoomElement/Photo.qml
+++ b/qml/Pages/RoomElement/Photo.qml
@@ -511,7 +511,6 @@ Item {
DelayedTrickArea {
id: delayedTrickAreaItem
- rows: 1
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
}
diff --git a/qml/Pages/RoomElement/PhotoElement/DelayedTrickArea.qml b/qml/Pages/RoomElement/PhotoElement/DelayedTrickArea.qml
index 7dbb504e..40b4c9cc 100644
--- a/qml/Pages/RoomElement/PhotoElement/DelayedTrickArea.qml
+++ b/qml/Pages/RoomElement/PhotoElement/DelayedTrickArea.qml
@@ -5,9 +5,6 @@ import ".."
import "../../skin-bank.js" as SkinBank
Item {
- property alias rows: grid.rows
- property alias columns: grid.columns
-
InvisibleCardArea {
id: area
checkExisting: true
@@ -17,16 +14,17 @@ Item {
id: cards
}
- Grid {
+ Row {
id: grid
anchors.fill: parent
- rows: 100
- columns: 100
+ spacing: -4
Repeater {
model: cards
Image {
+ height: 55 * 0.8
+ width: 47 * 0.8
source: SkinBank.DELAYED_TRICK_DIR + name
}
}
diff --git a/qml/Pages/RoomLogic.js b/qml/Pages/RoomLogic.js
index ab128abd..71fddef4 100644
--- a/qml/Pages/RoomLogic.js
+++ b/qml/Pages/RoomLogic.js
@@ -78,6 +78,18 @@ function doOkButton() {
));
return;
}
+ if (roomScene.extra_data.luckCard) {
+ okButton.enabled = false;
+ ClientInstance.notifyServer("PushRequest", [
+ "luckcard", true
+ ].join(","));
+
+ if (roomScene.extra_data.time == 1) {
+ roomScene.state = "notactive";
+ }
+
+ return;
+ }
replyToServer("1");
}
@@ -103,6 +115,13 @@ function doCancelButton() {
return;
}
+ if (roomScene.extra_data.luckCard) {
+ ClientInstance.notifyServer("PushRequest", [
+ "luckcard", false
+ ].join(","));
+ roomScene.state = "notactive";
+ return;
+ }
replyToServer("__cancel");
}
@@ -1060,3 +1079,17 @@ callbacks["ChangeSelf"] = (j) => {
}
changeSelf(data);
}
+
+callbacks["AskForLuckCard"] = (j) => {
+ // jsonData: int time
+ const time = parseInt(j);
+ roomScene.promptText = Backend.translate("#AskForLuckCard").arg(time);
+ roomScene.state = "replying";
+ roomScene.extra_data = {
+ luckCard: true,
+ time: time,
+ };
+ roomScene.okCancel.visible = true;
+ roomScene.okButton.enabled = true;
+ roomScene.cancelButton.enabled = true;
+}
diff --git a/qml/Splash.qml b/qml/Splash.qml
index 9e71bf03..01a7c02d 100644
--- a/qml/Splash.qml
+++ b/qml/Splash.qml
@@ -151,10 +151,13 @@ Rectangle {
}
Text {
- text: "FK联机交流群:531553435"
+ text: "常用联机IP:175.178.66.93\nFK联机交流群:531553435"
font.pixelSize: 20
anchors.bottom: parent.bottom
+ anchors.bottomMargin: 20
anchors.right: parent.right
+ anchors.rightMargin: 20
+ horizontalAlignment: Text.AlignRight
}
//--------------------Disappear--------------
diff --git a/qml/main.qml b/qml/main.qml
index 36bc515f..9004e648 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -15,6 +15,7 @@ Window {
minimumHeight: 90
title: "FreeKill v" + FkVersion
property var callbacks: Logic.callbacks
+ property var tipList: []
Item {
id: mainWindow
@@ -67,10 +68,45 @@ Item {
onBusyChanged: busyText = "";
BusyIndicator {
+ id: busyIndicator
running: true
anchors.centerIn: parent
visible: mainWindow.busy === true
}
+
+ Text {
+ anchors.top: busyIndicator.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.topMargin: 8
+ visible: mainWindow.busy === true
+
+ property int idx: 1
+ text: tipList[idx - 1] ?? ""
+ color: "#F0E5DA"
+ font.pixelSize: 20
+ font.family: fontLibian.name
+ style: Text.Outline
+ styleColor: "#3D2D1C"
+ textFormat: Text.RichText
+ width: parent.width * 0.7
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.WrapAnywhere
+
+ onVisibleChanged: idx = 0;
+
+ Timer {
+ running: parent.visible
+ interval: 3600
+ repeat: true
+ onTriggered: {
+ const oldIdx = parent.idx;
+ while (parent.idx === oldIdx) {
+ parent.idx = Math.floor(Math.random() * tipList.length) + 1;
+ }
+ }
+ }
+ }
+
Item {
visible: mainWindow.busy === true && mainWindow.busyText !== ""
anchors.bottom: parent.bottom
@@ -247,6 +283,9 @@ Item {
width = config.winWidth;
height = config.winHeight;
}
+
+ const tips = Backend.loadTips();
+ tipList = tips.trim().split("\n");
}
onClosing: {
diff --git a/src/ui/qmlbackend.cpp b/src/ui/qmlbackend.cpp
index ab999fb8..147d88df 100644
--- a/src/ui/qmlbackend.cpp
+++ b/src/ui/qmlbackend.cpp
@@ -231,6 +231,18 @@ QString QmlBackend::loadConf() {
return conf.readAll();
}
+QString QmlBackend::loadTips() {
+ QFile conf("waiting_tips.txt");
+ if (!conf.exists()) {
+ conf.open(QIODevice::WriteOnly);
+ static const char *init_conf = "转啊~ 转啊~";
+ conf.write(init_conf);
+ return init_conf;
+ }
+ conf.open(QIODevice::ReadOnly);
+ return conf.readAll();
+}
+
void QmlBackend::saveConf(const QString &conf) {
QFile c("freekill.client.config.json");
c.open(QIODevice::WriteOnly);
diff --git a/src/ui/qmlbackend.h b/src/ui/qmlbackend.h
index e492f049..26801838 100644
--- a/src/ui/qmlbackend.h
+++ b/src/ui/qmlbackend.h
@@ -38,6 +38,7 @@ public:
Q_INVOKABLE QString pubEncrypt(const QString &key, const QString &data);
Q_INVOKABLE QString loadConf();
+ Q_INVOKABLE QString loadTips();
Q_INVOKABLE void saveConf(const QString &conf);
Q_INVOKABLE void replyDelayTest(const QString &screenName, const QString &cipher);
diff --git a/waiting_tips.txt b/waiting_tips.txt
new file mode 100644
index 00000000..4dd7104b
--- /dev/null
+++ b/waiting_tips.txt
@@ -0,0 +1,26 @@
+在对局中长按他人武将牌可以查看其技能哦
+长按手牌可以查看这张卡牌的详细信息
+在大厅界面点击左上角的头像可以进行各种设置
+在聊天中输入$zhiheng:1试试看?
+在聊天中输入$~caocao试试看?
+不要为了一个战功,放弃你的队友,你不是一个人在战斗。
+转啊~ 转啊~
+给FreeKill的GitHub仓库点一个star吧!
+你可以在武将一览界面禁将,在你创建的房间中禁用武将不会出现在选将框。
+如果你遇到了bug,请截图并反馈给开发者
+如果你想要制作FK的mod,需要先学习Lua语言
+目光所及短寸吾才之间满腹狭目之阿瞒有我见袁本良计初只能窥取冀州便是底竟不从易成略在胸如反掌之良计速出吾才满目光所及腹袁本初竟短寸之间不从之
+吔!
+想要参与到FK的开发工作中?那么就从制作自己的Mod开始吧!
+在游戏的一些地方,长按可以显示该元素的详情。如果你用的是电脑版的话可以用鼠标右键代替长按。
+注意:官方不支持任何形式的账号交易行为,请妥善保管好您的账号密码。请勿与他人共享账号。因账号交易、共享引起的账号争议官方均不受理。
+如果牌不好的话,就请辱骂GK的发牌员吧
+行动前请三思,需要先明确全场所有人的技能与卡牌的效果,再去做出决定。
+神曰:“MBKS”
+正在匹配势均力敌的对手…… 匹配到界徐盛
+先喝酒还是先上刀,这是个值得考虑的问题
+在抱怨FK只有标准包?那么去试着参与联机吧
+如果在牌局内想查看技能,可以长按想要看技能的角色
+FK的开服很简单,只要单机启动就可以当做服务器使用了
+用Linux也能搭建FK服务器,起始页推荐的联机IP就是跑在Linux服务器上的
+我们的游戏正在蒸蒸日上哦~