diff --git a/Fk/LobbyElement/RoomGeneralSettings.qml b/Fk/LobbyElement/RoomGeneralSettings.qml index f2086805..73f332be 100644 --- a/Fk/LobbyElement/RoomGeneralSettings.qml +++ b/Fk/LobbyElement/RoomGeneralSettings.qml @@ -88,7 +88,7 @@ Flickable { id: warning anchors.rightMargin: 8 visible: { - config.disabledPack; // 没什么用,只是为了禁包刷新时刷新visible罢了 + //config.disabledPack; // 没什么用,只是为了禁包刷新时刷新visible罢了 const avail = JSON.parse(Backend.callLuaFunction("GetAvailableGeneralsNum", [])); const ret = avail < config.preferredGeneralNum * config.preferedPlayerNum; return ret; diff --git a/Fk/Pages/RoomLogic.js b/Fk/Pages/RoomLogic.js index f4b4280a..a9d50b69 100644 --- a/Fk/Pages/RoomLogic.js +++ b/Fk/Pages/RoomLogic.js @@ -94,13 +94,19 @@ function doOkButton() { replyToServer("1"); } +let _is_canceling = false; function doCancelButton() { + if (_is_canceling) return; + _is_canceling = true; + if (roomScene.state === "playing") { dashboard.stopPending(); dashboard.deactivateSkillButton(); dashboard.unSelectAll(); dashboard.enableCards(); dashboard.enableSkills(); + + _is_canceling = false; return; } else if (roomScene.state === "responding") { const p = dashboard.pending_skill; @@ -113,6 +119,8 @@ function doCancelButton() { dashboard.enableCards(roomScene.responding_card); dashboard.enableSkills(roomScene.responding_card); } + + _is_canceling = false; return; } @@ -121,9 +129,13 @@ function doCancelButton() { "luckcard", false ].join(",")); roomScene.state = "notactive"; + + _is_canceling = false; return; } + replyToServer("__cancel"); + _is_canceling = false; } function replyToServer(jsonData) { @@ -934,37 +946,25 @@ callbacks["AskForCardChosen"] = (jsonData) => { // jsonData: [ int[] handcards, int[] equips, int[] delayedtricks, // string reason ] const data = JSON.parse(jsonData); - const handcard_ids = data[0]; - 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); - }); + const reason = data._reason; roomScene.promptText = Backend.translate("#AskForChooseCard") .arg(Backend.translate(reason)); roomScene.state = "replying"; roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/PlayerCardBox.qml"); + const box = roomScene.popupBox.item; - box.addHandcards(handcards); - box.addEquips(equips); - box.addDelayedTricks(delayedTricks); + for (let d of data.card_data) { + const arr = []; + 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(); box.cardSelected.connect(function(cid){ replyToServer(cid); @@ -975,30 +975,9 @@ callbacks["AskForCardsChosen"] = (jsonData) => { // jsonData: [ int[] handcards, int[] equips, int[] delayedtricks, // int min, int max, string reason ] const data = JSON.parse(jsonData); - const handcard_ids = data[0]; - const equip_ids = data[1]; - const delayedTrick_ids = data[2]; - 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); - }); + const min = data._min; + const max = data._max; + const reason = data._reason; roomScene.promptText = Backend.translate("#AskForChooseCards") .arg(Backend.translate(reason)).arg(min).arg(max); @@ -1008,9 +987,17 @@ callbacks["AskForCardsChosen"] = (jsonData) => { box.multiChoose = true; box.min = min; box.max = max; - box.addHandcards(handcards); - box.addEquips(equips); - box.addDelayedTricks(delayedTricks); + for (let d of data.card_data) { + const arr = []; + 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(); box.cardsSelected.connect((ids) => { replyToServer(JSON.stringify(ids)); @@ -1295,12 +1282,38 @@ callbacks["LogEvent"] = (jsonData) => { } case "PlaySkillSound": { const skill = data.name; - let extension = data.extension; - if (!extension) { - const data = JSON.parse(Backend.callLuaFunction("GetSkillData", [skill])); - extension = data.extension; + // let extension = data.extension; + let extension; + let path; + 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; } case "PlaySound": { diff --git a/Fk/RoomElement/Dashboard.qml b/Fk/RoomElement/Dashboard.qml index 5729b96b..2158a9eb 100644 --- a/Fk/RoomElement/Dashboard.qml +++ b/Fk/RoomElement/Dashboard.qml @@ -377,7 +377,8 @@ RowLayout { function deactivateSkillButton() { for (let i = 0; i < skillButtons.count; i++) { - skillButtons.itemAt(i).pressed = false; + let item = skillButtons.itemAt(i); + item.pressed = false; } } diff --git a/Fk/RoomElement/PlayerCardBox.qml b/Fk/RoomElement/PlayerCardBox.qml index 2e635ad8..833e7999 100644 --- a/Fk/RoomElement/PlayerCardBox.qml +++ b/Fk/RoomElement/PlayerCardBox.qml @@ -10,8 +10,8 @@ GraphicsBox { 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 - width: 70 + Math.min(7, Math.max(1, handcards.count, equips.count, delayedTricks.count)) * 100 - height: 50 + (handcards.count > 0 ? 150 : 0) + (equips.count > 0 ? 150 : 0) + (delayedTricks.count > 0 ? 150 : 0) + width: 70 + 700 + height: 50 + Math.min(cardView.contentHeight, 400) + (multiChoose ? 20 : 0) signal cardSelected(int cid) signal cardsSelected(var ids) @@ -21,39 +21,35 @@ GraphicsBox { property var selected_ids: [] ListModel { - id: handcards + id: cardModel } - ListModel { - id: equips - } - - ListModel { - id: delayedTricks - } - - ColumnLayout { + ListView { + id: cardView anchors.fill: parent anchors.topMargin: 40 anchors.leftMargin: 20 anchors.rightMargin: 20 anchors.bottomMargin: 20 + spacing: 20 + model: cardModel + clip: true - Row { - height: 130 + delegate: RowLayout { spacing: 15 - visible: handcards.count > 0 + visible: areaCards.count > 0 Rectangle { border.color: "#A6967A" radius: 5 color: "transparent" width: 18 - height: parent.height + height: 130 + Layout.alignment: Qt.AlignTop Text { color: "#E4D5A0" - text: Backend.translate("$Hand") + text: Backend.translate(areaName) anchors.fill: parent wrapMode: Text.WrapAnywhere verticalAlignment: Text.AlignVCenter @@ -62,10 +58,10 @@ GraphicsBox { } } - Row { - spacing: 7 + GridLayout { + columns: 7 Repeater { - model: handcards + model: areaCards CardItem { cid: model.cid @@ -82,147 +78,50 @@ GraphicsBox { } onSelectedChanged: { if (selected) { - origY = origY - 20; - root.selected_ids.push(cid); + virt_name = "$Selected"; } else { - origY = origY + 20; - root.selected_ids.splice(root.selected_ids.indexOf(cid), 1); + virt_name = ""; } - origX = x; - goBack(true); root.selected_ids = root.selected_ids; } } } } } + } - Row { - height: 130 - spacing: 15 - visible: equips.count > 0 - - Rectangle { - 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) - } + MetroButton { + anchors.bottom: parent.bottom + 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(); - 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) { for (let i = 0; i < cards.length; i++) handcards.append(cards[i]); @@ -233,6 +132,7 @@ GraphicsBox { function addEquips(cards) { + let equips = findAreaModel('$Equip').areaCards; if (cards instanceof Array) { for (let i = 0; i < cards.length; i++) equips.append(cards[i]); @@ -243,6 +143,7 @@ GraphicsBox { function addDelayedTricks(cards) { + let delayedTricks = findAreaModel('$Judge').areaCards; if (cards instanceof Array) { for (let i = 0; i < cards.length; i++) delayedTricks.append(cards[i]); @@ -250,4 +151,14 @@ GraphicsBox { 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); + } + } } diff --git a/Fk/skin-bank.js b/Fk/skin-bank.js index 398ffff6..5360de46 100644 --- a/Fk/skin-bank.js +++ b/Fk/skin-bank.js @@ -132,7 +132,7 @@ function getRolePic(role) { } else { for (let dir of Backend.ls(AppPath + "/packages/")) { 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; } } diff --git a/lua/client/client.lua b/lua/client/client.lua index 39a4523b..b2668ba1 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -261,6 +261,10 @@ fk.client_callback["EnterRoom"] = function(jsonData) local data = _data[3] ClientInstance.enter_room_data = jsonData; ClientInstance.room_settings = data + table.insertTableIfNeed( + data.disabledPack, + Fk.game_mode_disabled[data.gameMode] + ) ClientInstance.disabled_packs = data.disabledPack ClientInstance.disabled_generals = data.disabledGenerals ClientInstance:notifyUI("EnterRoom", jsonData) @@ -371,19 +375,28 @@ fk.client_callback["AskForCardChosen"] = function(jsonData) local hand = target.player_cards[Player.Hand] local equip = target.player_cards[Player.Equip] local judge = target.player_cards[Player.Judge] - if not string.find(flag, "h") then - hand = {} - elseif target.id ~= Self.id then - -- FIXME: can not see other's handcard - hand = table.map(hand, function() return -1 end) + + 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 = { + _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 - 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)) end @@ -395,16 +408,32 @@ fk.client_callback["AskForCardsChosen"] = function(jsonData) local hand = target.player_cards[Player.Hand] local equip = target.player_cards[Player.Equip] 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 - 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)) end diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua index 3857a895..07ced9dd 100644 --- a/lua/client/i18n/zh_CN.lua +++ b/lua/client/i18n/zh_CN.lua @@ -224,6 +224,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下 ["$Hand"] = "手牌区", ["$Equip"] = "装备区", ["$Judge"] = "判定区", + ['$Selected'] = "已选择", ["#AskForUseActiveSkill"] = "请使用技能 %1", ["#AskForUseCard"] = "请使用卡牌 %1", ["#AskForResponseCard"] = "请打出卡牌 %1", diff --git a/lua/core/card.lua b/lua/core/card.lua index bec6be3c..42eac902 100644 --- a/lua/core/card.lua +++ b/lua/core/card.lua @@ -143,8 +143,6 @@ function Card:clone(suit, number) local newCard = self.class:new(self.name, suit, number) newCard.skill = self.skill 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.multiple_targets = self.multiple_targets newCard.is_derived = self.is_derived diff --git a/lua/core/card_type/equip.lua b/lua/core/card_type/equip.lua index c3491d89..3fdacb4f 100644 --- a/lua/core/card_type/equip.lua +++ b/lua/core/card_type/equip.lua @@ -26,7 +26,16 @@ function EquipCard:onUninstall(room, player) 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 +---@field public attack_range integer local Weapon = EquipCard:subclass("Weapon") function Weapon:initialize(name, suit, number, attackRange) @@ -35,6 +44,12 @@ function Weapon:initialize(name, suit, number, attackRange) self.attack_range = attackRange or 1 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 local Armor = EquipCard:subclass("armor") diff --git a/lua/core/engine.lua b/lua/core/engine.lua index c3c0246a..a66d14a6 100644 --- a/lua/core/engine.lua +++ b/lua/core/engine.lua @@ -24,6 +24,7 @@ ---@field public currentResponseReason string @ 要求用牌的原因(如濒死,被特定牌指定,使用特定技能···) ---@field public filtered_cards table @ 被锁视技影响的卡牌 ---@field public printed_cards table @ 被某些房间现场打印的卡牌,id都是负数且从-2开始 +---@field private _custom_events any[] @ 自定义事件列表 local Engine = class("Engine") --- Engine的构造函数。 @@ -53,6 +54,7 @@ function Engine:initialize() self.game_modes = {} self.game_mode_disabled = {} self.kingdoms = {} + self._custom_events = {} self:loadPackages() self:loadDisabled() @@ -247,8 +249,10 @@ end local function canUseGeneral(g) local r = Fk:currentRoom() - return not table.contains(r.disabled_packs, Fk.generals[g].package.name) and - not table.contains(r.disabled_generals, g) and not g.hidden and not g.total_hidden + local general = Fk.generals[g] + 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 --- 根据武将名称,获取它的同名武将。 @@ -323,6 +327,10 @@ function Engine:addGameMode(game_mode) self.game_modes[game_mode.name] = game_mode 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 if modify and RoomInstance then if not f.mute then - RoomInstance:broadcastSkillInvoke(f.name) + player:broadcastSkillInvoke(f.name) end RoomInstance:doAnimate("InvokeSkill", { name = f.name, diff --git a/lua/server/events/init.lua b/lua/server/events/init.lua index 139727e6..2280a603 100644 --- a/lua/server/events/init.lua +++ b/lua/server/events/init.lua @@ -44,6 +44,14 @@ dofile "lua/server/events/pindian.lua" -- TODO: fix this 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 = { [GameEvent.ChangeHp] = "GameEvent.ChangeHp", [GameEvent.Damage] = "GameEvent.Damage", @@ -68,5 +76,7 @@ local eventTranslations = { } function GameEvent.static:translate(id) - return eventTranslations[id] + local ret = eventTranslations[id] + if not ret then ret = id end + return ret end diff --git a/lua/server/gameevent.lua b/lua/server/gameevent.lua index 27f7883d..61e4cfbe 100644 --- a/lua/server/gameevent.lua +++ b/lua/server/gameevent.lua @@ -187,7 +187,7 @@ function GameEvent:clear() local logic = RoomInstance.logic local end_id = logic.current_event_id + 1 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 self.end_id = end_id else diff --git a/lua/server/gamelogic.lua b/lua/server/gamelogic.lua index 50d86cad..31d0e44a 100644 --- a/lua/server/gamelogic.lua +++ b/lua/server/gamelogic.lua @@ -494,7 +494,7 @@ function GameLogic:dumpAllEvents(from, to) local tab = " " for i = from, to, 1 do local v = self.all_game_events[i] - if type(v) == "number" then + if type(v) ~= "table" then indent = math.max(indent - 1, 0) -- v = "End" -- print(tab:rep(indent) .. string.format("#%d: %s", i, v)) diff --git a/lua/server/room.lua b/lua/server/room.lua index 5a2242ba..e8d8d274 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -934,9 +934,10 @@ function Room:sendLogEvent(type, data, players) end --- 播放技能的语音。 ----@param skill_name string @ 技能名 +---@param skill_name nil @ 技能名 ---@param index integer | nil @ 语音编号,默认为-1(也就是随机播放) function Room:broadcastSkillInvoke(skill_name, index) + print 'Room:broadcastSkillInvoke deprecated; use SPlayer:broadcastSkillInvoke' index = index or -1 self:sendLogEvent("PlaySkillSound", { name = skill_name, @@ -1361,7 +1362,7 @@ end --- 询问chooser,选择target的一张牌。 ---@param chooser ServerPlayer @ 要被询问的人 ---@param target ServerPlayer @ 被选牌的人 ----@param flag string @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区 +---@param flag any @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区 ---@param reason string @ 原因,一般是技能名 ---@return integer @ 选择的卡牌id function Room:askForCardChosen(chooser, target, flag, reason) @@ -1372,10 +1373,18 @@ function Room:askForCardChosen(chooser, target, flag, reason) if result == "" then local areas = {} - if string.find(flag, "h") then table.insert(areas, Player.Hand) end - if string.find(flag, "e") then table.insert(areas, Player.Equip) end - if string.find(flag, "j") then table.insert(areas, Player.Judge) end - local handcards = target:getCardIds(areas) + local handcards + if type(flag) == "string" then + if string.find(flag, "h") then table.insert(areas, Player.Hand) end + 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 result = handcards[math.random(1, #handcards)] else @@ -1397,7 +1406,7 @@ end ---@param target ServerPlayer @ 被选牌的人 ---@param min integer @ 最小选牌数 ---@param max integer @ 最大选牌数 ----@param flag string @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区 +---@param flag any @ 用"hej"三个字母的组合表示能选择哪些区域, h 手牌区, e - 装备区, j - 判定区 ---@param reason string @ 原因,一般是技能名 ---@return integer[] @ 选择的id 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) else local areas = {} - if string.find(flag, "h") then table.insert(areas, Player.Hand) end - if string.find(flag, "e") then table.insert(areas, Player.Equip) end - if string.find(flag, "j") then table.insert(areas, Player.Judge) end - local handcards = target:getCardIds(areas) + local handcards + if type(flag) == "string" then + if string.find(flag, "h") then table.insert(areas, Player.Hand) end + 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 ret = table.random(handcards, math.min(min, #handcards)) end @@ -3020,7 +3037,7 @@ function Room:useSkill(player, skill, effect_cb) self:broadcastPlaySound(soundName) self:setEmotion(player, pkgPath .. "/image/anim/" .. equip.name) else - self:broadcastSkillInvoke(skill.name) + player:broadcastSkillInvoke(skill.name) self:notifySkillInvoked(player, skill.name) end end diff --git a/lua/server/serverplayer.lua b/lua/server/serverplayer.lua index aa6285dd..a93cb731 100644 --- a/lua/server/serverplayer.lua +++ b/lua/server/serverplayer.lua @@ -716,6 +716,20 @@ function ServerPlayer:pindian(tos, skillName, initialCard) return pindianData 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 ---@param skill Skill diff --git a/packages/standard/init.lua b/packages/standard/init.lua index 2fd63a33..412a6b75 100644 --- a/packages/standard/init.lua +++ b/packages/standard/init.lua @@ -231,7 +231,7 @@ local luoyi_trigger = fk.CreateTriggerSkill{ end, on_use = function(self, event, target, player, data) local room = player.room - room:broadcastSkillInvoke("luoyi") + player:broadcastSkillInvoke("luoyi") room:notifySkillInvoked(player, "luoyi") data.damage = data.damage + 1 end, @@ -540,7 +540,7 @@ local paoxiaoAudio = fk.CreateTriggerSkill{ player:usedCardTimes("slash") > 1 end, on_refresh = function(self, event, target, player, data) - player.room:broadcastSkillInvoke("paoxiao") + player:broadcastSkillInvoke("paoxiao") player.room:doAnimate("InvokeSkill", { name = "paoxiao", player = player.id, @@ -592,7 +592,7 @@ local kongchengAudio = fk.CreateTriggerSkill{ end end, on_refresh = function(self, event, target, player, data) - player.room:broadcastSkillInvoke("kongcheng") + player:broadcastSkillInvoke("kongcheng") player.room:notifySkillInvoked(player, "kongcheng", "defensive") end, }