Enhancement (#253)

- 修复clone狮子的bug
- 支持拓展自定义游戏事件
- 修复反选拓展包时极其卡顿的bug
- 修复自订身份无法正常显示的bug
- 谋攻篇askForCard(s)Chosen
- 修复了倾国时点取消的bug
- player:broadcastSkillInvoke
- 修复客户端白名单忘记屏蔽的bug
This commit is contained in:
notify 2023-08-24 21:37:24 +08:00 committed by GitHub
parent d0913e42ce
commit 607d3b010c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 269 additions and 252 deletions

View File

@ -88,7 +88,7 @@ Flickable {
id: warning id: warning
anchors.rightMargin: 8 anchors.rightMargin: 8
visible: { visible: {
config.disabledPack; // visible //config.disabledPack; // visible
const avail = JSON.parse(Backend.callLuaFunction("GetAvailableGeneralsNum", [])); const avail = JSON.parse(Backend.callLuaFunction("GetAvailableGeneralsNum", []));
const ret = avail < config.preferredGeneralNum * config.preferedPlayerNum; const ret = avail < config.preferredGeneralNum * config.preferedPlayerNum;
return ret; return ret;

View File

@ -94,13 +94,19 @@ function doOkButton() {
replyToServer("1"); replyToServer("1");
} }
let _is_canceling = false;
function doCancelButton() { function doCancelButton() {
if (_is_canceling) return;
_is_canceling = true;
if (roomScene.state === "playing") { if (roomScene.state === "playing") {
dashboard.stopPending(); dashboard.stopPending();
dashboard.deactivateSkillButton(); dashboard.deactivateSkillButton();
dashboard.unSelectAll(); dashboard.unSelectAll();
dashboard.enableCards(); dashboard.enableCards();
dashboard.enableSkills(); dashboard.enableSkills();
_is_canceling = false;
return; return;
} else if (roomScene.state === "responding") { } else if (roomScene.state === "responding") {
const p = dashboard.pending_skill; const p = dashboard.pending_skill;
@ -113,6 +119,8 @@ function doCancelButton() {
dashboard.enableCards(roomScene.responding_card); dashboard.enableCards(roomScene.responding_card);
dashboard.enableSkills(roomScene.responding_card); dashboard.enableSkills(roomScene.responding_card);
} }
_is_canceling = false;
return; return;
} }
@ -121,9 +129,13 @@ function doCancelButton() {
"luckcard", false "luckcard", false
].join(",")); ].join(","));
roomScene.state = "notactive"; roomScene.state = "notactive";
_is_canceling = false;
return; return;
} }
replyToServer("__cancel"); replyToServer("__cancel");
_is_canceling = false;
} }
function replyToServer(jsonData) { function replyToServer(jsonData) {
@ -934,37 +946,25 @@ callbacks["AskForCardChosen"] = (jsonData) => {
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks, // jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
// string reason ] // string reason ]
const data = JSON.parse(jsonData); const data = JSON.parse(jsonData);
const handcard_ids = data[0]; const reason = data._reason;
const equip_ids = data[1];
const delayedTrick_ids = data[2];
const reason = data[3];
const handcards = [];
const equips = [];
const delayedTricks = [];
handcard_ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
handcards.push(card_data);
});
equip_ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
equips.push(card_data);
});
delayedTrick_ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
delayedTricks.push(card_data);
});
roomScene.promptText = Backend.translate("#AskForChooseCard") roomScene.promptText = Backend.translate("#AskForChooseCard")
.arg(Backend.translate(reason)); .arg(Backend.translate(reason));
roomScene.state = "replying"; roomScene.state = "replying";
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/PlayerCardBox.qml"); roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/PlayerCardBox.qml");
const box = roomScene.popupBox.item; const box = roomScene.popupBox.item;
box.addHandcards(handcards); for (let d of data.card_data) {
box.addEquips(equips); const arr = [];
box.addDelayedTricks(delayedTricks); const ids = d[1];
ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
arr.push(card_data);
});
box.addCustomCards(d[0], arr);
}
roomScene.popupBox.moveToCenter(); roomScene.popupBox.moveToCenter();
box.cardSelected.connect(function(cid){ box.cardSelected.connect(function(cid){
replyToServer(cid); replyToServer(cid);
@ -975,30 +975,9 @@ callbacks["AskForCardsChosen"] = (jsonData) => {
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks, // jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
// int min, int max, string reason ] // int min, int max, string reason ]
const data = JSON.parse(jsonData); const data = JSON.parse(jsonData);
const handcard_ids = data[0]; const min = data._min;
const equip_ids = data[1]; const max = data._max;
const delayedTrick_ids = data[2]; const reason = data._reason;
const min = data[3];
const max = data[4];
const reason = data[5];
const handcards = [];
const equips = [];
const delayedTricks = [];
handcard_ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
handcards.push(card_data);
});
equip_ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
equips.push(card_data);
});
delayedTrick_ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
delayedTricks.push(card_data);
});
roomScene.promptText = Backend.translate("#AskForChooseCards") roomScene.promptText = Backend.translate("#AskForChooseCards")
.arg(Backend.translate(reason)).arg(min).arg(max); .arg(Backend.translate(reason)).arg(min).arg(max);
@ -1008,9 +987,17 @@ callbacks["AskForCardsChosen"] = (jsonData) => {
box.multiChoose = true; box.multiChoose = true;
box.min = min; box.min = min;
box.max = max; box.max = max;
box.addHandcards(handcards); for (let d of data.card_data) {
box.addEquips(equips); const arr = [];
box.addDelayedTricks(delayedTricks); const ids = d[1];
ids.forEach(id => {
const card_data = JSON.parse(Backend.callLuaFunction("GetCardData", [id]));
arr.push(card_data);
});
box.addCustomCards(d[0], arr);
}
roomScene.popupBox.moveToCenter(); roomScene.popupBox.moveToCenter();
box.cardsSelected.connect((ids) => { box.cardsSelected.connect((ids) => {
replyToServer(JSON.stringify(ids)); replyToServer(JSON.stringify(ids));
@ -1295,12 +1282,38 @@ callbacks["LogEvent"] = (jsonData) => {
} }
case "PlaySkillSound": { case "PlaySkillSound": {
const skill = data.name; const skill = data.name;
let extension = data.extension; // let extension = data.extension;
if (!extension) { let extension;
const data = JSON.parse(Backend.callLuaFunction("GetSkillData", [skill])); let path;
extension = data.extension; let dat;
// try main general
if (data.general) {
dat = JSON.parse(Backend.callLuaFunction("GetGeneralData", [data.general]));
extension = dat.extension;
path = "./packages/" + extension + "/audio/skill/" + skill + "_" + data.general;
if (Backend.exists(path + ".mp3") || Backend.exists(path + "1.mp3")) {
Backend.playSound(path, data.i);
break;
}
} }
Backend.playSound("./packages/" + extension + "/audio/skill/" + skill, data.i);
// secondly try deputy general
if (data.deputy) {
dat = JSON.parse(Backend.callLuaFunction("GetGeneralData", [data.deputy]));
extension = dat.extension;
path = "./packages/" + extension + "/audio/skill/" + skill + "_" + data.deputy;
if (Backend.exists(path + ".mp3") || Backend.exists(path + "1.mp3")) {
Backend.playSound(path, data.i);
break;
}
}
// finally normal skill
dat = JSON.parse(Backend.callLuaFunction("GetSkillData", [skill]));
extension = dat.extension;
path = "./packages/" + extension + "/audio/skill/" + skill;
Backend.playSound(path, data.i);
break; break;
} }
case "PlaySound": { case "PlaySound": {

View File

@ -377,7 +377,8 @@ RowLayout {
function deactivateSkillButton() { function deactivateSkillButton() {
for (let i = 0; i < skillButtons.count; i++) { for (let i = 0; i < skillButtons.count; i++) {
skillButtons.itemAt(i).pressed = false; let item = skillButtons.itemAt(i);
item.pressed = false;
} }
} }

View File

@ -10,8 +10,8 @@ GraphicsBox {
title.text: root.multiChoose ? Backend.translate("$ChooseCards").arg(root.min).arg(root.max) : Backend.translate("$ChooseCard") title.text: root.multiChoose ? Backend.translate("$ChooseCards").arg(root.min).arg(root.max) : Backend.translate("$ChooseCard")
// TODO: Adjust the UI design in case there are more than 7 cards // TODO: Adjust the UI design in case there are more than 7 cards
width: 70 + Math.min(7, Math.max(1, handcards.count, equips.count, delayedTricks.count)) * 100 width: 70 + 700
height: 50 + (handcards.count > 0 ? 150 : 0) + (equips.count > 0 ? 150 : 0) + (delayedTricks.count > 0 ? 150 : 0) height: 50 + Math.min(cardView.contentHeight, 400) + (multiChoose ? 20 : 0)
signal cardSelected(int cid) signal cardSelected(int cid)
signal cardsSelected(var ids) signal cardsSelected(var ids)
@ -21,39 +21,35 @@ GraphicsBox {
property var selected_ids: [] property var selected_ids: []
ListModel { ListModel {
id: handcards id: cardModel
} }
ListModel { ListView {
id: equips id: cardView
}
ListModel {
id: delayedTricks
}
ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 40 anchors.topMargin: 40
anchors.leftMargin: 20 anchors.leftMargin: 20
anchors.rightMargin: 20 anchors.rightMargin: 20
anchors.bottomMargin: 20 anchors.bottomMargin: 20
spacing: 20
model: cardModel
clip: true
Row { delegate: RowLayout {
height: 130
spacing: 15 spacing: 15
visible: handcards.count > 0 visible: areaCards.count > 0
Rectangle { Rectangle {
border.color: "#A6967A" border.color: "#A6967A"
radius: 5 radius: 5
color: "transparent" color: "transparent"
width: 18 width: 18
height: parent.height height: 130
Layout.alignment: Qt.AlignTop
Text { Text {
color: "#E4D5A0" color: "#E4D5A0"
text: Backend.translate("$Hand") text: Backend.translate(areaName)
anchors.fill: parent anchors.fill: parent
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@ -62,10 +58,10 @@ GraphicsBox {
} }
} }
Row { GridLayout {
spacing: 7 columns: 7
Repeater { Repeater {
model: handcards model: areaCards
CardItem { CardItem {
cid: model.cid cid: model.cid
@ -82,147 +78,50 @@ GraphicsBox {
} }
onSelectedChanged: { onSelectedChanged: {
if (selected) { if (selected) {
origY = origY - 20; virt_name = "$Selected";
root.selected_ids.push(cid);
} else { } else {
origY = origY + 20; virt_name = "";
root.selected_ids.splice(root.selected_ids.indexOf(cid), 1);
} }
origX = x;
goBack(true);
root.selected_ids = root.selected_ids; root.selected_ids = root.selected_ids;
} }
} }
} }
} }
} }
}
Row { MetroButton {
height: 130 anchors.bottom: parent.bottom
spacing: 15 text: Backend.translate("OK")
visible: equips.count > 0 visible: root.multiChoose
enabled: root.selected_ids.length <= root.max && root.selected_ids.length >= root.min
Rectangle { onClicked: root.cardsSelected(root.selected_ids)
border.color: "#A6967A"
radius: 5
color: "transparent"
width: 18
height: parent.height
Text {
color: "#E4D5A0"
text: Backend.translate("$Equip")
anchors.fill: parent
wrapMode: Text.WrapAnywhere
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 15
}
}
Row {
spacing: 7
Repeater {
model: equips
CardItem {
cid: model.cid
name: model.name
suit: model.suit
number: model.number
autoBack: false
selectable: true
onClicked: {
if (!root.multiChoose) {
root.cardSelected(cid);
}
}
onSelectedChanged: {
if (selected) {
origY = origY - 20;
root.selected_ids.push(cid);
} else {
origY = origY + 20;
root.selected_ids.splice(root.selected_ids.indexOf(cid));
}
origX = x;
goBack(true);
root.selected_ids = root.selected_ids;
}
}
}
}
}
Row {
height: 130
spacing: 15
visible: delayedTricks.count > 0
Rectangle {
border.color: "#A6967A"
radius: 5
color: "transparent"
width: 18
height: parent.height
Text {
color: "#E4D5A0"
text: Backend.translate("$Judge")
anchors.fill: parent
wrapMode: Text.WrapAnywhere
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 15
}
}
Row {
spacing: 7
Repeater {
model: delayedTricks
CardItem {
cid: model.cid
name: model.name
suit: model.suit
number: model.number
autoBack: false
selectable: true
onClicked: {
if (!root.multiChoose) {
root.cardSelected(cid);
}
}
onSelectedChanged: {
if (selected) {
origY = origY - 20;
root.selected_ids.push(cid);
} else {
origY = origY + 20;
root.selected_ids.splice(root.selected_ids.indexOf(cid));
}
origX = x;
goBack(true);
root.selected_ids = root.selected_ids;
}
}
}
}
}
MetroButton {
text: Backend.translate("OK")
visible: root.multiChoose
enabled: root.selected_ids.length <= root.max && root.selected_ids.length >= root.min
onClicked: root.cardsSelected(root.selected_ids)
}
} }
onCardSelected: finished(); onCardSelected: finished();
function addHandcards(cards) function findAreaModel(name) {
{ let ret;
for (let i = 0; i < cardModel.count; i++) {
let item = cardModel.get(i);
if (item.areaName == name) {
ret = item;
break;
}
}
if (!ret) {
ret = {
areaName: name,
areaCards: [],
}
cardModel.append(ret);
ret = findAreaModel(name);
}
return ret;
}
function addHandcards(cards) {
let handcards = findAreaModel('$Hand').areaCards;
if (cards instanceof Array) { if (cards instanceof Array) {
for (let i = 0; i < cards.length; i++) for (let i = 0; i < cards.length; i++)
handcards.append(cards[i]); handcards.append(cards[i]);
@ -233,6 +132,7 @@ GraphicsBox {
function addEquips(cards) function addEquips(cards)
{ {
let equips = findAreaModel('$Equip').areaCards;
if (cards instanceof Array) { if (cards instanceof Array) {
for (let i = 0; i < cards.length; i++) for (let i = 0; i < cards.length; i++)
equips.append(cards[i]); equips.append(cards[i]);
@ -243,6 +143,7 @@ GraphicsBox {
function addDelayedTricks(cards) function addDelayedTricks(cards)
{ {
let delayedTricks = findAreaModel('$Judge').areaCards;
if (cards instanceof Array) { if (cards instanceof Array) {
for (let i = 0; i < cards.length; i++) for (let i = 0; i < cards.length; i++)
delayedTricks.append(cards[i]); delayedTricks.append(cards[i]);
@ -250,4 +151,14 @@ GraphicsBox {
delayedTricks.append(cards); delayedTricks.append(cards);
} }
} }
function addCustomCards(name, cards) {
let area = findAreaModel(name).areaCards;
if (cards instanceof Array) {
for (let i = 0; i < cards.length; i++)
area.append(cards[i]);
} else {
area.append(cards);
}
}
} }

View File

@ -132,7 +132,7 @@ function getRolePic(role) {
} else { } else {
for (let dir of Backend.ls(AppPath + "/packages/")) { for (let dir of Backend.ls(AppPath + "/packages/")) {
if (dir.endsWith(".disabled")) continue; if (dir.endsWith(".disabled")) continue;
path = AppPath + "/packages/" + dir + "/image/role/" + name + ".png"; path = AppPath + "/packages/" + dir + "/image/role/" + role + ".png";
if (Backend.exists(path)) return path; if (Backend.exists(path)) return path;
} }
} }

View File

@ -261,6 +261,10 @@ fk.client_callback["EnterRoom"] = function(jsonData)
local data = _data[3] local data = _data[3]
ClientInstance.enter_room_data = jsonData; ClientInstance.enter_room_data = jsonData;
ClientInstance.room_settings = data ClientInstance.room_settings = data
table.insertTableIfNeed(
data.disabledPack,
Fk.game_mode_disabled[data.gameMode]
)
ClientInstance.disabled_packs = data.disabledPack ClientInstance.disabled_packs = data.disabledPack
ClientInstance.disabled_generals = data.disabledGenerals ClientInstance.disabled_generals = data.disabledGenerals
ClientInstance:notifyUI("EnterRoom", jsonData) ClientInstance:notifyUI("EnterRoom", jsonData)
@ -371,19 +375,28 @@ fk.client_callback["AskForCardChosen"] = function(jsonData)
local hand = target.player_cards[Player.Hand] local hand = target.player_cards[Player.Hand]
local equip = target.player_cards[Player.Equip] local equip = target.player_cards[Player.Equip]
local judge = target.player_cards[Player.Judge] local judge = target.player_cards[Player.Judge]
if not string.find(flag, "h") then
hand = {} local ui_data = flag
elseif target.id ~= Self.id then if type(flag) == "string" then
-- FIXME: can not see other's handcard if not string.find(flag, "h") then
hand = table.map(hand, function() return -1 end) hand = {}
end
if not string.find(flag, "e") then
equip = {}
end
if not string.find(flag, "j") then
judge = {}
end
ui_data = {
_reason = reason,
card_data = {},
}
if #hand ~= 0 then table.insert(ui_data.card_data, { "$Hand", hand }) end
if #equip ~= 0 then table.insert(ui_data.card_data, { "$Equip", equip }) end
if #judge ~= 0 then table.insert(ui_data.card_data, { "$Judge", judge }) end
else
ui_data._reason = reason
end end
if not string.find(flag, "e") then
equip = {}
end
if not string.find(flag, "j") then
judge = {}
end
local ui_data = {hand, equip, judge, reason}
ClientInstance:notifyUI("AskForCardChosen", json.encode(ui_data)) ClientInstance:notifyUI("AskForCardChosen", json.encode(ui_data))
end end
@ -395,16 +408,32 @@ fk.client_callback["AskForCardsChosen"] = function(jsonData)
local hand = target.player_cards[Player.Hand] local hand = target.player_cards[Player.Hand]
local equip = target.player_cards[Player.Equip] local equip = target.player_cards[Player.Equip]
local judge = target.player_cards[Player.Judge] local judge = target.player_cards[Player.Judge]
if not string.find(flag, "h") then
hand = {} local ui_data = flag
if type(flag) == "string" then
if not string.find(flag, "h") then
hand = {}
end
if not string.find(flag, "e") then
equip = {}
end
if not string.find(flag, "j") then
judge = {}
end
ui_data = {
_min = min,
_max = max,
_reason = reason,
card_data = {}
}
if #hand ~= 0 then table.insert(ui_data.card_data, { "$Hand", hand }) end
if #equip ~= 0 then table.insert(ui_data.card_data, { "$Equip", equip }) end
if #judge ~= 0 then table.insert(ui_data.card_data, { "$Judge", judge }) end
else
ui_data._min = min
ui_data._max = max
ui_data._reason = reason
end end
if not string.find(flag, "e") then
equip = {}
end
if not string.find(flag, "j") then
judge = {}
end
local ui_data = {hand, equip, judge, min, max, reason}
ClientInstance:notifyUI("AskForCardsChosen", json.encode(ui_data)) ClientInstance:notifyUI("AskForCardsChosen", json.encode(ui_data))
end end

View File

@ -224,6 +224,7 @@ FreeKill使用的是libgit2的C API与此同时使用Git完成拓展包的下
["$Hand"] = "手牌区", ["$Hand"] = "手牌区",
["$Equip"] = "装备区", ["$Equip"] = "装备区",
["$Judge"] = "判定区", ["$Judge"] = "判定区",
['$Selected'] = "已选择",
["#AskForUseActiveSkill"] = "请使用技能 %1", ["#AskForUseActiveSkill"] = "请使用技能 %1",
["#AskForUseCard"] = "请使用卡牌 %1", ["#AskForUseCard"] = "请使用卡牌 %1",
["#AskForResponseCard"] = "请打出卡牌 %1", ["#AskForResponseCard"] = "请打出卡牌 %1",

View File

@ -143,8 +143,6 @@ function Card:clone(suit, number)
local newCard = self.class:new(self.name, suit, number) local newCard = self.class:new(self.name, suit, number)
newCard.skill = self.skill newCard.skill = self.skill
newCard.special_skills = self.special_skills newCard.special_skills = self.special_skills
newCard.equip_skill = self.equip_skill
newCard.attack_range = self.attack_range
newCard.is_damage_card = self.is_damage_card newCard.is_damage_card = self.is_damage_card
newCard.multiple_targets = self.multiple_targets newCard.multiple_targets = self.multiple_targets
newCard.is_derived = self.is_derived newCard.is_derived = self.is_derived

View File

@ -26,7 +26,16 @@ function EquipCard:onUninstall(room, player)
end end
end end
function EquipCard:clone(suit, number)
local ret = Card.clone(self, suit, number)
ret.equip_skill = self.equip_skill
ret.onInstall = self.onInstall
ret.onUninstall = self.onUninstall
return ret
end
---@class Weapon : EquipCard ---@class Weapon : EquipCard
---@field public attack_range integer
local Weapon = EquipCard:subclass("Weapon") local Weapon = EquipCard:subclass("Weapon")
function Weapon:initialize(name, suit, number, attackRange) function Weapon:initialize(name, suit, number, attackRange)
@ -35,6 +44,12 @@ function Weapon:initialize(name, suit, number, attackRange)
self.attack_range = attackRange or 1 self.attack_range = attackRange or 1
end end
function Weapon:clone(suit, number)
local ret = EquipCard.clone(self, suit, number)
ret.attack_range = self.attack_range
return ret
end
---@class Armor : EquipCard ---@class Armor : EquipCard
local Armor = EquipCard:subclass("armor") local Armor = EquipCard:subclass("armor")

View File

@ -24,6 +24,7 @@
---@field public currentResponseReason string @ 要求用牌的原因(如濒死,被特定牌指定,使用特定技能···) ---@field public currentResponseReason string @ 要求用牌的原因(如濒死,被特定牌指定,使用特定技能···)
---@field public filtered_cards table<integer, Card> @ 被锁视技影响的卡牌 ---@field public filtered_cards table<integer, Card> @ 被锁视技影响的卡牌
---@field public printed_cards table<integer, Card> @ 被某些房间现场打印的卡牌id都是负数且从-2开始 ---@field public printed_cards table<integer, Card> @ 被某些房间现场打印的卡牌id都是负数且从-2开始
---@field private _custom_events any[] @ 自定义事件列表
local Engine = class("Engine") local Engine = class("Engine")
--- Engine的构造函数。 --- Engine的构造函数。
@ -53,6 +54,7 @@ function Engine:initialize()
self.game_modes = {} self.game_modes = {}
self.game_mode_disabled = {} self.game_mode_disabled = {}
self.kingdoms = {} self.kingdoms = {}
self._custom_events = {}
self:loadPackages() self:loadPackages()
self:loadDisabled() self:loadDisabled()
@ -247,8 +249,10 @@ end
local function canUseGeneral(g) local function canUseGeneral(g)
local r = Fk:currentRoom() local r = Fk:currentRoom()
return not table.contains(r.disabled_packs, Fk.generals[g].package.name) and local general = Fk.generals[g]
not table.contains(r.disabled_generals, g) and not g.hidden and not g.total_hidden if not general then return false end
return not table.contains(r.disabled_packs, general.package.name) and
not table.contains(r.disabled_generals, g) and not general.hidden and not general.total_hidden
end end
--- 根据武将名称,获取它的同名武将。 --- 根据武将名称,获取它的同名武将。
@ -323,6 +327,10 @@ function Engine:addGameMode(game_mode)
self.game_modes[game_mode.name] = game_mode self.game_modes[game_mode.name] = game_mode
end end
function Engine:addGameEvent(name, pfunc, mfunc, cfunc, efunc)
table.insert(self._custom_events, { name = name, p = pfunc, m = mfunc, c = cfunc, e = efunc })
end
--- 从已经开启的拓展包中,随机选出若干名武将。 --- 从已经开启的拓展包中,随机选出若干名武将。
--- ---
--- 对于同名武将不会重复选取。 --- 对于同名武将不会重复选取。
@ -440,7 +448,7 @@ function Engine:filterCard(id, player, data)
_card.skillName = f.name _card.skillName = f.name
if modify and RoomInstance then if modify and RoomInstance then
if not f.mute then if not f.mute then
RoomInstance:broadcastSkillInvoke(f.name) player:broadcastSkillInvoke(f.name)
end end
RoomInstance:doAnimate("InvokeSkill", { RoomInstance:doAnimate("InvokeSkill", {
name = f.name, name = f.name,

View File

@ -44,6 +44,14 @@ dofile "lua/server/events/pindian.lua"
-- TODO: fix this -- TODO: fix this
GameEvent.BreakEvent = 999 GameEvent.BreakEvent = 999
for _, l in ipairs(Fk._custom_events) do
local name, p, m, c, e = l.name, l.p, l.m, l.c, l.e
GameEvent.prepare_funcs[name] = p
GameEvent.functions[name] = m
GameEvent.cleaners[name] = c
GameEvent.exit_funcs[name] = e
end
local eventTranslations = { local eventTranslations = {
[GameEvent.ChangeHp] = "GameEvent.ChangeHp", [GameEvent.ChangeHp] = "GameEvent.ChangeHp",
[GameEvent.Damage] = "GameEvent.Damage", [GameEvent.Damage] = "GameEvent.Damage",
@ -68,5 +76,7 @@ local eventTranslations = {
} }
function GameEvent.static:translate(id) function GameEvent.static:translate(id)
return eventTranslations[id] local ret = eventTranslations[id]
if not ret then ret = id end
return ret
end end

View File

@ -187,7 +187,7 @@ function GameEvent:clear()
local logic = RoomInstance.logic local logic = RoomInstance.logic
local end_id = logic.current_event_id + 1 local end_id = logic.current_event_id + 1
if self.id ~= end_id - 1 then if self.id ~= end_id - 1 then
logic.all_game_events[end_id] = -self.event logic.all_game_events[end_id] = self.event
logic.current_event_id = end_id logic.current_event_id = end_id
self.end_id = end_id self.end_id = end_id
else else

View File

@ -494,7 +494,7 @@ function GameLogic:dumpAllEvents(from, to)
local tab = " " local tab = " "
for i = from, to, 1 do for i = from, to, 1 do
local v = self.all_game_events[i] local v = self.all_game_events[i]
if type(v) == "number" then if type(v) ~= "table" then
indent = math.max(indent - 1, 0) indent = math.max(indent - 1, 0)
-- v = "End" -- v = "End"
-- print(tab:rep(indent) .. string.format("#%d: %s", i, v)) -- print(tab:rep(indent) .. string.format("#%d: %s", i, v))

View File

@ -934,9 +934,10 @@ function Room:sendLogEvent(type, data, players)
end end
--- 播放技能的语音。 --- 播放技能的语音。
---@param skill_name string @ 技能名 ---@param skill_name nil @ 技能名
---@param index integer | nil @ 语音编号,默认为-1也就是随机播放 ---@param index integer | nil @ 语音编号,默认为-1也就是随机播放
function Room:broadcastSkillInvoke(skill_name, index) function Room:broadcastSkillInvoke(skill_name, index)
print 'Room:broadcastSkillInvoke deprecated; use SPlayer:broadcastSkillInvoke'
index = index or -1 index = index or -1
self:sendLogEvent("PlaySkillSound", { self:sendLogEvent("PlaySkillSound", {
name = skill_name, name = skill_name,
@ -1361,7 +1362,7 @@ end
--- 询问chooser选择target的一张牌。 --- 询问chooser选择target的一张牌。
---@param chooser ServerPlayer @ 要被询问的人 ---@param chooser ServerPlayer @ 要被询问的人
---@param target ServerPlayer @ 被选牌的人 ---@param target ServerPlayer @ 被选牌的人
---@param flag string @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区 ---@param flag any @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区
---@param reason string @ 原因,一般是技能名 ---@param reason string @ 原因,一般是技能名
---@return integer @ 选择的卡牌id ---@return integer @ 选择的卡牌id
function Room:askForCardChosen(chooser, target, flag, reason) function Room:askForCardChosen(chooser, target, flag, reason)
@ -1372,10 +1373,18 @@ function Room:askForCardChosen(chooser, target, flag, reason)
if result == "" then if result == "" then
local areas = {} local areas = {}
if string.find(flag, "h") then table.insert(areas, Player.Hand) end local handcards
if string.find(flag, "e") then table.insert(areas, Player.Equip) end if type(flag) == "string" then
if string.find(flag, "j") then table.insert(areas, Player.Judge) end if string.find(flag, "h") then table.insert(areas, Player.Hand) end
local handcards = target:getCardIds(areas) if string.find(flag, "e") then table.insert(areas, Player.Equip) end
if string.find(flag, "j") then table.insert(areas, Player.Judge) end
handcards = target:getCardIds(areas)
else
handcards = {}
for _, t in ipairs(flag.card_data) do
table.insertTable(handcards, t[2])
end
end
if #handcards == 0 then return end if #handcards == 0 then return end
result = handcards[math.random(1, #handcards)] result = handcards[math.random(1, #handcards)]
else else
@ -1397,7 +1406,7 @@ end
---@param target ServerPlayer @ 被选牌的人 ---@param target ServerPlayer @ 被选牌的人
---@param min integer @ 最小选牌数 ---@param min integer @ 最小选牌数
---@param max integer @ 最大选牌数 ---@param max integer @ 最大选牌数
---@param flag string @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区 ---@param flag any @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区
---@param reason string @ 原因,一般是技能名 ---@param reason string @ 原因,一般是技能名
---@return integer[] @ 选择的id ---@return integer[] @ 选择的id
function Room:askForCardsChosen(chooser, target, min, max, flag, reason) function Room:askForCardsChosen(chooser, target, min, max, flag, reason)
@ -1415,10 +1424,18 @@ function Room:askForCardsChosen(chooser, target, min, max, flag, reason)
ret = json.decode(result) ret = json.decode(result)
else else
local areas = {} local areas = {}
if string.find(flag, "h") then table.insert(areas, Player.Hand) end local handcards
if string.find(flag, "e") then table.insert(areas, Player.Equip) end if type(flag) == "string" then
if string.find(flag, "j") then table.insert(areas, Player.Judge) end if string.find(flag, "h") then table.insert(areas, Player.Hand) end
local handcards = target:getCardIds(areas) if string.find(flag, "e") then table.insert(areas, Player.Equip) end
if string.find(flag, "j") then table.insert(areas, Player.Judge) end
handcards = target:getCardIds(areas)
else
handcards = {}
for _, t in ipairs(flag.card_data) do
table.insertTable(handcards, t[2])
end
end
if #handcards == 0 then return {} end if #handcards == 0 then return {} end
ret = table.random(handcards, math.min(min, #handcards)) ret = table.random(handcards, math.min(min, #handcards))
end end
@ -3020,7 +3037,7 @@ function Room:useSkill(player, skill, effect_cb)
self:broadcastPlaySound(soundName) self:broadcastPlaySound(soundName)
self:setEmotion(player, pkgPath .. "/image/anim/" .. equip.name) self:setEmotion(player, pkgPath .. "/image/anim/" .. equip.name)
else else
self:broadcastSkillInvoke(skill.name) player:broadcastSkillInvoke(skill.name)
self:notifySkillInvoked(player, skill.name) self:notifySkillInvoked(player, skill.name)
end end
end end

View File

@ -716,6 +716,20 @@ function ServerPlayer:pindian(tos, skillName, initialCard)
return pindianData return pindianData
end end
--- 播放技能的语音。
---@param skill_name string @ 技能名
---@param index integer | nil @ 语音编号,默认为-1也就是随机播放
function ServerPlayer:broadcastSkillInvoke(skill_name, index)
print 'Room:broadcastSkillInvoke deprecated; use SPlayer:broadcastSkillInvoke'
index = index or -1
self.room:sendLogEvent("PlaySkillSound", {
name = skill_name,
i = index,
general = self.general,
deputy = self.deputyGeneral,
})
end
-- Hegemony func -- Hegemony func
---@param skill Skill ---@param skill Skill

View File

@ -231,7 +231,7 @@ local luoyi_trigger = fk.CreateTriggerSkill{
end, end,
on_use = function(self, event, target, player, data) on_use = function(self, event, target, player, data)
local room = player.room local room = player.room
room:broadcastSkillInvoke("luoyi") player:broadcastSkillInvoke("luoyi")
room:notifySkillInvoked(player, "luoyi") room:notifySkillInvoked(player, "luoyi")
data.damage = data.damage + 1 data.damage = data.damage + 1
end, end,
@ -540,7 +540,7 @@ local paoxiaoAudio = fk.CreateTriggerSkill{
player:usedCardTimes("slash") > 1 player:usedCardTimes("slash") > 1
end, end,
on_refresh = function(self, event, target, player, data) on_refresh = function(self, event, target, player, data)
player.room:broadcastSkillInvoke("paoxiao") player:broadcastSkillInvoke("paoxiao")
player.room:doAnimate("InvokeSkill", { player.room:doAnimate("InvokeSkill", {
name = "paoxiao", name = "paoxiao",
player = player.id, player = player.id,
@ -592,7 +592,7 @@ local kongchengAudio = fk.CreateTriggerSkill{
end end
end, end,
on_refresh = function(self, event, target, player, data) on_refresh = function(self, event, target, player, data)
player.room:broadcastSkillInvoke("kongcheng") player:broadcastSkillInvoke("kongcheng")
player.room:notifySkillInvoked(player, "kongcheng", "defensive") player.room:notifySkillInvoked(player, "kongcheng", "defensive")
end, end,
} }