mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-15 19:22:25 +08:00
Misc (#184)
- 复活角色 - 将cancelable全改为默认true - move私有牌堆的未知牌时不再显示错误 - 处理区牌增加大多数脚注 - 装备栏有宝物时压缩间距 - 使用虚拟牌时处理区有虚拟名字 - 带详细描述的选择框 - 武将一览界面显示技能语音、胜利语音、死亡语音
This commit is contained in:
parent
04f1009075
commit
7f718503bd
|
@ -17,19 +17,19 @@ ColumnLayout {
|
|||
font.pixelSize: 20
|
||||
font.bold: true
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr(hint)
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("validator_hint")
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
|
|
@ -12,7 +12,7 @@ ColumnLayout {
|
|||
Text {
|
||||
text: qsTr("help_text")
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -54,7 +54,7 @@ ColumnLayout {
|
|||
Text {
|
||||
text: qsTr("key_help_text")
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
wrapMode: Text.WordWrap
|
||||
textFormat: Text.RichText
|
||||
onLinkActivated: Qt.openUrlExternally(link);
|
||||
}
|
||||
|
|
|
@ -148,16 +148,42 @@ Item {
|
|||
radius: 8
|
||||
|
||||
property string general: "caocao"
|
||||
|
||||
function addSkillAudio(skill) {
|
||||
const skilldata = JSON.parse(Backend.callLuaFunction("GetSkillData", [skill]));
|
||||
if (!skilldata) return;
|
||||
const extension = skilldata.extension;
|
||||
for (let i = 0; i < 999; i++) {
|
||||
let fname = AppPath + "/packages/" + extension + "/audio/skill/" +
|
||||
skill + (i !== 0 ? i.toString() : "") + ".mp3";
|
||||
|
||||
if (Backend.exists(fname)) {
|
||||
audioModel.append({ name: skill, idx: i });
|
||||
} else {
|
||||
if (i > 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateGeneral() {
|
||||
detailGeneralCard.name = general;
|
||||
const data = JSON.parse(Backend.callLuaFunction("GetGeneralDetail", [general]));
|
||||
generalText.clear();
|
||||
audioModel.clear();
|
||||
data.skill.forEach(t => {
|
||||
generalText.append("<b>" + Backend.translate(t.name) + "</b>: " + t.description)
|
||||
generalText.append("<b>" + Backend.translate(t.name) +
|
||||
"</b>: " + t.description);
|
||||
|
||||
addSkillAudio(t.name);
|
||||
});
|
||||
data.related_skill.forEach(t => {
|
||||
generalText.append("<font color=\"purple\"><b>" + Backend.translate(t.name) + "</b>: " + t.description + "</font>")
|
||||
generalText.append("<font color=\"purple\"><b>" + Backend.translate(t.name) +
|
||||
"</b>: " + t.description + "</font>");
|
||||
|
||||
addSkillAudio(t.name);
|
||||
});
|
||||
|
||||
addSkillAudio(general + "_win_audio");
|
||||
}
|
||||
|
||||
Flickable {
|
||||
|
@ -190,6 +216,58 @@ Item {
|
|||
textFormat: TextEdit.RichText
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: ListModel {
|
||||
id: audioModel
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
contentItem: ColumnLayout {
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: Backend.translate(name) + (idx ? " (" + idx.toString() + ")" : "")
|
||||
font.bold: true
|
||||
font.pixelSize: 14
|
||||
}
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: Backend.translate("$" + name + (idx ? idx.toString() : ""))
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
const skilldata = JSON.parse(Backend.callLuaFunction("GetSkillData", [name]));
|
||||
const extension = skilldata.extension;
|
||||
Backend.playSound("./packages/" + extension +
|
||||
"/audio/skill/" + name, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
contentItem: ColumnLayout {
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: Backend.translate("Death audio")
|
||||
font.bold: true
|
||||
font.pixelSize: 14
|
||||
}
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: Backend.translate("~" + generalDetail.general)
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
const general = generalDetail.general
|
||||
const extension = JSON.parse(Backend.callLuaFunction("GetGeneralData", [general])).extension;
|
||||
Backend.playSound("./packages/" + extension + "/audio/death/" + general);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ Item {
|
|||
Text {
|
||||
id: bulletin_info
|
||||
width: parent.width
|
||||
wrapMode: TextEdit.WrapAnywhere
|
||||
wrapMode: TextEdit.WordWrap
|
||||
textFormat: Text.MarkdownText
|
||||
text: Backend.translate('Bulletin Info')
|
||||
}
|
||||
|
|
|
@ -263,6 +263,53 @@ function setEmotion(id, emotion, isCardId) {
|
|||
animation.start();
|
||||
}
|
||||
|
||||
function setCardFootnote(id, footnote) {
|
||||
let card;
|
||||
roomScene.tableCards.forEach((v) => {
|
||||
if (v.cid === id) {
|
||||
card = v;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
card.footnote = footnote;
|
||||
card.footnoteVisible = true;
|
||||
}
|
||||
|
||||
callbacks["SetCardFootnote"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
const id = data[0];
|
||||
const note = data[1];
|
||||
setCardFootnote(id, note);
|
||||
}
|
||||
|
||||
function setCardVirtName(id, name) {
|
||||
let card;
|
||||
roomScene.tableCards.forEach((v) => {
|
||||
if (v.cid === id) {
|
||||
card = v;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
card.virt_name = name;
|
||||
}
|
||||
|
||||
callbacks["SetCardVirtName"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
const ids = data[0];
|
||||
const note = data[1];
|
||||
ids.forEach(id => setCardVirtName(id, note));
|
||||
}
|
||||
|
||||
function changeHp(id, delta, losthp) {
|
||||
const photo = getPhoto(id);
|
||||
if (!photo) {
|
||||
|
@ -754,6 +801,7 @@ callbacks["AskForChoice"] = (jsonData) => {
|
|||
const choices = data[0];
|
||||
const skill_name = data[1];
|
||||
const prompt = data[2];
|
||||
const detailed = data[3];
|
||||
if (prompt === "") {
|
||||
roomScene.promptText = Backend.translate("#AskForChoice")
|
||||
.arg(Backend.translate(skill_name));
|
||||
|
@ -761,7 +809,13 @@ callbacks["AskForChoice"] = (jsonData) => {
|
|||
roomScene.promptText = processPrompt(prompt);
|
||||
}
|
||||
roomScene.state = "replying";
|
||||
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/ChoiceBox.qml");
|
||||
let qmlSrc;
|
||||
if (!detailed) {
|
||||
qmlSrc = "../RoomElement/ChoiceBox.qml";
|
||||
} else {
|
||||
qmlSrc = "../RoomElement/DetailedChoiceBox.qml";
|
||||
}
|
||||
roomScene.popupBox.sourceComponent = Qt.createComponent(qmlSrc);
|
||||
const box = roomScene.popupBox.item;
|
||||
box.options = choices;
|
||||
box.skill_name = skill_name;
|
||||
|
|
|
@ -13,9 +13,9 @@ import Fk.RoomElement
|
|||
*/
|
||||
|
||||
Column {
|
||||
height: 88
|
||||
height: 70
|
||||
width: 138
|
||||
property int itemHeight: Math.floor(height / 4)
|
||||
property int itemHeight: treasureItem.name === "" ? height / 3 : height / 4
|
||||
property var items: [treasureItem, weaponItem, armorItem, defensiveHorseItem, offensiveHorseItem]
|
||||
property var subtypes: ["treasure", "weapon", "armor", "defensive_horse", "offensive_horse"]
|
||||
property int length: area.length
|
||||
|
@ -29,7 +29,7 @@ Column {
|
|||
EquipItem {
|
||||
id: treasureItem
|
||||
width: parent.width
|
||||
height: itemHeight
|
||||
height: name === "" ? 0 : itemHeight
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
|
|
|
@ -120,31 +120,44 @@ Item {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
id: virt_rect
|
||||
visible: root.virt_name !== ""
|
||||
width: parent.width
|
||||
height: 14
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: Backend.translate(root.virt_name)
|
||||
}
|
||||
height: 20
|
||||
y: 40
|
||||
color: "snow"
|
||||
opacity: 0.8
|
||||
radius: 4
|
||||
border.color: "black"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
GlowText {
|
||||
Text {
|
||||
visible: virt_rect.visible
|
||||
anchors.centerIn: virt_rect
|
||||
font.pixelSize: 16
|
||||
font.family: fontLibian.name
|
||||
font.letterSpacing: -0.6
|
||||
text: Backend.translate(root.virt_name)
|
||||
}
|
||||
|
||||
Text {
|
||||
id: footnoteItem
|
||||
text: footnote
|
||||
x: 6
|
||||
y: parent.height - height - 6
|
||||
x: 0
|
||||
y: parent.height - height - 10
|
||||
width: root.width - x * 2
|
||||
color: "#E4D5A0"
|
||||
// color: "white"
|
||||
visible: footnoteVisible
|
||||
style: Text.Outline
|
||||
wrapMode: Text.WrapAnywhere
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.family: fontLibian.name
|
||||
font.pixelSize: 14
|
||||
glow.color: "black"
|
||||
glow.spread: 1
|
||||
glow.radius: 1
|
||||
// glow.color: "black"
|
||||
// glow.spread: 1
|
||||
// glow.radius: 1
|
||||
//glow.samples: 12
|
||||
}
|
||||
|
||||
|
|
67
Fk/RoomElement/DetailedChoiceBox.qml
Normal file
67
Fk/RoomElement/DetailedChoiceBox.qml
Normal file
|
@ -0,0 +1,67 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import Fk.Pages
|
||||
|
||||
GraphicsBox {
|
||||
property var options: []
|
||||
property string skill_name: ""
|
||||
property int result
|
||||
|
||||
id: root
|
||||
title.text: Backend.translate("$Choice").arg(Backend.translate(skill_name))
|
||||
width: Math.max(140, body.width + 20)
|
||||
height: body.height + title.height + 20
|
||||
|
||||
ListView {
|
||||
id: body
|
||||
x: 10
|
||||
y: title.height + 5
|
||||
width: Math.min(700, 220 * model.length)
|
||||
height: 300
|
||||
orientation: ListView.Horizontal
|
||||
clip: true
|
||||
spacing: 20
|
||||
|
||||
model: options
|
||||
|
||||
delegate: Item {
|
||||
width: 200
|
||||
height: 290
|
||||
|
||||
MetroButton {
|
||||
id: choicetitle
|
||||
width: parent.width
|
||||
text: Backend.translate(modelData)
|
||||
textFont.pixelSize: 24
|
||||
anchors.top: choiceDetail.bottom
|
||||
anchors.topMargin: 8
|
||||
|
||||
onClicked: {
|
||||
result = index;
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: choiceDetail
|
||||
x: 4
|
||||
height: parent.height - choicetitle.height
|
||||
contentHeight: detail.height
|
||||
width: parent.width
|
||||
clip: true
|
||||
Text {
|
||||
id: detail
|
||||
width: parent.width
|
||||
text: Backend.translate(":" + modelData)
|
||||
color: "white"
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 16
|
||||
textFormat: TextEdit.RichText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ GraphicsBox {
|
|||
font.family: fontLibian.name
|
||||
font.pixelSize: 18
|
||||
style: Text.Outline
|
||||
wrapMode: Text.WrapAnywhere
|
||||
wrapMode: Text.WordWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ Item {
|
|||
lineHeightMode: Text.FixedHeight
|
||||
color: "white"
|
||||
width: 24
|
||||
wrapMode: Text.WordWrap
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: ""
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ Item {
|
|||
lineHeightMode: Text.FixedHeight
|
||||
color: "white"
|
||||
width: 24
|
||||
wrapMode: Text.WordWrap
|
||||
wrapMode: Text.WrapAnywhere
|
||||
text: Backend.translate(deputyGeneral)
|
||||
style: Text.Outline
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ Item {
|
|||
id: equipAreaItem
|
||||
|
||||
x: 31
|
||||
y: 139
|
||||
y: 157
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
|
@ -66,7 +66,7 @@ Item {
|
|||
c.selectable = true;
|
||||
c.height = c.height * 0.8;
|
||||
c.width = c.width * 0.8;
|
||||
c.rotation = (Math.random() - 0.5) * 5;
|
||||
// c.rotation = (Math.random() - 0.5) * 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ Item {
|
|||
c.selectable = false;
|
||||
c.height = c.height / 0.8;
|
||||
c.width = c.width / 0.8;
|
||||
c.rotation = 0;
|
||||
// c.rotation = 0;
|
||||
}
|
||||
const vanished = [];
|
||||
if (result.length < outputs.length) {
|
||||
|
|
|
@ -117,9 +117,11 @@ function Client:moveCards(moves)
|
|||
end
|
||||
|
||||
---@param msg LogMessage
|
||||
function Client:appendLog(msg)
|
||||
local function parseMsg(msg, nocolor)
|
||||
local self = ClientInstance
|
||||
local data = msg
|
||||
local function getPlayerStr(pid, color)
|
||||
if nocolor then color = "white" end
|
||||
if not pid then
|
||||
return ""
|
||||
end
|
||||
|
@ -177,7 +179,7 @@ function Client:appendLog(msg)
|
|||
local function parseArg(arg)
|
||||
arg = arg or ""
|
||||
arg = Fk:translate(arg)
|
||||
arg = string.format('<font color="#0598BC"><b>%s</b></font>', arg)
|
||||
arg = string.format('<font color="%s"><b>%s</b></font>', nocolor and "white" or "#0598BC", arg)
|
||||
return arg
|
||||
end
|
||||
|
||||
|
@ -192,7 +194,26 @@ function Client:appendLog(msg)
|
|||
log = string.gsub(log, "%%arg2", arg2)
|
||||
log = string.gsub(log, "%%arg3", arg3)
|
||||
log = string.gsub(log, "%%arg", arg)
|
||||
self:notifyUI("GameLog", log)
|
||||
return log
|
||||
end
|
||||
|
||||
---@param msg LogMessage
|
||||
function Client:appendLog(msg)
|
||||
self:notifyUI("GameLog", parseMsg(msg))
|
||||
end
|
||||
|
||||
---@param msg LogMessage
|
||||
function Client:setCardNote(ids, msg)
|
||||
for _, id in ipairs(ids) do
|
||||
if id ~= -1 then
|
||||
self:notifyUI("SetCardFootnote", json.encode{ id, parseMsg(msg, true) })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["SetCardFootnote"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
ClientInstance:setCardNote(data[1], data[2]);
|
||||
end
|
||||
|
||||
fk.client_callback["Setup"] = function(jsonData)
|
||||
|
@ -412,28 +433,33 @@ local function mergeMoves(moves)
|
|||
end
|
||||
|
||||
local function sendMoveCardLog(move)
|
||||
local client = ClientInstance
|
||||
if #move.ids == 0 then return end
|
||||
local hidden = table.contains(move.ids, -1)
|
||||
local msgtype
|
||||
|
||||
if move.from and move.toArea == Card.DrawPile then
|
||||
msgtype = hidden and "$PutCard" or "$PutKnownCard"
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = msgtype,
|
||||
from = move.from,
|
||||
card = move.ids,
|
||||
arg = #move.ids,
|
||||
}
|
||||
client:setCardNote(move.ids, {
|
||||
type = "$$PutCard",
|
||||
from = move.from,
|
||||
})
|
||||
elseif move.toArea == Card.PlayerSpecial then
|
||||
msgtype = hidden and "$RemoveCardFromGame" or "$AddToPile"
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = msgtype,
|
||||
arg = move.specialName,
|
||||
arg2 = #move.ids,
|
||||
card = move.ids,
|
||||
}
|
||||
elseif move.fromArea == Card.PlayerSpecial and move.to then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$GetCardsFromPile",
|
||||
from = move.to,
|
||||
arg = move.fromSpecialName,
|
||||
|
@ -441,7 +467,7 @@ local function sendMoveCardLog(move)
|
|||
card = move.ids,
|
||||
}
|
||||
elseif move.moveReason == fk.ReasonDraw then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$DrawCards",
|
||||
from = move.to,
|
||||
card = move.ids,
|
||||
|
@ -449,7 +475,7 @@ local function sendMoveCardLog(move)
|
|||
}
|
||||
elseif (move.fromArea == Card.DrawPile or move.fromArea == Card.DiscardPile)
|
||||
and move.moveReason == fk.ReasonPrey then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$PreyCardsFromPile",
|
||||
from = move.to,
|
||||
card = move.ids,
|
||||
|
@ -457,14 +483,14 @@ local function sendMoveCardLog(move)
|
|||
}
|
||||
elseif (move.fromArea == Card.Processing or move.fromArea == Card.PlayerJudge)
|
||||
and move.toArea == Card.PlayerHand then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$GotCardBack",
|
||||
from = move.to,
|
||||
card = move.ids,
|
||||
arg = #move.ids,
|
||||
}
|
||||
elseif move.fromArea == Card.DiscardPile and move.toArea == Card.PlayerHand then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$RecycleCard",
|
||||
from = move.to,
|
||||
card = move.ids,
|
||||
|
@ -472,7 +498,7 @@ local function sendMoveCardLog(move)
|
|||
}
|
||||
elseif move.from and move.fromArea ~= Card.PlayerJudge and
|
||||
move.toArea ~= Card.PlayerJudge and move.to and move.from ~= move.to then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$MoveCards",
|
||||
from = move.from,
|
||||
to = { move.to },
|
||||
|
@ -486,7 +512,7 @@ local function sendMoveCardLog(move)
|
|||
msgtype = "$PasteCard"
|
||||
end
|
||||
if msgtype then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = msgtype,
|
||||
from = move.from,
|
||||
to = { move.to },
|
||||
|
@ -497,12 +523,16 @@ local function sendMoveCardLog(move)
|
|||
|
||||
-- TODO ...
|
||||
if move.moveReason == fk.ReasonDiscard then
|
||||
ClientInstance:appendLog{
|
||||
client:appendLog{
|
||||
type = "$DiscardCards",
|
||||
from = move.from,
|
||||
card = move.ids,
|
||||
arg = #move.ids,
|
||||
}
|
||||
client:setCardNote(move.ids, {
|
||||
type = "$$DiscardCards",
|
||||
from = move.from
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -512,10 +542,10 @@ fk.client_callback["MoveCards"] = function(jsonData)
|
|||
local separated = separateMoves(raw_moves)
|
||||
ClientInstance:moveCards(separated)
|
||||
local merged = mergeMoves(separated)
|
||||
ClientInstance:notifyUI("MoveCards", json.encode(merged))
|
||||
for _, move in ipairs(merged) do
|
||||
sendMoveCardLog(move)
|
||||
end
|
||||
ClientInstance:notifyUI("MoveCards", json.encode(merged))
|
||||
end
|
||||
|
||||
fk.client_callback["ShowCard"] = function(jsonData)
|
||||
|
|
|
@ -130,6 +130,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["Quit"] = "退出",
|
||||
["BanGeneral"] = "禁将",
|
||||
["ResumeGeneral"] = "解禁",
|
||||
["Death audio"] = "阵亡",
|
||||
|
||||
["$WelcomeToLobby"] = "欢迎进入新月杀游戏大厅!",
|
||||
|
||||
|
@ -350,9 +351,22 @@ Fk:loadTranslationTable{
|
|||
["#EnterDying"] = "%from 进入了濒死阶段",
|
||||
["#KillPlayer"] = "%from [%arg] 阵亡,凶手是 %to",
|
||||
["#KillPlayerWithNoKiller"] = "%from [%arg] 阵亡,无伤害来源",
|
||||
["#Revive"] = "%from 竟然复活了",
|
||||
|
||||
-- misc
|
||||
["#GuanxingResult"] = "%from 的观星结果为 %arg 上 %arg2 下",
|
||||
["#ChainStateChange"] = "%from %arg 了武将牌",
|
||||
["#ChainDamage"] = "%from 处于连环状态,将受到传导的伤害",
|
||||
}
|
||||
|
||||
-- card footnote
|
||||
Fk:loadTranslationTable{
|
||||
["$$DiscardCards"] = "%from弃置",
|
||||
["$$PutCard"] = "%from置于",
|
||||
|
||||
["##UseCard"] = "%from使用",
|
||||
["##UseCardTo"] = "%from对%to",
|
||||
["##ResponsePlayCard"] = "%from打出",
|
||||
["##ShowCard"] = "%from展示",
|
||||
["##JudgeCard"] = "%arg判定",
|
||||
}
|
||||
|
|
|
@ -244,7 +244,14 @@ function Player:removeCards(playerArea, cardIds, specialName)
|
|||
break
|
||||
end
|
||||
|
||||
table.removeOne(fromAreaIds, id)
|
||||
if table.contains(fromAreaIds, id) then
|
||||
table.removeOne(fromAreaIds, id)
|
||||
-- FIXME: 为客户端移动id为-1的牌考虑,但总感觉有地方需要商讨啊!
|
||||
elseif table.every(fromAreaIds, function(e) return e == -1 end) then
|
||||
table.remove(fromAreaIds, 1)
|
||||
elseif id == -1 then
|
||||
table.remove(fromAreaIds, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,6 +21,10 @@ GameEvent.functions[GameEvent.Judge] = function(self)
|
|||
card = {data.card.id},
|
||||
}
|
||||
self:moveCardTo(data.card, Card.Processing, nil, fk.ReasonJudge)
|
||||
self:sendFootnote({ data.card.id }, {
|
||||
type = "##JudgeCard",
|
||||
arg = data.reason,
|
||||
})
|
||||
|
||||
self.logic:trigger(fk.AskForRetrial, who, data)
|
||||
self.logic:trigger(fk.FinishRetrial, who, data)
|
||||
|
@ -30,6 +34,10 @@ GameEvent.functions[GameEvent.Judge] = function(self)
|
|||
from = who.id,
|
||||
card = {data.card.id},
|
||||
}
|
||||
self:sendFootnote({ data.card.id }, {
|
||||
type = "##JudgeCard",
|
||||
arg = data.reason,
|
||||
})
|
||||
|
||||
if data.pattern then
|
||||
self:delay(400);
|
||||
|
|
|
@ -154,6 +154,27 @@ local sendCardEmotionAndLog = function(room, cardUseEvent)
|
|||
}
|
||||
end
|
||||
end
|
||||
|
||||
if #useCardIds == 0 then return end
|
||||
if cardUseEvent.tos and #cardUseEvent.tos > 0 and #cardUseEvent.tos <= 2 then
|
||||
local tos = table.map(cardUseEvent.tos, function(e) return e[1] end)
|
||||
room:sendFootnote(useCardIds, {
|
||||
type = "##UseCardTo",
|
||||
from = from,
|
||||
to = tos,
|
||||
})
|
||||
if card:isVirtual() then
|
||||
room:sendCardVirtName(useCardIds, card.name)
|
||||
end
|
||||
else
|
||||
room:sendFootnote(useCardIds, {
|
||||
type = "##UseCard",
|
||||
from = from,
|
||||
})
|
||||
if card:isVirtual() then
|
||||
room:sendCardVirtName(useCardIds, card.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param self GameEvent
|
||||
|
@ -250,6 +271,15 @@ GameEvent.functions[GameEvent.RespondCard] = function(self)
|
|||
toArea = Card.Processing,
|
||||
moveReason = fk.ReasonResonpse,
|
||||
})
|
||||
if #cardIds > 0 then
|
||||
self:sendFootnote(cardIds, {
|
||||
type = "##ResponsePlayCard",
|
||||
from = from,
|
||||
})
|
||||
if card:isVirtual() then
|
||||
self:sendCardVirtName(cardIds, card.name)
|
||||
end
|
||||
end
|
||||
|
||||
if self.logic:trigger(fk.PreCardRespond, self:getPlayerById(cardResponseEvent.from), cardResponseEvent) then
|
||||
self.logic:breakEvent()
|
||||
|
|
|
@ -419,6 +419,11 @@ function Room:removeCardMark(card, mark, count)
|
|||
self:setCardMark(card, mark, math.max(num - count, 0))
|
||||
end
|
||||
|
||||
---@param player ServerPlayer
|
||||
function Room:setPlayerProperty(player, property, value)
|
||||
player[property] = value
|
||||
self:broadcastProperty(player, property)
|
||||
end
|
||||
|
||||
--- 将房间中某个tag设为特定值。
|
||||
---
|
||||
|
@ -742,6 +747,14 @@ function Room:sendLog(log)
|
|||
self:doBroadcastNotify("GameLog", json.encode(log))
|
||||
end
|
||||
|
||||
function Room:sendFootnote(ids, log)
|
||||
self:doBroadcastNotify("SetCardFootnote", json.encode{ ids, log })
|
||||
end
|
||||
|
||||
function Room:sendCardVirtName(ids, name)
|
||||
self:doBroadcastNotify("SetCardVirtName", json.encode{ ids, name })
|
||||
end
|
||||
|
||||
--- 播放某种动画效果给players看。
|
||||
---@param type string @ 动画名字
|
||||
---@param data any @ 这个动画附加的额外信息,在这个函数将会被转成json字符串
|
||||
|
@ -868,7 +881,7 @@ end
|
|||
---@return boolean, table
|
||||
function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra_data)
|
||||
prompt = prompt or ""
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
extra_data = extra_data or {}
|
||||
local skill = Fk.skills[skill_name]
|
||||
if not (skill and (skill:isInstanceOf(ActiveSkill) or skill:isInstanceOf(ViewAsSkill))) then
|
||||
|
@ -929,7 +942,7 @@ Room.askForUseViewAsSkill = Room.askForUseActiveSkill
|
|||
---@param skipDiscard boolean @ 是否跳过弃牌(即只询问选择可以弃置的牌)
|
||||
---@return integer[] @ 弃掉的牌的id列表,可能是空的
|
||||
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt, skipDiscard)
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
pattern = pattern or ""
|
||||
|
||||
local canDiscards = table.filter(
|
||||
|
@ -1004,7 +1017,7 @@ function Room:askForChoosePlayers(player, targets, minNum, maxNum, prompt, skill
|
|||
if maxNum < 1 then
|
||||
return {}
|
||||
end
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
|
||||
local data = {
|
||||
targets = targets,
|
||||
|
@ -1042,7 +1055,7 @@ function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancel
|
|||
if minNum < 1 then
|
||||
return nil
|
||||
end
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
pattern = pattern or ""
|
||||
|
||||
local chosenCards = {}
|
||||
|
@ -1089,7 +1102,7 @@ function Room:askForChooseCardAndPlayers(player, targets, minNum, maxNum, patter
|
|||
if maxNum < 1 then
|
||||
return {}
|
||||
end
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
pattern = pattern or "."
|
||||
|
||||
local pcards = table.filter(player:getCardIds({ Player.Hand, Player.Equip }), function(id)
|
||||
|
@ -1224,15 +1237,15 @@ end
|
|||
---@param choices string[] @ 可选选项列表
|
||||
---@param skill_name string @ 技能名
|
||||
---@param prompt string @ 提示信息
|
||||
---@param data any @ 暂未使用
|
||||
---@param detailed boolean @ 暂未使用
|
||||
---@return string @ 选择的选项
|
||||
function Room:askForChoice(player, choices, skill_name, prompt, data)
|
||||
function Room:askForChoice(player, choices, skill_name, prompt, detailed)
|
||||
if #choices == 1 then return choices[1] end
|
||||
local command = "AskForChoice"
|
||||
prompt = prompt or ""
|
||||
self:notifyMoveFocus(player, skill_name)
|
||||
local result = self:doRequest(player, command, json.encode{
|
||||
choices, skill_name, prompt
|
||||
choices, skill_name, prompt, detailed
|
||||
})
|
||||
if result == "" then result = choices[1] end
|
||||
return result
|
||||
|
@ -1459,7 +1472,7 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
|
|||
|
||||
local command = "AskForUseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
extra_data = extra_data or {}
|
||||
pattern = pattern or card_name
|
||||
prompt = prompt or ""
|
||||
|
@ -1505,7 +1518,7 @@ function Room:askForResponse(player, card_name, pattern, prompt, cancelable, ext
|
|||
|
||||
local command = "AskForResponseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
extra_data = extra_data or {}
|
||||
pattern = pattern or card_name
|
||||
prompt = prompt or ""
|
||||
|
@ -1554,7 +1567,7 @@ function Room:askForNullification(players, card_name, pattern, prompt, cancelabl
|
|||
|
||||
local command = "AskForUseCard"
|
||||
card_name = card_name or "nullification"
|
||||
cancelable = cancelable or false
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
extra_data = extra_data or {}
|
||||
prompt = prompt or ""
|
||||
pattern = pattern or card_name
|
||||
|
@ -1750,7 +1763,7 @@ function Room:askForChooseToMoveCardInBoard(player, prompt, skillName, cancelabl
|
|||
if flag then
|
||||
assert(flag == "e" or flag == "j")
|
||||
end
|
||||
cancelable = (not cancelable) and false or true
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
|
||||
local data = {
|
||||
flag = flag,
|
||||
|
@ -2694,6 +2707,21 @@ function Room:useSkill(player, skill, effect_cb)
|
|||
end
|
||||
end
|
||||
|
||||
---@param player ServerPlayer
|
||||
---@param sendLog boolean|nil
|
||||
function Room:revivePlayer(player, sendLog)
|
||||
if not player.dead then return end
|
||||
self:setPlayerProperty(player, "dead", false)
|
||||
self:setPlayerProperty(player, "dying", false)
|
||||
self:setPlayerProperty(player, "hp", player.maxHp)
|
||||
table.insertIfNeed(self.alive_players, player)
|
||||
|
||||
sendLog = (sendLog == nil) and true or sendLog
|
||||
if sendLog then
|
||||
self:sendLog { type = "#Revive", from = player.id }
|
||||
end
|
||||
end
|
||||
|
||||
---@param room Room
|
||||
local function shouldUpdateWinRate(room)
|
||||
if room.settings.gameMode == "heg_mode" then return false end
|
||||
|
|
|
@ -351,6 +351,10 @@ function ServerPlayer:showCards(cards)
|
|||
from = self.id,
|
||||
cards = cards,
|
||||
})
|
||||
room:sendFootnote(cards, {
|
||||
type = "##ShowCard",
|
||||
from = self.id,
|
||||
})
|
||||
|
||||
room.logic:trigger(fk.CardShown, self, { cardIds = cards })
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user