askForUseViewAsSkill
送花砸蛋
This commit is contained in:
notify 2023-05-19 23:03:39 +08:00 committed by GitHub
parent ead6de967f
commit c222728a98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 456 additions and 45 deletions

132
Fk/ChatAnim/Egg.qml Normal file
View File

@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import Fk
Item {
id: root
anchors.fill: parent
property point start: Qt.point(0, 0)
property point end: Qt.point(0, 0)
property alias running: pointToAnimation.running
signal finished()
Image {
id: egg
source: SkinBank.PIXANIM_DIR + "/egg/egg"
x: start.x - width / 2
y: start.y - height / 2
scale: 0.7
opacity: 0
}
Image {
id: whip
x: end.x - width / 2
y: end.y - height / 2
property int idx: 1
opacity: 0
scale: 0.7
source: SkinBank.PIXANIM_DIR + "/egg/egg" + idx
}
SequentialAnimation {
id: pointToAnimation
running: false
PropertyAnimation {
target: egg
property: "opacity"
to: 1
duration: 400
}
PauseAnimation {
duration: 350
}
ScriptAction {
script: Backend.playSound("./audio/system/fly" + (Math.floor(Math.random() * 2) + 1));
}
ParallelAnimation {
PropertyAnimation {
target: egg
property: "scale"
to: 0.4
duration: 500
}
PropertyAnimation {
target: egg
property: "x"
to: end.x - egg.width / 2
duration: 500
}
PropertyAnimation {
target: egg
property: "y"
to: end.y - egg.height / 2
duration: 500
}
PropertyAnimation {
target: egg
property: "rotation"
to: 360
duration: 250
loops: 2
}
SequentialAnimation {
PauseAnimation { duration: 400 }
PropertyAnimation {
target: egg
property: "opacity"
to: 0
duration: 100
}
}
}
ScriptAction {
script: Backend.playSound("./audio/system/egg" + (Math.floor(Math.random() * 2) + 1));
}
ParallelAnimation {
SequentialAnimation {
SequentialAnimation {
PauseAnimation { duration: 160 }
ScriptAction { script: whip.idx++; }
loops: 2
}
PauseAnimation { duration: 160 }
}
SequentialAnimation {
PropertyAnimation {
target: whip
property: "opacity"
to: 1
duration: 100
}
PauseAnimation { duration: 300 }
PropertyAnimation {
target: whip
property: "opacity"
to: 0
duration: 100
}
}
}
onStopped: {
root.visible = false;
root.finished();
}
}
}

169
Fk/ChatAnim/Flower.qml Normal file
View File

@ -0,0 +1,169 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import Fk
Item {
id: root
anchors.fill: parent
property point start: Qt.point(0, 0)
property point end: Qt.point(0, 0)
property alias running: pointToAnimation.running
signal finished()
Image {
id: egg
source: SkinBank.PIXANIM_DIR + "/flower/egg"
x: start.x - width / 2
y: start.y - height / 2
scale: 0.7
rotation: Math.atan(Math.abs(end.y - start.y) / Math.abs(end.x - start.x))
/ Math.PI * 180 + 90 * (end.x > start.x ? 1 : -1)
}
Image {
id: whip
x: end.x - width / 2
y: end.y - height / 2
property int idx: 1
opacity: 0
scale: 0.7
source: SkinBank.PIXANIM_DIR + "/flower/egg" + idx
}
Image {
id: star
opacity: 0
source: SkinBank.PIXANIM_DIR + "/flower/star"
scale: 0.7
}
SequentialAnimation {
id: pointToAnimation
running: false
ScriptAction {
script: Backend.playSound("./audio/system/fly" + (Math.floor(Math.random() * 2) + 1));
}
ParallelAnimation {
PropertyAnimation {
target: egg
property: "scale"
to: 0.5
duration: 360
}
PropertyAnimation {
target: egg
property: "x"
to: end.x - egg.width / 2
duration: 360
}
PropertyAnimation {
target: egg
property: "y"
to: end.y - egg.height / 2
duration: 360
}
SequentialAnimation {
PauseAnimation { duration: 300 }
PropertyAnimation {
target: egg
property: "opacity"
to: 0
duration: 60
}
}
}
ScriptAction {
script: Backend.playSound("./audio/system/flower" + (Math.floor(Math.random() * 2) + 1));
}
ParallelAnimation {
SequentialAnimation {
SequentialAnimation {
PauseAnimation { duration: 180 }
ScriptAction { script: whip.idx++; }
loops: 2
}
ScriptAction {
script: {
star.x = end.x - 25;
star.y = end.y - 35;
}
}
SequentialAnimation {
PropertyAnimation {
target: star
property: "opacity"
to: 1
duration: 100
}
PauseAnimation { duration: 100 }
PropertyAnimation {
target: star
property: "opacity"
to: 0
duration: 100
}
ScriptAction {
script: {
star.x = end.x - 10;
star.y = end.y - 20;
}
}
}
SequentialAnimation {
PropertyAnimation {
target: star
property: "opacity"
to: 1
duration: 100
}
PauseAnimation { duration: 100 }
PropertyAnimation {
target: star
property: "opacity"
to: 0
duration: 100
}
}
}
SequentialAnimation {
PropertyAnimation {
target: whip
property: "opacity"
to: 1
duration: 100
}
PauseAnimation { duration: 1100 }
PropertyAnimation {
target: whip
property: "opacity"
to: 0
duration: 100
}
}
}
onStopped: {
root.visible = false;
root.finished();
}
}
}

