Overview UI (#130)

优化了卡牌一览/武将一览的UI
This commit is contained in:
notify 2023-04-21 17:49:30 +08:00 committed by GitHub
parent f488cc4b69
commit ab4cfba7a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 467 additions and 88 deletions

View File

@ -35,6 +35,8 @@ Fk:loadTranslationTable{
["Generals Overview"] = "武将一览",
["Cards Overview"] = "卡牌一览",
["Special card skills:"] = "<b>卡牌的特殊用法:</b>",
["Every suit & number:"] = "<b>所有的花色和点数:</b>",
["Scenarios Overview"] = "玩法一览",
["Replay"] = "录像",
["About"] = "关于",

View File

@ -483,19 +483,32 @@ Fk:loadTranslationTable{
["maneuvering"] = "军争",
["thunder__slash"] = "雷杀",
[":thunder__slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名角色<br /><b>效果</b>对目标角色造成1点雷电伤害。",
["fire__slash"] = "火杀",
[":fire__slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名角色<br /><b>效果</b>对目标角色造成1点火焰伤害。",
["analeptic"] = "",
[":analeptic"] = "基本牌<br /><b>时机</b>:出牌阶段/你处于濒死状态时<br /><b>目标</b>:你<br /><b>效果</b>:目标角色本回合使用的下一张【杀】将要造成的伤害+1/目标角色回复1点体力。",
["iron_chain"] = "铁锁连环",
[":iron_chain"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一至两名角色<br /><b>效果</b>:横置或重置目标角色的武将牌。",
["_normal_use"] = "正常使用",
["recast"] = "重铸",
[":recast"] = "你可以将此牌置入弃牌堆,然后摸一张牌。",
["fire_attack"] = "火攻",
["fire_attack_skill"] = "火攻",
[":fire_attack"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名有手牌的角色<br /><b>效果</b>目标角色展示一张手牌然后你可以弃置一张与所展示牌花色相同的手牌令其受到1点火焰伤害。",
["supply_shortage"] = "兵粮寸断",
[":supply_shortage"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>距离1的一名其他角色<br /><b>效果</b>:将此牌置于目标角色判定区内。其判定阶段进行判定:若结果不为梅花,其跳过摸牌阶段。然后将【兵粮寸断】置入弃牌堆。",
["guding_blade"] = "古锭刀",
[":guding_blade"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技。每当你使用【杀】对目标角色造成伤害时,若该角色没有手牌,此伤害+1。",
["fan"] = "朱雀羽扇",
[":fan"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:你可以将一张普通【杀】当火【杀】使用。",
["#fan_skill"] = "朱雀羽扇",
["vine"] = "藤甲",
[":vine"] = "装备牌·防具<br /><b>防具技能</b>:锁定技。【南蛮入侵】、【万箭齐发】和普通【杀】对你无效。每当你受到火焰伤害时,此伤害+1。",
["silver_lion"] = "白银狮子",
[":silver_lion"] = "装备牌·防具<br /><b>防具技能</b>锁定技。每当你受到伤害时若此伤害大于1点防止多余的伤害。每当你失去装备区里的【白银狮子】后你回复1点体力。",
["hualiu"] = "骅骝",
[":hualiu"] = "装备牌·坐骑<br /><b>坐骑技能</b>:其他角色与你的距离+1。",
}
return extension

View File

@ -16,78 +16,111 @@ Fk:loadTranslationTable{
["diamond"] = "方块",
["slash"] = "",
[":slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名其他角色<br /><b>效果</b>对目标角色造成1点伤害。",
["#slash-jink"] = "%src 对你使用了杀,请使用 %arg 张闪",
["jink"] = "",
[":jink"] = "基本牌<br /><b>时机</b>:【杀】对你生效时<br /><b>目标</b>:此【杀】<br /><b>效果</b>:抵消此【杀】的效果。",
["peach"] = "",
[":peach"] = "基本牌<br /><b>时机</b>:出牌阶段/一名角色处于濒死状态时<br /><b>目标</b>:已受伤的你/处于濒死状态的角色<br /><b>效果</b>目标角色回复1点体力。",
["dismantlement"] = "过河拆桥",
[":dismantlement"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名区域内有牌的其他角色。<br /><b>效果</b>:你弃置目标角色区域内的一张牌。",
["dismantlement_skill"] = "过河拆桥",
["snatch"] = "顺手牵羊",
[":snatch"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>距离1的一名区域内有牌的角色<br /><b>效果</b>:你获得目标角色区域内的一张牌。",
["snatch_skill"] = "顺手牵羊",
["duel"] = "决斗",
[":duel"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名其他角色<br /><b>效果</b>由目标角色开始你与其轮流打出一张【杀】否则受到对方的1点伤害并结束此牌结算。",
["collateral"] = "借刀杀人",
[":collateral"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>装备区内有武器牌且攻击范围内有【杀】的合法目标的一名其他角色A你需要选择一名A攻击范围内的【杀】的合法目标B<br /><b>效果</b>A须对B使用一张【杀】否则你获得A装备区内的武器牌。",
["ex_nihilo"] = "无中生有",
[":ex_nihilo"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:你<br /><b>效果</b>:目标角色摸两张牌。",
["nullification"] = "无懈可击",
[":nullification"] = "锦囊牌<br /><b>时机</b>:锦囊牌对目标角色生效前,或一张【无懈可击】生效前<br /><b>目标</b>:该锦囊牌<br /><b>效果</b>:抵消该锦囊牌对该角色产生的效果,或抵消另一张【无懈可击】产生的效果。",
["savage_assault"] = "南蛮入侵",
[":savage_assault"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有其他角色<br /><b>效果</b>每名目标角色须打出一张【杀】否则受到1点伤害。",
["archery_attack"] = "万箭齐发",
[":archery_attack"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有其他角色<br /><b>效果</b>每名目标角色须打出一张【闪】否则受到1点伤害。",
["god_salvation"] = "桃园结义",
[":god_salvation"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有角色<br /><b>效果</b>每名目标角色回复1点体力。",
["amazing_grace"] = "五谷丰登",
[":amazing_grace"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有角色<br /><b>效果</b>:你亮出牌堆顶等于角色数的牌,每名目标角色获得其中一张牌,然后将其余的牌置入弃牌堆。",
["amazing_grace_skill"] = "五谷选牌",
["lightning"] = "闪电",
[":lightning"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:你<br /><b>效果</b>将此牌置于目标角色判定区内。其判定阶段进行判定若结果为黑桃2-9其受到3点雷电伤害并将【闪电】置入弃牌堆否则将【闪电】移动至其下家判定区内。",
["indulgence"] = "乐不思蜀",
[":indulgence"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名其他角色<br /><b>效果</b>:将此牌置于目标角色判定区内。其判定阶段进行判定:若结果不为红桃,其跳过出牌阶段。然后将【乐不思蜀】置入弃牌堆。",
["crossbow"] = "诸葛连弩",
[":crossbow"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技。你于出牌阶段内使用【杀】无次数限制。",
["qinggang_sword"] = "青釭剑",
[":qinggang_sword"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技。你的【杀】无视目标角色的防具。",
["ice_sword"] = "寒冰剑",
[":ice_sword"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:每当你使用【杀】对目标角色造成伤害时,若该角色有牌,你可以防止此伤害,然后依次弃置其两张牌。",
["#ice_sword_skill"] = "寒冰剑",
["double_swords"] = "雌雄双股剑",
[":double_swords"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:每当你指定异性角色为【杀】的目标后,你可以令其选择一项:弃置一张手牌,或令你摸一张牌。",
["#double_swords_skill"] = "雌雄双股剑",
["blade"] = "青龙偃月刀",
[":blade"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:每当你使用的【杀】被【闪】抵消后,你可以对该角色再使用一张【杀】(无距离限制且不能选择额外目标)。",
["#blade_skill"] = "青龙偃月刀",
["#blade_slash"] = "你可以发动“青龙偃月刀”对 %src 再使用一张杀",
["spear"] = "丈八蛇矛",
[":spear"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:你可以将两张手牌当【杀】使用或打出。",
["spear_skill"] = "丈八矛",
[":spear_skill"] = "你可以将两张手牌当【杀】使用或打出。",
["axe"] = "贯石斧",
[":axe"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:每当你使用的【杀】被【闪】抵消后,你可以弃置两张牌,则此【杀】继续造成伤害。",
["#axe_skill"] = "贯石斧",
["halberd"] = "方天画戟",
[":halberd"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技。你使用最后的手牌【杀】可以额外选择至多两名目标。",
["kylin_bow"] = "麒麟弓",
[":kylin_bow"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:每当你使用【杀】对目标角色造成伤害时,你可以弃置其装备区内的一张坐骑牌。",
["#kylin_bow_skill"] = "麒麟弓",
["eight_diagram"] = "八卦阵",
[":eight_diagram"] = "装备牌·防具<br /><b>防具技能</b>:每当你需要使用或打出一张【闪】时,你可以进行判定:若结果为红色,视为你使用或打出了一张【闪】。",
["#eight_diagram_skill"] = "八卦阵",
["nioh_shield"] = "仁王盾",
[":nioh_shield"] = "装备牌·防具<br /><b>防具技能</b>:锁定技。黑色【杀】对你无效。",
["dilu"] = "的卢",
[":dilu"] = "装备牌·坐骑<br /><b>坐骑技能</b>:其他角色与你的距离+1。",
["jueying"] = "绝影",
[":jueying"] = "装备牌·坐骑<br /><b>坐骑技能</b>:其他角色与你的距离+1。",
["zhuahuangfeidian"] = "爪黄飞电",
[":zhuahuangfeidian"] = "装备牌·坐骑<br /><b>坐骑技能</b>:其他角色与你的距离+1。",
["chitu"] = "赤兔",
[":chitu"] = "装备牌·坐骑<br /><b>坐骑技能</b>:你与其他角色的距离-1。",
["dayuan"] = "大宛",
[":dayuan"] = "装备牌·坐骑<br /><b>坐骑技能</b>:你与其他角色的距离-1。",
["zixing"] = "紫骍",
[":zixing"] = "装备牌·坐骑<br /><b>坐骑技能</b>:你与其他角色的距离-1。",
}

View File

@ -10,29 +10,281 @@ Item {
property bool loaded: false
Rectangle {
anchors.fill: listView
color: "#88EEEEEE"
radius: 6
}
ListView {
width: Math.floor(root.width / 98) * 98
height: parent.height
anchors.centerIn: parent
id: listView
width: 130
height: parent.height - 20
y: 10
ScrollBar.vertical: ScrollBar {}
model: ListModel {
id: packages
}
delegate: ColumnLayout {
Text { text: Backend.translate(name) }
GridLayout {
columns: root.width / 98
Repeater {
model: JSON.parse(Backend.callLuaFunction("GetCards", [name]))
CardItem {
autoBack: false
Component.onCompleted: {
let data = JSON.parse(Backend.callLuaFunction("GetCardData", [modelData]));
setData(data);
}
highlight: Rectangle { color: "#E91E63"; radius: 5 }
highlightMoveDuration: 500
delegate: Item {
width: listView.width
height: 40
Text {
text: Backend.translate(name)
anchors.centerIn: parent
}
TapHandler {
onTapped: {
listView.currentIndex = index;
}
}
}
onCurrentIndexChanged: { vanishAnim.start(); }
}
GridView {
id: gridView
width: root.width - listView.width - cardDetail.width - 16
height: parent.height - 20
y: 10
anchors.left: listView.right
anchors.leftMargin: 8 + (width % 100) / 2
cellHeight: 140
cellWidth: 100
delegate: CardItem {
autoBack: false
property int dupCount: 0
Text {
anchors.right: parent.right
anchors.bottom: parent.bottom
text: parent.dupCount ? ("x" + parent.dupCount.toString()) : ""
font.pixelSize: 36
color: "white"
style: Text.Outline
}
Component.onCompleted: {
let data = modelData;
if (!data.cards) {
name = data.name;
suit = data.suit;
number = data.number;
cid = data.cid;
} else {
name = data.name;
cid = data.cid;
suit = "";
number = 0;
color = "";
dupCount = data.cards.length;
}
}
onClicked: {
cardDetail.cid = modelData.cid;
cardDetail.cards = modelData.cards;
cardDetail.updateCard();
}
}
}
ParallelAnimation {
id: vanishAnim
PropertyAnimation {
target: gridView
property: "opacity"
to: 0
duration: 150
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: gridView
property: "y"
to: 30
duration: 150
easing.type: Easing.InOutQuad
}
onFinished: {
let pkg = [listView.model.get(listView.currentIndex).name];
let idList = JSON.parse(Backend.callLuaFunction("GetCards", pkg));
let cardList = idList.map(id => JSON.parse(Backend.callLuaFunction
("GetCardData",[id])));
let groupedCardList = [];
let groupedCards = {};
cardList.forEach(c => {
let name = c.name;
if (!groupedCards[name]) {
groupedCardList.push(name);
groupedCards[name] = [];
}
groupedCards[name].push({
cid: c.cid,
suit: c.suit,
number: c.number,
});
});
let model = [];
groupedCardList.forEach(name => {
let cards = groupedCards[name];
if (cards.length === 1) {
model.push({
name: name,
extension: pkg,
suit: cards[0].suit,
number: cards[0].number,
cid: cards[0].cid,
});
} else {
model.push({
name: name,
cid: cards[0].cid,
cards: cards,
})
}
});
gridView.model = model;
appearAnim.start();
}
}
SequentialAnimation {
id: appearAnim
PauseAnimation { duration: 200 }
ParallelAnimation {
PropertyAnimation {
target: gridView
property: "opacity"
to: 1
duration: 150
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: gridView
property: "y"
from: 20
to: 10
duration: 150
easing.type: Easing.InOutQuad
}
}
}
Rectangle {
id: cardDetail
width: 310
height: parent.height - 20
y: 10
anchors.right: parent.right
anchors.rightMargin: 10
color: "#88EEEEEE"
radius: 8
property int cid: 1
property var cards
function updateCard() {
let data = JSON.parse(Backend.callLuaFunction("GetCardData", [cid]));
const suitTable = {
spade: "♠", heart: '<font color="red">♥</font>',
club: "♣", diamond: '<font color="red">♦</font>',
}
const getNumString = n => {
switch (n) {
case 1:
return "A";
case 11:
return "J";
case 12:
return "Q";
case 13:
return "K";
default:
return n.toString();
}
}
if (!cards) {
detailCard.setData(data);
detailCard.dupCount = 0;
} else {
detailCard.cid = cid;
detailCard.color = "";
detailCard.suit = "";
detailCard.number = 0;
detailCard.dupCount = cards.length;
}
detailCard.known = true;
cardText.clear();
cardText.append(Backend.translate(":" + data.name));
let skills = JSON.parse(Backend.callLuaFunction
("GetCardSpecialSkills", [cid]));
if (skills.length > 0) {
cardText.append("<br/>" + Backend.translate("Special card skills:"));
skills.forEach(t => {
cardText.append("<b>" + Backend.translate(t) + "</b>: "
+ Backend.translate(":" + t));
});
}
if (cards) {
cardText.append("<br/>" + Backend.translate("Every suit & number:"));
cardText.append(cards.map(c => {
return (suitTable[c.suit] + getNumString(c.number))
}).join(", "));
}
}
Flickable {
flickableDirection: Flickable.VerticalFlick
contentHeight: detailLayout.height
width: parent.width - 40
height: parent.height - 40
clip: true
anchors.centerIn: parent
ScrollBar.vertical: ScrollBar {}
ColumnLayout {
id: detailLayout
width: parent.width
CardItem {
id: detailCard
Layout.alignment: Qt.AlignHCenter
cid: 1
known: false
property int dupCount: 0
Text {
anchors.right: parent.right
anchors.bottom: parent.bottom
text: parent.dupCount ? ("x" + parent.dupCount.toString()) : ""
font.pixelSize: 36
color: "white"
style: Text.Outline
}
}
TextEdit {
id: cardText
Layout.fillWidth: true
readOnly: true
selectByKeyboard: true
selectByMouse: false
wrapMode: TextEdit.WordWrap
textFormat: TextEdit.RichText
font.pixelSize: 16
}
}
}
}

View File

@ -10,31 +10,163 @@ Item {
property bool loaded: false
Rectangle {
anchors.fill: listView
color: "#88EEEEEE"
radius: 6
}
ListView {
width: Math.floor(root.width / 98) * 98
height: parent.height
anchors.centerIn: parent
id: listView
width: 130
height: parent.height - 20
y: 10
ScrollBar.vertical: ScrollBar {}
model: ListModel {
id: packages
}
delegate: ColumnLayout {
Text { text: Backend.translate(name) }
GridLayout {
columns: root.width / 98
Repeater {
model: JSON.parse(Backend.callLuaFunction("GetGenerals", [name]))
GeneralCardItem {
autoBack: false
name: modelData
onClicked: {
generalText.clear();
generalText.general = modelData;
generalText.updateGeneral();
generalDetail.open();
}
}
highlight: Rectangle { color: "#E91E63"; radius: 5 }
highlightMoveDuration: 500
delegate: Item {
width: listView.width
height: 40
Text {
text: Backend.translate(name)
anchors.centerIn: parent
}
TapHandler {
onTapped: {
listView.currentIndex = index;
}
}
}
onCurrentIndexChanged: { vanishAnim.start(); }
}
GridView {
id: gridView
width: root.width - listView.width - generalDetail.width - 16
height: parent.height - 20
y: 10
anchors.left: listView.right
anchors.leftMargin: 8 + (width % 100) / 2
cellHeight: 140
cellWidth: 100
delegate: GeneralCardItem {
autoBack: false
name: modelData
onClicked: {
generalText.clear();
generalDetail.general = modelData;
generalDetail.updateGeneral();
// generalDetail.open();
}
}
}
ParallelAnimation {
id: vanishAnim
PropertyAnimation {
target: gridView
property: "opacity"
to: 0
duration: 150
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: gridView
property: "y"
to: 30
duration: 150
easing.type: Easing.InOutQuad
}
onFinished: {
gridView.model = JSON.parse(Backend.callLuaFunction("GetGenerals",
[listView.model.get(listView.currentIndex).name]));
appearAnim.start();
}
}
SequentialAnimation {
id: appearAnim
PauseAnimation { duration: 200 }
ParallelAnimation {
PropertyAnimation {
target: gridView
property: "opacity"
to: 1
duration: 150
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: gridView
property: "y"
from: 20
to: 10
duration: 150
easing.type: Easing.InOutQuad
}
}
}
Rectangle {
id: generalDetail
width: 310
height: parent.height - 20
y: 10
anchors.right: parent.right
anchors.rightMargin: 10
color: "#88EEEEEE"
radius: 8
property string general: "caocao"
function updateGeneral() {
detailGeneralCard.name = general;
let data = JSON.parse(Backend.callLuaFunction("GetGeneralDetail", [general]));
generalText.clear();
data.skill.forEach(t => {
generalText.append("<b>" + Backend.translate(t.name) + "</b>: " + t.description)
});
data.related_skill.forEach(t => {
generalText.append("<font color=\"purple\"><b>" + Backend.translate(t.name) + "</b>: " + t.description + "</font>")
});
}
Flickable {
flickableDirection: Flickable.VerticalFlick
contentHeight: detailLayout.height
width: parent.width - 40
height: parent.height - 40
clip: true
anchors.centerIn: parent
ScrollBar.vertical: ScrollBar {}
ColumnLayout {
id: detailLayout
width: parent.width
GeneralCardItem {
id: detailGeneralCard
Layout.alignment: Qt.AlignHCenter
name: "caocao"
}
TextEdit {
id: generalText
Layout.fillWidth: true
readOnly: true
selectByKeyboard: true
selectByMouse: false
wrapMode: TextEdit.WordWrap
textFormat: TextEdit.RichText
font.pixelSize: 16
}
}
}
@ -48,57 +180,11 @@ Item {
}
}
Drawer {
id: generalDetail
edge: Qt.RightEdge
width: parent.width * 0.4 / mainWindow.scale
height: parent.height / mainWindow.scale
dim: false
clip: true
dragMargin: 0
scale: mainWindow.scale
transformOrigin: Item.TopRight
Flickable {
flickableDirection: Flickable.VerticalFlick
contentWidth: generalText.width
contentHeight: generalText.height
width: parent.width * 0.8
height: parent.height * 0.8
clip: true
anchors.centerIn: parent
ScrollBar.vertical: ScrollBar {}
TextEdit {
id: generalText
property string general: ""
width: generalDetail.width * 0.75
readOnly: true
selectByKeyboard: true
selectByMouse: true
wrapMode: TextEdit.WordWrap
textFormat: TextEdit.RichText
font.pixelSize: 16
function updateGeneral() {
let data = JSON.parse(Backend.callLuaFunction("GetGeneralDetail", [general]));
this.append(Backend.translate(data.kingdom) + " " + Backend.translate(general) + " " + data.hp + "/" + data.maxHp);
data.skill.forEach(t => {
this.append("<b>" + Backend.translate(t.name) + "</b>: " + t.description)
});
data.related_skill.forEach(t => {
this.append("<font color=\"purple\"><b>" + Backend.translate(t.name) + "</b>: " + t.description + "</font>")
});
}
}
}
}
function loadPackages() {
if (loaded) return;
let packs = JSON.parse(Backend.callLuaFunction("GetAllGeneralPack", []));
packs.forEach((name) => packages.append({ name: name }));
generalDetail.updateGeneral();
loaded = true;
}
}

View File

@ -1,7 +0,0 @@
fk={}pcall(function()dofile'lua/freekill.lua'end)
a=Exppattern:Parse('slash,asd,df,^sd,sfff,^(xzc,afsd)|34,23|.|.|.|.|^(23~32)')
p(a.matchers)
c = { trueName = 'slash', number = 4, id = 155 }
p(a:match(c))
p(a:matchExp('^jink'))
print(a)