enhance processPrompt (#355)

1. 改进processPrompt,支持双将和暗将
2. 副将长名旋转
3. 国战体力上限优化,包括一览和选将框
4. 空格添加结束出牌阶段,Escape键呼出菜单
5. 武将一览左栏文本换行
6. 同名替换影响已选择的武将
7. 再次排序手牌时按照点数排序
8. Logic.js翻译
9. 进入房间翻译删去句号,跟房间内其他toast风格统一
10. 常见疑问最后一张“下一条”改为“OK!”
11. 录像回放“从文件打开”翻译
12. interaction自动弹出和关闭,comboBox补技能名
13. 卡牌音效添加装备效果音效和使用音效,小小重构
14. activeSkill的prompt的selected_targets实装
15. 禁用扩展包文本ui限制长度
16. 右键技能呼出气泡
Qsgs-Fans/freekill-core#3
This commit is contained in:
Nyutanislavsky 2024-06-10 14:58:48 +08:00 committed by GitHub
parent ebc5675ead
commit 4235bf6237
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 272 additions and 43 deletions

View File

@ -40,8 +40,13 @@ Flickable {
extra_data.generals.forEach((g) => { extra_data.generals.forEach((g) => {
const data = lcall("GetGeneralDetail", g); const data = lcall("GetGeneralDetail", g);
skillDesc.append(luatr(data.kingdom) + " " + luatr(g) + " " + data.hp + skillDesc.append(luatr(data.kingdom) + " " + luatr(g) + " " + (data.hp === data.maxHp
"/" + data.maxHp); ? ((g.startsWith('hs__') || g.startsWith('ld__') || g.includes('heg__'))
? ((data.mainMaxHp != 0 || data.deputyMaxHp != 0)
? ((data.hp + data.mainMaxHp) / 2 + '/' + (data.hp + data.deputyMaxHp) / 2)
: data.hp / 2)
: data.hp)
: data.hp + "/" + data.maxHp));
if (data.companions.length > 0){ if (data.companions.length > 0){
let ret = ''; let ret = '';
ret +="<font color=\"slategrey\"><b>" + luatr("Companions") + "</b>: "; ret +="<font color=\"slategrey\"><b>" + luatr("Companions") + "</b>: ";

View File

@ -50,6 +50,16 @@ Item {
if (idx < extra_data.cards.count) { if (idx < extra_data.cards.count) {
extra_data.cards.set(idx, { name: modelData }); extra_data.cards.set(idx, { name: modelData });
} }
idx = 0;
extra_data.choices.forEach( s => {
if (s === gname) {
extra_data.choices[idx] = modelData;
return;
}
idx++;
});
root.finish(); root.finish();
} }
} }

View File

@ -184,6 +184,12 @@ Item {
return ret; return ret;
} }
delegate: Text { delegate: Text {
width: parent.width / 2
wrapMode: Text.WordWrap
fontSizeMode: Text.HorizontalFit
minimumPixelSize: 14
elide: Text.ElideRight
height: 24
text: luatr(modelData) text: luatr(modelData)
font.pixelSize: 16 font.pixelSize: 16
} }

View File

@ -289,18 +289,29 @@ Item {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: { text: {
if (gender === "male") { if (audioType === "male") {
return luatr("Male Audio"); return luatr("Male Audio");
} else { } else if (audioType === "female") {
return luatr("Female Audio"); return luatr("Female Audio");
} else if (audioType === "equip_effect") {
return luatr("Equip Effect Audio");
} {
return luatr("Equip Use Audio");
} }
} }
font.pixelSize: 14 font.pixelSize: 14
} }
onClicked: { onClicked: {
const data = lcall("GetCardData", cardDetail.cid); const data = lcall("GetCardData", cardDetail.cid);
if (audioType === "male" || audioType === "female") {
Backend.playSound("./packages/" + extension + "/audio/card/" Backend.playSound("./packages/" + extension + "/audio/card/"
+ gender + "/" + data.name); + audioType + "/" + data.name);
} else if (audioType === "equip_effect") {
Backend.playSound("./packages/" + extension + "/audio/card/"
+ "/" + data.name);
} else {
Backend.playSound("./audio/card/common/" + extension);
}
} }
} }
} }
@ -317,27 +328,41 @@ Item {
} }
} }
function loadAudio(cardName, type, extension, orig_extension) {
const prefix = AppPath + "/packages/";
const suffix = cardName + ".mp3";
let midfix = type + "/";
if (type === "equip_effect") {
midfix = "";
}
let fname = prefix + extension + "/audio/card/" + midfix + suffix;
if (Backend.exists(fname)) {
audioRow.append( { audioType: type, extension: extension } );
} else {
fname = prefix + orig_extension + "/audio/card/" + midfix + suffix;
if (Backend.exists(fname)) {
audioRow.append( { audioType: type, extension: orig_extension} );
}
}
}
function addCardAudio(card) { function addCardAudio(card) {
const extension = card.extension; const extension = card.extension;
const orig_extension = lcall("GetCardExtensionByName", card.name); const orig_extension = lcall("GetCardExtensionByName", card.name);
const prefix = AppPath + "/packages/"; loadAudio(card.name, "male", extension, orig_extension);
const suffix = card.name + ".mp3"; loadAudio(card.name, "female", extension, orig_extension);
let fname = prefix + extension + "/audio/card/male/" + suffix; if (audioRow.count === 0 && card.type === 3) {
if (Backend.exists(fname)) { loadAudio(card.name, "equip_effect", extension, orig_extension);
audioRow.append( { gender: "male", extension: extension } ); if (audioRow.count === 0) {
let subType = "";
if (card.subtype === "defensive_horse" || card.subtype === "offensive_horse") {
subType = "horse";
} else if (card.subtype === "weapon") {
subType = "weapon";
} else { } else {
fname = prefix + orig_extension + "/audio/card/male/" + suffix; subType = "armor";
if (Backend.exists(fname)) {
audioRow.append( {gender: "male", extension: orig_extension} );
} }
} audioRow.append( { audioType: "equip_use", extension: subType } );
fname = prefix + extension + "/audio/card/female/" + suffix;
if (Backend.exists(fname)) {
audioRow.append( { gender: "female", extension: extension } );
}else {
fname = prefix + orig_extension + "/audio/card/female/" + suffix;
if (Backend.exists(fname)) {
audioRow.append( { gender: "female", extension: orig_extension } );
} }
} }
} }