2
Fk/ChatAnim/qmldir Normal file
View File

@ -0,0 +1,2 @@
module Fk.ChatAnim
Egg 1.0 Egg.qml

View File

@ -8,6 +8,7 @@ Flickable {
id: root
anchors.fill: parent
property var extra_data: ({})
property int pid
signal finish()
@ -19,6 +20,24 @@ Flickable {
width: parent.width - 40
x: 20
RowLayout {
Button {
text: Backend.translate("Give Flower")
onClicked: {
root.givePresent("Flower");
root.finish();
}
}
Button {
text: Backend.translate("Give Egg")
onClicked: {
root.givePresent("Egg");
root.finish();
}
}
}
// TODO: player details
Text {
id: screenName
@ -40,6 +59,16 @@ Flickable {
}
}
function givePresent(p) {
ClientInstance.notifyServer(
"Chat",
JSON.stringify({
type: 2,
msg: "$!" + p + ":" + pid
})
);
}
onExtra_dataChanged: {
if (!extra_data.photo) return;
screenName.text = "";
@ -47,6 +76,9 @@ Flickable {
let id = extra_data.photo.playerid;
if (id == 0) return;
root.pid = id;
screenName.text = extra_data.photo.screenName;
let data = JSON.parse(Backend.callLuaFunction("GetPlayerSkills", [id]));
data.forEach(t => {

View File

@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Fk.Pages
Rectangle {
property bool isLobby: false
@ -26,34 +28,66 @@ Rectangle {
}
}
Rectangle {
GridView {
id: emojiSelector
Layout.fillWidth: true
Layout.preferredHeight: 28
color: "#040403"
radius: 3
border.width: 1
border.color: "#A6967A"
Layout.preferredHeight: 120
cellHeight: 48
cellWidth: 48
model: 49
visible: false
delegate: ItemDelegate {
Image {
height: 32; width: 32
anchors.centerIn: parent
source: "../../image/emoji/" + index
}
onClicked: chatEdit.insert(chatEdit.cursorPosition, "{emoji" + index + "}");
}
}
TextInput {
anchors.fill: parent
anchors.margins: 6
color: "white"
clip: true
font.pixelSize: 14
RowLayout {
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 28
color: "#040403"
radius: 3
border.width: 1
border.color: "#A6967A"
onAccepted: {
if (text != "") {
ClientInstance.notifyServer(
"Chat",
JSON.stringify({
type: isLobby ? 1 : 2,
msg: text
})
);
text = "";
TextInput {
id: chatEdit
anchors.fill: parent
anchors.margins: 6
color: "white"
clip: true
font.pixelSize: 14
onAccepted: {
if (text != "") {
ClientInstance.notifyServer(
"Chat",
JSON.stringify({
type: isLobby ? 1 : 2,
msg: text
})
);
text = "";
}
}
}
}
MetroButton {
id: emojiBtn
text: "😃"
onClicked: emojiSelector.visible = !emojiSelector.visible;
}
MetroButton {
text: "✔️"
onClicked: chatEdit.accepted();
}
}
}
}

View File

@ -277,6 +277,8 @@ Item {
function addToChat(pid, raw, msg) {
if (raw.type !== 1) return;
msg = msg.replace(/\{emoji([0-9]+)\}/g, '<img src="../../image/emoji/$1.png" height="24" width="24" />');
raw.msg = raw.msg.replace(/\{emoji([0-9]+)\}/g, '<img src="../../image/emoji/$1.png" height="24" width="24" />');
lobbyChat.append(msg);
danmaku.sendLog("<b>" + raw.userName + "</b>: " + raw.msg);
}

View File

@ -9,7 +9,6 @@ import Fk.Common
import Fk.RoomElement
import "RoomLogic.js" as Logic
Item {
id: roomScene
@ -693,6 +692,9 @@ Item {
function addToChat(pid, raw, msg) {
if (raw.type === 1) return;
msg = msg.replace(/\{emoji([0-9]+)\}/g, '<img src="../../image/emoji/$1.png" height="24" width="24" />');
raw.msg = raw.msg.replace(/\{emoji([0-9]+)\}/g, '<img src="../../image/emoji/$1.png" height="24" width="24" />');
if (raw.msg.startsWith("$")) {
if (specialChat(pid, raw, raw.msg.slice(1))) return;
}
@ -710,20 +712,32 @@ Item {
function specialChat(pid, data, msg) {
// skill audio: %s%d
// death audio: ~%s
// something special: .%s:...
// something special: !%s:...
let time = data.time;
let userName = data.userName;
let general = Backend.translate(data.general);
if (msg.startsWith(".")) {
if (msg.startsWith("!")) {
let splited = msg.split(":");
let type = splited[0].slice(1);
switch (type) {
case "egg": {
return true;
}
case "flower": {
case "Egg":
case "Flower": {
const fromId = pid;
const toId = parseInt(splited[1]);
const component = Qt.createComponent("../ChatAnim/" + type + ".qml");
//if (component.status !== Component.Ready)
// return false;
const fromItem = Logic.getPhoto(fromId);
const fromPos = mapFromItem(fromItem, fromItem.width / 2, fromItem.height / 2);
const toItem = Logic.getPhoto(toId);
const toPos = mapFromItem(toItem, toItem.width / 2, toItem.height / 2);
const egg = component.createObject(roomScene, { start: fromPos, end: toPos });
egg.finished.connect(() => egg.destroy());
egg.running = true;
return true;
}
default:

View File

@ -68,14 +68,15 @@ function arrangePhotos() {
function doOkButton() {
if (roomScene.state == "playing" || roomScene.state == "responding") {
replyToServer(JSON.stringify(
const reply = JSON.stringify(
{
card: dashboard.getSelectedCard(),
targets: selected_targets,
special_skill: roomScene.getCurrentCardUseMethod(),
interaction_data: roomScene.skillInteraction.item ? roomScene.skillInteraction.item.answer : undefined,
}
));
);
replyToServer(reply);
return;
}
if (roomScene.extra_data.luckCard) {
@ -823,6 +824,7 @@ callbacks["AskForUseActiveSkill"] = function(jsonData) {
let skill_name = data[0];
let prompt = data[1];
let cancelable = data[2];
let extra_data = data[3] ?? {};
if (prompt === "") {
roomScene.promptText = Backend.translate("#AskForUseActiveSkill")
.arg(Backend.translate(skill_name));
@ -832,8 +834,11 @@ callbacks["AskForUseActiveSkill"] = function(jsonData) {
roomScene.respond_play = false;
roomScene.state = "responding";
roomScene.responding_card = ".";
roomScene.autoPending = true;
dashboard.startPending(skill_name);
roomScene.extra_data = extra_data;
// dashboard.startPending(skill_name);
roomScene.activateSkill(skill_name, true);
cancelButton.enabled = cancelable;
}

View File

@ -220,6 +220,6 @@ Item {
config.winWidth = width;
config.winHeight = height;
config.saveConf();
Backend.quitLobby();
Backend.quitLobby(false);
}
}

BIN
audio/system/egg1.mp3 Normal file

Binary file not shown.

BIN
audio/system/egg2.mp3 Normal file

Binary file not shown.

BIN
audio/system/flower1.mp3 Normal file

Binary file not shown.

BIN
audio/system/flower2.mp3 Normal file

Binary file not shown.

BIN
audio/system/fly1.mp3 Normal file

Binary file not shown.

BIN
audio/system/fly2.mp3 Normal file

Binary file not shown.

BIN
image/anim/egg/egg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
image/anim/egg/egg1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
image/anim/egg/egg2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
image/anim/egg/egg3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
image/anim/flower/egg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
image/anim/flower/egg1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
image/anim/flower/egg2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
image/anim/flower/egg3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
image/anim/flower/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
image/emoji/24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
image/emoji/26.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/27.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/28.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
image/emoji/29.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/31.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
image/emoji/34.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/35.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/37.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/38.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/39.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/41.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/42.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
image/emoji/43.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/44.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/45.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/46.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/47.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
image/emoji/48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
image/emoji/49.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
image/emoji/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
image/emoji/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
image/emoji/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
image/emoji/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -40,6 +40,9 @@ Fk:loadTranslationTable{
["General Packages"] = "武将拓展包",
["Card Packages"] = "卡牌拓展包",
["Give Flower"] = "送花",
["Give Egg"] = "砸蛋",
["$OnlineInfo"] = "大厅人数:%1总在线人数%2",
["Generals Overview"] = "武将一览",

View File

@ -871,7 +871,7 @@ function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra
cancelable = cancelable or false
extra_data = extra_data or {}
local skill = Fk.skills[skill_name]
if not (skill and skill:isInstanceOf(ActiveSkill)) then
if not (skill and (skill:isInstanceOf(ActiveSkill) or skill:isInstanceOf(ViewAsSkill))) then
print("Attempt ask for use non-active skill: " .. skill_name)
return false
end
@ -894,11 +894,18 @@ function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra
local card_data = json.decode(card)
local selected_cards = card_data.subcards
self:doIndicate(player.id, targets)
skill:onUse(self, {
from = player.id,
cards = selected_cards,
tos = targets,
})
if skill.interaction then
skill.interaction.data = data.interaction_data
end
if skill:isInstanceOf(ActiveSkill) then
skill:onUse(self, {
from = player.id,
cards = selected_cards,
tos = targets,
})
end
return true, {
cards = selected_cards,
@ -906,6 +913,8 @@ function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra
}
end
Room.askForUseViewAsSkill = Room.askForUseActiveSkill
--- 询问一名角色弃牌。
---
--- 在这个函数里面牌已经被弃掉了。

View File

@ -78,9 +78,18 @@ local test_active = fk.CreateActiveSkill{
on_use = function(self, room, effect)
--room:doSuperLightBox("packages/test/qml/Test.qml")
local from = room:getPlayerById(effect.from)
local to = room:getPlayerById(effect.tos[1])
--local to = room:getPlayerById(effect.tos[1])
-- room:swapSeat(from, to)
from:control(to)
--from:control(to)
local success, dat = room:askForUseViewAsSkill(from, "test_vs", nil, true)
if success then
local card = Fk.skills["test_vs"]:viewAs(dat.cards)
room:useCard{
from = from.id,
tos = table.map(dat.targets, function(e) return {e} end),
card = card,
}
end
-- from:pindian({to})
-- local result = room:askForCustomDialog(from, "simayi", "packages/test/qml/TestDialog.qml", "Hello, world. FROM LUA")
-- print(result)

View File

@ -106,10 +106,10 @@ void QmlBackend::joinServer(QString address) {
client->connectToHost(addr, port);
}
void QmlBackend::quitLobby() {
void QmlBackend::quitLobby(bool close) {
if (ClientInstance)
ClientInstance->deleteLater();
if (ServerInstance)
delete ClientInstance;
if (ServerInstance && close)
ServerInstance->deleteLater();
}

View File

@ -26,7 +26,7 @@ public:
Q_INVOKABLE void joinServer(QString address);
// Lobby
Q_INVOKABLE void quitLobby();
Q_INVOKABLE void quitLobby(bool close = true);
// lua --> qml
void emitNotifyUI(const QString &command, const QString &jsonData);