Dev bugfix (#352)

- 搬运了ArrangeCards。
- 优化了GuanxingBox的操作
- 修复了不能及时更新技能prompt的bug
- 取消目标后会刷新目标选择
- 完备了借刀的牌名

---------

Co-authored-by: notify <notify-ctrl@qq.com>
This commit is contained in:
YoumuKon 2024-06-10 15:02:46 +08:00 committed by GitHub
parent 4235bf6237
commit 5090bdba77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 687 additions and 43 deletions

View File

@ -718,6 +718,40 @@ function updateSelectedTargets(playerid, selected) {
}
if (candidate) {
if (!selected) {
const remain_targets = [];
selected_targets.forEach(id => {
const photo = getPhoto(id);
const ret = lcall("CanUseCardToTarget", card, id, remain_targets,
JSON.stringify(roomScene.extra_data));
let bool = ret;
if (roomScene.extra_data instanceof Object) {
const must = roomScene.extra_data.must_targets;
const included = roomScene.extra_data.include_targets;
const exclusive = roomScene.extra_data.exclusive_targets;
if (exclusive instanceof Array) {
if (exclusive.indexOf(id) === -1) bool = false;
}
if (must instanceof Array) {
if (must.filter((val) => {
return remain_targets.indexOf(val) === -1;
}).length !== 0 && must.indexOf(id) === -1) bool = false;
}
if (included instanceof Array) {
if (included.filter((val) => {
return remain_targets.indexOf(val) !== -1;
}).length === 0 && included.indexOf(id) === -1) bool = false;
}
}
if (bool) {
remain_targets.push(id);
} else {
photo.selected = false;
}
})
selected_targets = remain_targets;
}
roomScene.resetPrompt(); // update prompt due to selected_targets
const prompt = lcall("ActiveSkillPrompt",
dashboard.pending_skill !== "" ? dashboard.pending_skill: lcall("GetCardSkill", card),
@ -779,6 +813,10 @@ function updateSelectedTargets(playerid, selected) {
}
}
}
const prompt = lcall("CardPrompt", card, selected_targets);
if (prompt !== "") {
roomScene.setPrompt(Util.processPrompt(prompt));
}
} else {
all_photos.forEach(photo => {
photo.state = "normal";
@ -1014,8 +1052,31 @@ callbacks["AskForSkillInvoke"] = (data) => {
roomScene.cancelButton.enabled = true;
}
callbacks["AskForArrangeCards"] = (data) => {
roomScene.state = "replying";
roomScene.popupBox.sourceComponent =
Qt.createComponent("../RoomElement/ArrangeCardsBox.qml");
const box = roomScene.popupBox.item;
const cards = data.cards;
box.cards = cards.reduce((newArray, elem) => {
return newArray.concat(elem.map(cid => lcall("GetCardData", cid)));
}, []);
box.org_cards = cards;
box.prompt = data.prompt;
box.size = data.size;
box.areaCapacities = data.capacities;
box.areaLimits = data.limits;
box.free_arrange = data.is_free;
box.areaNames = data.names;
box.pattern = data.pattern;
box.poxi_type = data.poxi_type;
box.cancelable = data.cancelable;
box.initializeCards();
}
callbacks["AskForGuanxing"] = (data) => {
const cards = [];
const cards = data.cards;
const min_top_cards = data.min_top_cards;
const max_top_cards = data.max_top_cards;
const min_bottom_cards = data.min_bottom_cards;
@ -1026,9 +1087,9 @@ callbacks["AskForGuanxing"] = (data) => {
roomScene.state = "replying";
roomScene.popupBox.sourceComponent =
Qt.createComponent("../RoomElement/GuanxingBox.qml");
data.cards.forEach(id => cards.push(lcall("GetCardData", id)));
const box = roomScene.popupBox.item;
box.prompt = prompt;
box.free_arrange = data.is_free;
if (max_top_cards === 0) {
box.areaCapacities = [max_bottom_cards];
box.areaLimits = [min_bottom_cards];
@ -1044,8 +1105,11 @@ callbacks["AskForGuanxing"] = (data) => {
box.areaNames = [luatr(top_area_name), luatr(bottom_area_name)];
}
}
box.cards = cards;
box.arrangeCards();
box.org_cards = cards;
box.cards = cards.reduce((newArray, elem) => {
return newArray.concat(elem.map(cid => lcall("GetCardData", cid)));
}, []);
box.initializeCards();
box.accepted.connect(() => {
replyToServer(JSON.stringify(box.getResult()));
});
@ -1061,6 +1125,7 @@ callbacks["AskForExchange"] = (data) => {
Qt.createComponent("../RoomElement/GuanxingBox.qml");
let for_i = 0;
const box = roomScene.popupBox.item;
box.org_cards = data.piles;
data.piles.forEach(ids => {
if (ids.length > 0) {
ids.forEach(id => cards.push(lcall("GetCardData", id)));
@ -1070,11 +1135,11 @@ callbacks["AskForExchange"] = (data) => {
for_i ++;
}
});
box.cards = cards;
box.areaCapacities = capacities
box.areaLimits = limits
box.areaNames = cards_name
box.cards = cards;
box.arrangeCards();
box.initializeCards();
box.accepted.connect(() => {
replyToServer(JSON.stringify(box.getResult()));
});

View File

@ -0,0 +1,423 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import QtQuick.Layouts
import Fk
import Fk.Pages
import Fk.RoomElement
GraphicsBox {
id: root
property string prompt
property var cards: []
property var org_cards: []
property var result: []
property var areaCapacities: []
property var areaLimits: []
property var areaNames: []
property var dragging_card: ""
property var movepos: []
property bool free_arrange: true
property bool cancelable: false
property string poxi_type: ""
property string pattern: "."
property int size: 0
property int padding: 25
title.text: Backend.translate(prompt !== "" ? Util.processPrompt(prompt) : "Please arrange cards")
width: body.width + padding * 2
height: title.height + body.height + padding * 2
ColumnLayout {
id: body
x: padding
y: parent.height - padding - height
spacing: 10
Repeater {
id: areaRepeater
model: areaCapacities
Row {
spacing: 7
property int areaCapacity: modelData
property string areaName: index < areaNames.length ? qsTr(Backend.translate(areaNames[index])) : ""
Rectangle {
anchors.verticalCenter: parent.verticalCenter
color: "#6B5D42"
width: 20
height: 100
radius: 5
Text {
anchors.fill: parent
width: 20
height: 100
text: areaName
color: "white"
font.family: fontLibian.name
font.pixelSize: 18
style: Text.Outline
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
Repeater {
id: cardRepeater
model: (size === 0) ? areaCapacity : 1
Rectangle {
color: "#1D1E19"
width: (size === 0) ? 93 : size * 100 - 7
height: 130
}
}
property alias cardRepeater: cardRepeater
}
}
Row {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
spacing: 32
MetroButton {
width: 120
height: 35
id: buttonConfirm
text: luatr("OK")
onClicked: {
close();
roomScene.state = "notactive";
const reply = JSON.stringify(getResult());
ClientInstance.replyToServer("", reply);
}
}
MetroButton {
width: 120
height: 35
text: luatr("Cancel")
visible: root.cancelable
onClicked: {
close();
roomScene.state = "notactive";
const ret = [];
let i;
for (i = 0; i < result.length; i++) {
ret.push([]);
}
const reply = JSON.stringify(ret);
ClientInstance.replyToServer("", reply);
}
}
}
}
Repeater {
id: cardItem
model: cards
CardItem {
x: index
y: -1
cid: modelData.cid
name: modelData.name
suit: modelData.suit
number: modelData.number
draggable: true
onReleased: updateCardReleased(this);
onDraggingChanged: {
if (!dragging) return;
dragging_card = this;
let i, card
for (i = 0; i < cardItem.count; i++) {
card = cardItem.itemAt(i);
if (card !== this)
card.draggable = false;
}
}
onXChanged : updateCardDragging(this);
onYChanged : updateCardDragging(this);
onSelectedChanged : updateCardSelected(this);
}
}
function updateCardDragging(_card) {
if (!_card.dragging) return;
_card.goBackAnim.stop();
_card.opacity = 0.5
let i, j
let box, pos, pile;
movepos = [];
for (j = 0; j <= result.length; j++) {
if (j >= result.length) {
arrangeCards();
return;
}
pile = areaRepeater.itemAt(j);
if (pile.y === 0) {
pile.y = j * 140
}
box = pile.cardRepeater.itemAt(0);
pos = mapFromItem(pile, box.x, box.y);
if (Math.abs(pos.y - _card.y) < 130 / 2) break;
}
if (result[j].includes(_card)) {
if (j === 0 && !free_arrange) {
arrangeCards();
return;
}
} else if (!_card.selectable) {
arrangeCards();
return;
}
let card;
let index = result[j].indexOf(_card);
if (index === -1 && result[j].length === areaCapacities[j]) {
for (i = result[j].length; i > 0; i--) {
card = result[j][i-1];
if (card === _card) continue;
if (Math.abs(card.x - _card.x) <= card.width / 2 && card.selectable) {
movepos = [j, i-1];
break;
}
}
} else {
for (i = 0; i < result[j].length; i++) {
card = result[j][i];
if (card.dragging) continue;
if (card.x > _card.x) {
movepos = [j, i - ((index !==-1 && index < i) ? 1 : 0)];
break;
}
}
if (movepos.length === 0)
movepos = [j, result[j].length - ((index === -1) ? 0 : 1)];
if (!free_arrange && j === 0 && org_cards[0].includes(_card.cid)) {
let a = 0, b = -1, c = -1;
i = 0;
while (i < result[j].length && a < org_cards[0].length) {
if (result[j][i].cid === org_cards[0][a]) {
if (b !==c) {
c = i;
break;
}
i++;
a++;
} else {
if (b === -1)
b = i;
if (org_cards[0].includes(result[j][i].cid)) {
a++;
} else {
i++;
}
}
}
if (b === -1) b = result[j].length;
if (c === -1) c = result[j].length;
if (b === c)
movepos = [j, b];
else if (movepos[1] < b || (movepos[1] > c && c !==-1))
movepos = [];
}
}
arrangeCards();
}
function updateCardReleased(_card) {
let i, j;
if (movepos.length === 2) {
for (j = 0; j < result.length; j++) {
i = result[j].indexOf(_card);
if (i !==-1) {
if (j !==movepos[0] && result[movepos[0]].length === areaCapacities[movepos[0]]) {
result[j][i] = result[movepos[0]][movepos[1]];
result[movepos[0]][movepos[1]] = _card;
if (!free_arrange && result[0].length < areaCapacities[0])
result[0].sort((a, b) => org_cards[0].indexOf(a.cid) - org_cards[0].indexOf(b.cid));
} else {
result[j].splice(i, 1);
result[movepos[0]].splice(movepos[1], 0, _card);
}
movepos = [];
break;
}
}
}
dragging_card = "";
arrangeCards();
}
function updateCardSelected(_card) {
let i = result[0].indexOf(_card);
let j;
if (i === -1) {
if (result[0].length < areaCapacities[0]) {
if (free_arrange || !org_cards[0].includes(_card.cid)) {
for (j = 1; j < result.length; j++) {
i = result[j].indexOf(_card);
if (i !==-1) {
result[j].splice(i, 1);
result[0].push(_card);
arrangeCards();
break;
}
}
} else {
i = 0;
j = 0;
while (i < result[0].length && j < org_cards[0].length) {
if (org_cards[0][j] === _card.cid) break;
if (result[0][i].cid === org_cards[0][j]) {
i++;
j++;
} else {
if (org_cards[0].includes(result[0][i].cid))
j++;
else
i++;
}
}
let index;
for (j = 1; j < result.length; j++) {
index = result[j].indexOf(_card);
if (index !== -1) {
result[j].splice(index, 1);
result[0].splice(i, 0, _card);
arrangeCards();
break;
}
}
}
}
} else {
for (j = 1; j < result.length; j++) {
if (result[j].length < areaCapacities[j]) {
result[0].splice(i, 1);
result[j].push(_card);
arrangeCards();
break;
}
}
}
}
function arrangeCards() {
let i, j, a, b;
let card, box, pos, pile;
let spacing;
let same_row;
let c_result = getResult();
let is_exchange = (movepos.length === 2 && !result[movepos[0]].includes(dragging_card) && result[movepos[0]].length === areaCapacities[movepos[0]])
for (j = 0; j < result.length; j++) {
pile = areaRepeater.itemAt(j);
box = pile.cardRepeater.itemAt(0);
if (pile.y === 0) {
pile.y = j * 140
}
a = result[j].length;
if (movepos.length === 2) {
if (movepos[0] === j && !result[j].includes(dragging_card) && result[j].length < areaCapacities[j]) {
a++;
} else if (movepos[0] !== j && result[j].includes(dragging_card)) {
a--;
}
}
spacing = (size > 0 && a > size) ? ((size - 1) * 100 / (a - 1)) : 100;
b = 0;
for (i = 0; i < result[j].length; i++) {
card = result[j][i];
if (card.dragging) {
if (movepos.length !== 2 || movepos[0] !== j)
b++;
continue;
}
if (movepos.length === 2 && movepos[0] === j && b === movepos[1] && !is_exchange)
b++;
pos = mapFromItem(pile, box.x, box.y);
card.glow.visible = false;
card.chosenInBox = (movepos.length === 2 && result[j].length === areaCapacities[j] && movepos[0] === j && movepos[1] === b);
card.origX = (movepos.length === 2 && movepos[0] === j && b > (movepos[1] - (is_exchange ? 0 : 1))) ? (pos.x + (b - 1) * spacing + 100) : (pos.x + b * spacing);
card.origY = pos.y;
card.opacity = 1;
card.z = i + 1;
card.initialZ = i + 1;
card.maxZ = cardItem.count;
if (poxi_type !== "")
card.selectable = lcall("PoxiFilter", poxi_type, card.cid, [dragging_card.cid], c_result, org_cards);
else if (pattern !== ".")
card.selectable = lcall("CardFitPattern", card.cid, pattern);
else {
if (free_arrange || dragging_card === "")
card.selectable = true;
else if (result[j].length < areaCapacities[j] + (result[j].includes(dragging_card) ? 1 : 0))
card.selectable = (j !== 0);
else {
if (j === 0)
card.selectable = !org_cards[0].includes(dragging_card.cid) || i === org_cards[0].indexOf(dragging_card.cid);
else {
if (result[0].includes(dragging_card))
card.selectable = result[0].length < areaCapacities[0] || !org_cards[0].includes(card.cid) || card.cid === org_cards[0][result[0].indexOf(dragging_card)]
else
card.selectable = org_cards[0].includes(dragging_card.cid) || card.cid === org_cards[0][result[0].indexOf(dragging_card)]
}
}
}
card.draggable = (dragging_card === "") && (free_arrange || j > 0 || card.selectable);
card.goBack(true);
b++;
}
}
for (i = 0; i < areaRepeater.count; i++) {
if (result[i].length < areaLimits[i]) {
buttonConfirm.enabled = false;
break;
}
buttonConfirm.enabled = poxi_type ? lcall("PoxiFeasible", poxi_type, [], c_result, org_cards) : true;
}
}
function initializeCards() {
result = new Array(areaCapacities.length);
let i, j;
let k = 0;
for (i = 0; i < result.length; i++){
result[i] = [];
}
let card;
for (j = 0; j < org_cards.length; j++){
for (i = 0; i < org_cards[j].length; i++){
result[j].push(cardItem.itemAt(k));
k++;
}
}
arrangeCards();
}
function getResult() {
const ret = [];
result.forEach(t => {
const t2 = [];
t.forEach(v => t2.push(v.cid));
ret.push(t2);
});
return ret;
}
}

View File

@ -322,11 +322,6 @@ RowLayout {
const enabled_cards = [];
const targets = roomScene.selected_targets;
const prompt = lcall("ActiveSkillPrompt", pending_skill, pendings,
targets);
if (prompt !== "") {
roomScene.setPrompt(Util.processPrompt(prompt));
}
handcardAreaItem.cards.forEach((card) => {
if (card.selected || lcall("ActiveCardFilter", pending_skill, card.cid,
@ -373,6 +368,11 @@ RowLayout {
pending_card = -1;
cardSelected(pending_card);
}
const prompt = lcall("ActiveSkillPrompt", pending_skill, pendings,
targets);
if (prompt !== "") {
roomScene.setPrompt(Util.processPrompt(prompt));
}
}
function startPending(skill_name) {

View File

@ -8,10 +8,14 @@ GraphicsBox {
id: root
property string prompt
property var cards: []
property var org_cards: []
property var movepos: []
property var dragging_card: ""
property var result: []
property var areaCapacities: []
property var areaLimits: []
property var areaNames: []
property bool free_arrange: true
property int padding: 25
title.text: luatr(prompt !== "" ? prompt : "Please arrange cards")
@ -103,59 +107,191 @@ GraphicsBox {
number: modelData.number
mark: modelData.mark
draggable: true
onReleased: arrangeCards();
}
}
function arrangeCards() {
result = new Array(areaCapacities.length);
let i;
for (i = 0; i < result.length; i++){
result[i] = [];
}
let card, j, area, cards, stay;
onDraggingChanged: {
if (!dragging) return;
dragging_card = this;
let i, card
for (i = 0; i < cardItem.count; i++) {
card = cardItem.itemAt(i);
stay = true;
for (j = areaRepeater.count - 1; j >= 0; j--) {
area = areaRepeater.itemAt(j);
cards = result[j];
if (cards.length < areaCapacities[j] && card.y >= area.y) {
cards.push(card);
stay = false;
break;
if (card !== this)
card.draggable = false;
}
}
onReleased: updateCardReleased(this);
onXChanged : updateCardDragging(this);
onYChanged : updateCardDragging(this);
}
}
if (stay) {
for (j = 0; j < areaRepeater.count; j++) {
if (result[j].length < areaCapacities[j]) {
result[j].push(card);
break;
}
}
}
}
for(i = 0; i < result.length; i++)
result[i].sort((a, b) => a.x - b.x);
function updateCardDragging(_card) {
if (!_card.dragging) return;
_card.goBackAnim.stop();
_card.opacity = 0.5
let i, j
let box, pos, pile;
for (j = 0; j < areaRepeater.count; j++) {
movepos = [];
for (j = 0; j <= result.length; j++) {
if (j >= result.length) {
arrangeCards();
return;
}
pile = areaRepeater.itemAt(j);
if (pile.y === 0) {
pile.y = j * 150
}
for (i = 0; i < result[j].length; i++) {
box = pile.cardRepeater.itemAt(i);
box = pile.cardRepeater.itemAt(0);
pos = mapFromItem(pile, box.x, box.y);
if (Math.abs(pos.y - _card.y) < 130 / 2) break;
}
if (result[j].includes(_card)) {
if (j === 0 && !free_arrange) {
arrangeCards();
return;
}
} else if (!_card.selectable) {
arrangeCards();
return;
}
let card;
let index = result[j].indexOf(_card);
if (index === -1 && result[j].length === areaCapacities[j]) {
for (i = result[j].length; i > 0; i--) {
card = result[j][i-1];
if (card === _card) continue;
if (Math.abs(card.x - _card.x) <= card.width / 2 && card.selectable) {
movepos = [j, i-1];
break;
}
}
} else {
for (i = 0; i < result[j].length; i++) {
card = result[j][i];
card.origX = pos.x;
if (card.dragging) continue;
if (card.x > _card.x) {
movepos = [j, i - ((index !==-1 && index < i) ? 1 : 0)];
break;
}
}
if (movepos.length === 0)
movepos = [j, result[j].length - ((index === -1) ? 0 : 1)];
if (!free_arrange && j === 0 && org_cards[0].includes(_card.cid)) {
let a = 0, b = -1, c = -1;
i = 0;
while (i < result[j].length && a < org_cards[0].length) {
if (result[j][i].cid === org_cards[0][a]) {
if (b !==c) {
c = i;
break;
}
i++;
a++;
} else {
if (b === -1)
b = i;
if (org_cards[0].includes(result[j][i].cid)) {
a++;
} else {
i++;
}
}
}
if (b === -1) b = result[j].length;
if (c === -1) c = result[j].length;
if (b === c)
movepos = [j, b];
else if (movepos[1] < b || (movepos[1] > c && c !==-1))
movepos = [];
}
}
arrangeCards();
}
function updateCardReleased(_card) {
let i, j;
if (movepos.length === 2) {
for (j = 0; j < result.length; j++) {
i = result[j].indexOf(_card);
if (i !==-1) {
if (j !==movepos[0] && result[movepos[0]].length === areaCapacities[movepos[0]]) {
result[j][i] = result[movepos[0]][movepos[1]];
result[movepos[0]][movepos[1]] = _card;
if (!free_arrange && result[0].length < areaCapacities[0])
result[0].sort((a, b) => org_cards[0].indexOf(a.cid) - org_cards[0].indexOf(b.cid));
} else {
result[j].splice(i, 1);
result[movepos[0]].splice(movepos[1], 0, _card);
}
movepos = [];
break;
}
}
}
dragging_card = "";
arrangeCards();
}
function arrangeCards() {
let i, j, a, b;
let card, box, pos, pile;
let spacing;
let same_row;
let c_result = getResult();
let is_exchange = (movepos.length === 2 && !result[movepos[0]].includes(dragging_card) && result[movepos[0]].length === areaCapacities[movepos[0]])
for (j = 0; j < result.length; j++) {
pile = areaRepeater.itemAt(j);
box = pile.cardRepeater.itemAt(0);
if (pile.y === 0) {
pile.y = j * 150
}
a = result[j].length;
if (movepos.length === 2) {
if (movepos[0] === j && !result[j].includes(dragging_card) && result[j].length < areaCapacities[j]) {
a++;
} else if (movepos[0] !== j && result[j].includes(dragging_card)) {
a--;
}
}
spacing = 100;
b = 0;
for (i = 0; i < result[j].length; i++) {
card = result[j][i];
if (card.dragging) {
if (movepos.length !== 2 || movepos[0] !== j)
b++;
continue;
}
if (movepos.length === 2 && movepos[0] === j && b === movepos[1] && !is_exchange)
b++;
pos = mapFromItem(pile, box.x, box.y);
card.glow.visible = false;
card.origX = (movepos.length === 2 && movepos[0] === j && b > (movepos[1] - (is_exchange ? 0 : 1))) ? (pos.x + (b - 1) * spacing + 100) : (pos.x + b * spacing);
card.origY = pos.y;
card.opacity = 1;
card.z = i + 1;
card.initialZ = i + 1;
card.maxZ = cardItem.count;
if (free_arrange || dragging_card === "")
card.selectable = true;
else if (result[j].length < areaCapacities[j] + (result[j].includes(dragging_card) ? 1 : 0))
card.selectable = (j !== 0);
else {
if (j === 0)
card.selectable = !org_cards[0].includes(dragging_card.cid) || i === org_cards[0].indexOf(dragging_card.cid);
else {
if (result[0].includes(dragging_card))
card.selectable = result[0].length < areaCapacities[0] || !org_cards[0].includes(card.cid) || card.cid === org_cards[0][result[0].indexOf(dragging_card)]
else
card.selectable = org_cards[0].includes(dragging_card.cid) || card.cid === org_cards[0][result[0].indexOf(dragging_card)]
}
}
card.draggable = (dragging_card === "") && (free_arrange || j > 0 || card.selectable);
card.goBack(true);
b++;
}
}
@ -168,6 +304,26 @@ GraphicsBox {
}
}
function initializeCards() {
result = new Array(areaCapacities.length);
let i, j;
let k = 0;
for (i = 0; i < result.length; i++){
result[i] = [];
}
let card;
for (j = 0; j < org_cards.length; j++){
for (i = 0; i < org_cards[j].length; i++){
result[j].push(cardItem.itemAt(k));
k++;
}
}
arrangeCards();
}
function getResult() {
const ret = [];
result.forEach(t => {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 25 KiB