View File

@ -503,6 +503,8 @@ Item {
Item { Item {
id: generalInfo id: generalInfo
x: 5
y: 10
width: 150 width: 150
ColumnLayout { ColumnLayout {
width: parent.width width: parent.width
@ -516,6 +518,7 @@ Item {
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WordWrap
textFormat: TextEdit.RichText textFormat: TextEdit.RichText
font.pixelSize: 16 font.pixelSize: 16
function trans(str) { function trans(str) {

View File

@ -3,13 +3,13 @@
callbacks["UpdateAvatar"] = (jsonData) => { callbacks["UpdateAvatar"] = (jsonData) => {
mainWindow.busy = false; mainWindow.busy = false;
Self.avatar = jsonData; Self.avatar = jsonData;
toast.show("Update avatar done."); toast.show(luatr("Update avatar done."));
} }
callbacks["UpdatePassword"] = (jsonData) => { callbacks["UpdatePassword"] = (jsonData) => {
mainWindow.busy = false; mainWindow.busy = false;
if (jsonData === "1") if (jsonData === "1")
toast.show("Update password done."); toast.show(luatr("Update password done."));
else else
toast.show("Old password wrong!", 5000); toast.show(luatr("Old password wrong!"), 5000);
} }

View File

@ -32,7 +32,7 @@ Item {
id: menu id: menu
y: bar.height y: bar.height
MenuItem { MenuItem {
text: qsTr("Replay from file") text: luatr("Replay from File")
onTriggered: { onTriggered: {
fdialog.open(); fdialog.open();
} }

View File

@ -810,7 +810,7 @@ Item {
skillInteraction.item.choices = data.choices; skillInteraction.item.choices = data.choices;
skillInteraction.item.detailed = data.detailed; skillInteraction.item.detailed = data.detailed;
skillInteraction.item.all_choices = data.all_choices; skillInteraction.item.all_choices = data.all_choices;
// skillInteraction.item.clicked(); skillInteraction.item.clicked();
break; break;
case "spin": case "spin":
skillInteraction.sourceComponent = skillInteraction.sourceComponent =
@ -818,12 +818,14 @@ Item {
skillInteraction.item.skill = skill_name; skillInteraction.item.skill = skill_name;
skillInteraction.item.from = data.from; skillInteraction.item.from = data.from;
skillInteraction.item.to = data.to; skillInteraction.item.to = data.to;
skillInteraction.item.clicked();
break; break;
case "custom": case "custom":
skillInteraction.sourceComponent = skillInteraction.sourceComponent =
Qt.createComponent(AppPath + "/" + data.qml_path + ".qml"); Qt.createComponent(AppPath + "/" + data.qml_path + ".qml");
skillInteraction.item.skill = skill_name; skillInteraction.item.skill = skill_name;
skillInteraction.item.extra_data = data; skillInteraction.item.extra_data = data;
skillInteraction.item.clicked();
break; break;
default: default:
skillInteraction.sourceComponent = undefined; skillInteraction.sourceComponent = undefined;
@ -837,6 +839,8 @@ Item {
cancelButton.enabled = true; cancelButton.enabled = true;
} else { } else {
skillInteraction.sourceComponent = undefined; skillInteraction.sourceComponent = undefined;
if (roomScene.popupBox.item)
roomScene.popupBox.item.close();
Logic.doCancelButton(); Logic.doCancelButton();
} }
} }
@ -1060,8 +1064,17 @@ Item {
Shortcut { Shortcut {
sequence: "Space" sequence: "Space"
enabled: cancelButton.enabled enabled: cancelButton.enabled || endPhaseButton.visible;
onActivated: Logic.doCancelButton(); onActivated: if (cancelButton.enabled) {
Logic.doCancelButton();
} else {
Logic.replyToServer("");
}
}
Shortcut {
sequence: "Escape"
onActivated: menuContainer.open();
} }
function getCurrentCardUseMethod() { function getCurrentCardUseMethod() {

View File

@ -314,6 +314,10 @@ function resortHandcards() {
["treasure"]: Card.SubtypeTreasure, ["treasure"]: Card.SubtypeTreasure,
} }
const hand = dashboard.handcardArea.cards.map(c => {
return c.cid;
})
dashboard.handcardArea.cards.sort((prev, next) => { dashboard.handcardArea.cards.sort((prev, next) => {
if (prev.footnote === next.footnote) { if (prev.footnote === next.footnote) {
if (prev.type === next.type) { if (prev.type === next.type) {
@ -341,6 +345,34 @@ function resortHandcards() {
} }
}); });
let i = 0;
let resort = true;
dashboard.handcardArea.cards.forEach(c => {
if (hand[i] !== c.cid) {
resort = false;
return;
}
i++;
})
if (resort) {
dashboard.handcardArea.cards.sort((prev, next) => {
if (prev.footnote === next.footnote) {
if (prev.number === next.number) { // 按点数排
if (prev.suit === next.suit) {
return prev.cid - next.cid;
} else {
return prev.suit - next.suit;
}
} else {
return prev.number - next.number;
}
} else {
return prev.footnote > next.footnote ? 1 : -1;
}
});
}
dashboard.handcardArea.updateCardPosition(true); dashboard.handcardArea.updateCardPosition(true);
} }
@ -488,15 +520,29 @@ function doIndicate(from, tos) {
line.running = true; line.running = true;
} }
function getPlayerStr(playerid) {
const photo = getPhoto(playerid);
if (photo.general === "anjiang" && (photo.deputyGeneral === "anjiang" || !p.deputyGeneral)) {
return luatr("seat#" + photo.seatNumber);
}
let ret = photo.general;
ret = luatr(ret);
if (photo.deputyGeneral && photo.deputyGeneral !== "") {
ret = ret + "/" + luatr(photo.deputyGeneral);
}
return ret;
}
function processPrompt(prompt) { function processPrompt(prompt) {
const data = prompt.split(":"); const data = prompt.split(":");
let raw = luatr(data[0]); let raw = luatr(data[0]);
const src = parseInt(data[1]); const src = parseInt(data[1]);
const dest = parseInt(data[2]); const dest = parseInt(data[2]);
if (raw.match("%src")) if (raw.match("%src"))
raw = raw.replace(/%src/g, luatr(getPhoto(src).general)); raw = raw.replace(/%src/g, getPlayerStr(src));
if (raw.match("%dest")) if (raw.match("%dest"))
raw = raw.replace(/%dest/g, luatr(getPhoto(dest).general)); raw = raw.replace(/%dest/g, getPlayerStr(dest));
if (raw.match("%arg2")) if (raw.match("%arg2"))
raw = raw.replace(/%arg2/g, luatr(data[4])); raw = raw.replace(/%arg2/g, luatr(data[4]));
if (raw.match("%arg")) if (raw.match("%arg"))
@ -672,6 +718,15 @@ function updateSelectedTargets(playerid, selected) {
} }
if (candidate) { if (candidate) {
roomScene.resetPrompt(); // update prompt due to selected_targets
const prompt = lcall("ActiveSkillPrompt",
dashboard.pending_skill !== "" ? dashboard.pending_skill: lcall("GetCardSkill", card),
dashboard.pending_skill !== "" ? dashboard.pendings : [card],
selected_targets);
if (prompt !== "") {
roomScene.setPrompt(Util.processPrompt(prompt));
}
all_photos.forEach(photo => { all_photos.forEach(photo => {
if (photo.selected) return; if (photo.selected) return;
const id = photo.playerid; const id = photo.playerid;

View File

@ -112,7 +112,7 @@ GraphicsBox {
visible: !convertDisabled visible: !convertDisabled
text: luatr("Same General Convert") text: luatr("Same General Convert")
onClicked: { onClicked: {
roomScene.startCheat("SameConvert", { cards: generalList }); roomScene.startCheat("SameConvert", { cards: generalList, choices: choices });
} }
} }
@ -263,6 +263,7 @@ GraphicsBox {
item.selectable = hegemony ? isHegPair(selectedItem[0], item) item.selectable = hegemony ? isHegPair(selectedItem[0], item)
: true; : true;
if (hegemony) { if (hegemony) {
item.inPosition = 0;
if (selectedItem[0]) { if (selectedItem[0]) {
if (selectedItem[1]) { if (selectedItem[1]) {
if (selectedItem[0] === item) { if (selectedItem[0] === item) {
@ -299,6 +300,23 @@ GraphicsBox {
} }
} }
if (hegemony) {
if (selectedItem[0]) {
if (selectedItem[0].mainMaxHp < 0) {
selectedItem[0].inPosition = 1;
} else if (selectedItem[0].deputyMaxHp < 0) {
selectedItem[0].inPosition = -1;
}
if (selectedItem[1]) {
if (selectedItem[1].mainMaxHp < 0) {
selectedItem[1].inPosition = -1;
} else if (selectedItem[1].deputyMaxHp < 0) {
selectedItem[1].inPosition = 1;
}
}
}
}
for (let i = 0; i < generalList.count; i++) { for (let i = 0; i < generalList.count; i++) {
if (lcall("GetSameGenerals", generalList.get(i).name).length > 0) { if (lcall("GetSameGenerals", generalList.get(i).name).length > 0) {
convertBtn.enabled = true; convertBtn.enabled = true;

View File

@ -22,6 +22,9 @@ CardItem {
property int hp property int hp
property int maxHp property int maxHp
property int shieldNum property int shieldNum
property int mainMaxHp
property int deputyMaxHp
property int inPosition: 0
property string pkgName: "" property string pkgName: ""
property bool detailed: true property bool detailed: true
property alias hasCompanions: companions.visible property alias hasCompanions: companions.visible
@ -119,12 +122,15 @@ CardItem {
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height
Image { Image {
opacity: ((mainMaxHp < 0 || deputyMaxHp < 0) && (index * 2 + 1 === hp) && inPosition !== -1)
? (inPosition === 0 ? 0.5 : 0) :1
height: 12; fillMode: Image.PreserveAspectFit height: 12; fillMode: Image.PreserveAspectFit
source: SkinBank.getGeneralCardDir(kingdom) + kingdom + "-magatama-l" source: SkinBank.getGeneralCardDir(kingdom) + kingdom + "-magatama-l"
} }
Image { Image {
x: 4.4 x: 4.4
opacity: (index + 1) * 2 <= hp ? 1 : 0 opacity: (index + 1) * 2 <= hp ? (((mainMaxHp < 0 || deputyMaxHp < 0) && inPosition !== -1 && ((index + 1) * 2 === hp))
? (inPosition === 0 ? 0.5 : 0) : 1) : 0
height: 12; fillMode: Image.PreserveAspectFit height: 12; fillMode: Image.PreserveAspectFit
source: { source: {
const k = subkingdom ? subkingdom : kingdom; const k = subkingdom ? subkingdom : kingdom;
@ -227,6 +233,8 @@ CardItem {
hp = data.hp; hp = data.hp;
maxHp = data.maxHp; maxHp = data.maxHp;
shieldNum = data.shield; shieldNum = data.shield;
mainMaxHp = data.mainMaxHpAdjustedValue;
deputyMaxHp = data.deputyMaxHpAdjustedValue;
const splited = name.split("__"); const splited = name.split("__");
if (splited.length > 1) { if (splited.length > 1) {

View File

@ -234,7 +234,26 @@ Item {
color: "white" color: "white"
width: 24 width: 24
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
text: luatr(deputyGeneral) text: ""
style: Text.Outline
}
Text {
id: longDeputyGeneralName
anchors.left: generalImage.right
anchors.leftMargin: -14
y: 23
font.family: fontLibian.name
font.pixelSize: 22
rotation: 90
transformOrigin: Item.BottomLeft
opacity: 0.9
horizontalAlignment: Text.AlignHCenter
lineHeight: 18
lineHeightMode: Text.FixedHeight
color: "white"
width: 24
text: ""
style: Text.Outline style: Text.Outline
} }
} }
@ -740,6 +759,18 @@ Item {
} }
} }
onDeputyGeneralChanged: {
if (!roomScene.isStarted) return;
const text = luatr(deputyGeneral);
if (text.length > 6) {
deputyGeneralName.text = "";
longDeputyGeneralName.text = text;
} else {
deputyGeneralName.text = text;
longDeputyGeneralName.text = "";
}
}
function chat(msg) { function chat(msg) {
chat.text = msg; chat.text = msg;
chat.visible = true; chat.visible = true;

View File

@ -2,6 +2,7 @@
import QtQuick import QtQuick
import Qt5Compat.GraphicalEffects import Qt5Compat.GraphicalEffects
import QtQuick.Controls
Item { Item {
id: root id: root
@ -86,7 +87,40 @@ Item {
} }
TapHandler { TapHandler {
enabled: root.type !== "notactive" && root.enabled acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.NoButton
onTapped: parent.pressed = !parent.pressed; onTapped: (p, btn) => {
if ((btn === Qt.LeftButton || btn === Qt.NoButton) && root.type !== "notactive" && root.enabled) {
parent.pressed = !parent.pressed;
} else if (btn === Qt.RightButton) {
skillDetail.open();
}
}
}
Popup {
id: skillDetail
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
property string text: ""
width: Math.min(contentWidth, realMainWin.width * 0.4)
height: Math.min(contentHeight + 24, realMainWin.height * 0.9)
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
padding: 12
background: Rectangle {
color: "#EEEEEEEE"
radius: 5
border.color: "#A6967A"
border.width: 1
}
contentItem: Text {
text: "<b>" + luatr(orig) + "</b>: " + luatr(":" + orig)
font.pixelSize: 20
wrapMode: Text.WordWrap
textFormat: TextEdit.RichText
TapHandler {
onTapped: skillDetail.close();
}
}
} }
} }

View File

@ -32,6 +32,7 @@ MetroButton {
const box = roomScene.popupBox.item; const box = roomScene.popupBox.item;
box.options = choices; box.options = choices;
box.all_options = all_choices; box.all_options = all_choices;
box.skill_name = skill;
box.accepted.connect(() => { box.accepted.connect(() => {
answer = all_choices[box.result]; answer = all_choices[box.result];
}); });

View File

@ -64,9 +64,15 @@ Rectangle {
} }
Button { Button {
text: qsTr("Next") text: view.currentIndex + 1 == total ? qsTr("OK!") : qsTr("Next")
enabled: view.currentIndex + 1 < total enabled: view.currentIndex + 1 <= total
onClicked: view.currentIndex++ onClicked: {
if (view.currentIndex + 1 == total) {
mainStack.pop();
} else {
view.currentIndex++
}
}
} }
} }
} }

View File

@ -12,15 +12,29 @@ function convertNumber(number) {
return ""; return "";
} }
function getPlayerStr(playerid) {
const photo = getPhoto(playerid);
if (photo.general === "anjiang" && (photo.deputyGeneral === "anjiang" || !p.deputyGeneral)) {
return luatr("seat#" + photo.seatNumber);
}
let ret = photo.general;
ret = luatr(ret);
if (photo.deputyGeneral && photo.deputyGeneral !== "") {
ret = ret + "/" + luatr(photo.deputyGeneral);
}
return ret;
}
function processPrompt(prompt) { function processPrompt(prompt) {
const data = prompt.split(":"); const data = prompt.split(":");
let raw = luatr(data[0]); let raw = luatr(data[0]);
const src = parseInt(data[1]); const src = parseInt(data[1]);
const dest = parseInt(data[2]); const dest = parseInt(data[2]);
if (raw.match("%src")) if (raw.match("%src"))
raw = raw.replace(/%src/g, luatr(getPhoto(src).general)); raw = raw.replace(/%src/g, getPlayerStr(src));
if (raw.match("%dest")) if (raw.match("%dest"))
raw = raw.replace(/%dest/g, luatr(getPhoto(dest).general)); raw = raw.replace(/%dest/g, getPlayerStr(dest));
if (raw.match("%arg2")) if (raw.match("%arg2"))
raw = raw.replace(/%arg2/g, luatr(data[4])); raw = raw.replace(/%arg2/g, luatr(data[4]));
if (raw.match("%arg")) if (raw.match("%arg"))