diff --git a/audio/system/chain.mp3 b/audio/system/chain.mp3 new file mode 100644 index 00000000..2dc29409 Binary files /dev/null and b/audio/system/chain.mp3 differ diff --git a/lua/server/room.lua b/lua/server/room.lua index ddce55c0..4bbeb212 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -777,15 +777,6 @@ function Room:notifyMoveCards(players, card_moves, forceVisible) for _, move in ipairs(arg) do -- local to = self:getPlayerById(move.to) - local function infosContainArea(info, area) - for _, i in ipairs(info) do - if i.fromArea == area then - return true - end - end - return false - end - for _, info in ipairs(move.moveInfo) do local realFromArea = self:getCardArea(info.cardId) local playerAreas = { Player.Hand, Player.Equip, Player.Judge, Player.Special } @@ -800,28 +791,25 @@ function Room:notifyMoveCards(players, card_moves, forceVisible) end end - -- forceVisible make the move visible - -- FIXME: move.moveInfo is an array, fix this - move.moveVisible = move.moveVisible or (forceVisible) - -- if move is relevant to player, it should be open - or ((move.from == p.id) or (move.to == p.id)) - -- cards move from/to equip/judge/discard/processing should be open - or infosContainArea(move.moveInfo, Card.PlayerEquip) - or move.toArea == Card.PlayerEquip - or infosContainArea(move.moveInfo, Card.PlayerJudge) - or move.toArea == Card.PlayerJudge - or infosContainArea(move.moveInfo, Card.DiscardPile) - or move.toArea == Card.DiscardPile - or infosContainArea(move.moveInfo, Card.Processing) - or move.toArea == Card.Processing - -- TODO: PlayerSpecial + local function containArea(area, relevant) --处理区的处理? + local areas = relevant + and {Card.PlayerEquip, Card.PlayerJudge, Card.DiscardPile, Card.Processing, Card.PlayerHand} + or {Card.PlayerEquip, Card.PlayerJudge, Card.DiscardPile, Card.Processing} + return table.contains(areas, area) + end - if not move.moveVisible then + -- forceVisible make the move visible + -- if move is relevant to player's hands or equips, it should be open + -- cards move from/to equip/judge/discard/processing should be open + + if not (move.moveVisible or forceVisible or containArea(move.toArea, move.to == p.id)) then for _, info in ipairs(move.moveInfo) do + if not containArea(info.fromArea, move.from == p.id) then info.cardId = -1 end end end + end p:doNotify("MoveCards", json.encode(arg)) end end @@ -2580,7 +2568,7 @@ function Room:drawCards(player, num, skillName, fromPlace) skillName = skillName, fromPlace = fromPlace, } - if self.logic:trigger(fk.BeforeDrawCard, player, drawData) or drawData.num < 1 then + if self.logic:trigger(fk.BeforeDrawCard, player, drawData) then self.logic:breakEvent(false) end diff --git a/lua/server/serverplayer.lua b/lua/server/serverplayer.lua index dbe2cdf1..3b04fde1 100644 --- a/lua/server/serverplayer.lua +++ b/lua/server/serverplayer.lua @@ -589,19 +589,21 @@ function ServerPlayer:bury() end function ServerPlayer:throwAllCards(flag) - local room = self.room + local cardIds = {} flag = flag or "hej" if string.find(flag, "h") then - room:throwCard(self.player_cards[Player.Hand], "", self) + table.insertTable(cardIds, self.player_cards[Player.Hand]) end if string.find(flag, "e") then - room:throwCard(self.player_cards[Player.Equip], "", self) + table.insertTable(cardIds, self.player_cards[Player.Equip]) end if string.find(flag, "j") then - room:throwCard(self.player_cards[Player.Judge], "", self) + table.insertTable(cardIds, self.player_cards[Player.Judge]) end + + self.room:throwCard(cardIds, "", self) end function ServerPlayer:throwAllMarks() @@ -611,9 +613,11 @@ function ServerPlayer:throwAllMarks() end function ServerPlayer:clearPiles() + local cardIds = {} for _, ids in pairs(self.special_cards) do - self.room:throwCard(ids, "", self) + table.insertTable(cardIds, ids) end + self.room:moveCardTo(cardIds, Card.DiscardPile, nil, fk.ReasonPutIntoDiscardPile, "", nil, true) end function ServerPlayer:addVirtualEquip(card) @@ -656,19 +660,22 @@ end ---@param chained boolean function ServerPlayer:setChainState(chained) - if self.room.logic:trigger(fk.BeforeChainStateChange, self) then + local room = self.room + if room.logic:trigger(fk.BeforeChainStateChange, self) then return end self.chained = chained - self.room:broadcastProperty(self, "chained") - self.room:sendLog{ + + room:broadcastProperty(self, "chained") + room:sendLog{ type = "#ChainStateChange", from = self.id, arg = self.chained and "chained" or "un-chained" } - - self.room.logic:trigger(fk.ChainStateChanged, self) + room:delay(150) + room:broadcastPlaySound("./audio/system/chain") + room.logic:trigger(fk.ChainStateChanged, self) end function ServerPlayer:reset() diff --git a/packages/standard/i18n/zh_CN.lua b/packages/standard/i18n/zh_CN.lua index 11a510c4..9cc520b5 100644 --- a/packages/standard/i18n/zh_CN.lua +++ b/packages/standard/i18n/zh_CN.lua @@ -76,6 +76,7 @@ Fk:loadTranslationTable{ ["$luoshen2"] = "飘飖兮若流风之回雪。", ["luoshen"] = "洛神", [":luoshen"] = "准备阶段开始时,你可以进行判定:若结果为黑色,判定牌生效后你获得之,然后你可以再次发动“洛神”。", + ["#luoshen_obtain"] = "洛神", ["$qingguo1"] = "凌波微步,罗袜生尘。", ["$qingguo2"] = "体迅飞凫,飘忽若神。", ["qingguo"] = "倾国", diff --git a/packages/standard/init.lua b/packages/standard/init.lua index 4f8c314c..e7240c9f 100644 --- a/packages/standard/init.lua +++ b/packages/standard/init.lua @@ -130,10 +130,7 @@ local fankui = fk.CreateTriggerSkill{ on_use = function(self, event, target, player, data) local room = player.room local from = data.from - local flag = "he" - if from == player then - flag = "e" - end + local flag = from == player and "e" or "he" local card = room:askForCardChosen(player, from, flag, self.name) room:obtainCard(player.id, card, false, fk.ReasonPrey) end @@ -366,16 +363,24 @@ local luoshen = fk.CreateTriggerSkill{ pattern = ".|.|spade,club", } room:judge(judge) - if judge.card.color ~= Card.Black then - break - end - room:obtainCard(player.id, judge.card, true, fk.ReasonJustMove) - if player.dead or not room:askForSkillInvoke(player, self.name) then + if judge.card.color ~= Card.Black or player.dead or not room:askForSkillInvoke(player, self.name) then break end end end, } +local luoshen_obtain = fk.CreateTriggerSkill{ + name = "#luoshen_obtain", + mute = true, + frequency = Skill.Compulsory, + events = {fk.FinishJudge}, + can_trigger = function(self, event, target, player, data) + return target == player and data.reason == "luoshen" and data.card.color == Card.Black end, + on_use = function(self, event, target, player, data) + player.room:obtainCard(player.id, data.card) + end, +} +luoshen:addRelatedSkill(luoshen_obtain) local qingguo = fk.CreateViewAsSkill{ name = "qingguo", anim_type = "defensive", @@ -383,7 +388,7 @@ local qingguo = fk.CreateViewAsSkill{ card_filter = function(self, to_select, selected) if #selected == 1 then return false end return Fk:getCardById(to_select).color == Card.Black - and Fk:currentRoom():getCardArea(to_select) ~= Player.Hand + and Fk:currentRoom():getCardArea(to_select) == Player.Hand end, view_as = function(self, cards) if #cards ~= 1 then @@ -951,24 +956,38 @@ local xiaoji = fk.CreateTriggerSkill{ events = {fk.AfterCardsMove}, can_trigger = function(self, event, target, player, data) if not player:hasSkill(self.name) then return end - self.trigger_times = 0 for _, move in ipairs(data) do if move.from == player.id then for _, info in ipairs(move.moveInfo) do if info.fromArea == Card.PlayerEquip then - self.trigger_times = self.trigger_times + 1 + return true end end end end - return self.trigger_times > 0 end, on_trigger = function(self, event, target, player, data) - local ret - for i = 1, self.trigger_times do - ret = self:doCost(event, target, player, data) - if ret then return ret end + local i = 0 + for _, move in ipairs(data) do + if move.from == player.id then + for _, info in ipairs(move.moveInfo) do + if info.fromArea == Card.PlayerEquip then + i = i + 1 + end + end + end end + self.cancel_cost = false + for i = 1, i do + if self.cancel_cost or not player:hasSkill(self.name) then break end + self:doCost(event, target, player, data) + end + end, + on_cost = function(self, event, target, player, data) + if player.room:askForSkillInvoke(player, self.name) then + return true + end + self.cancel_cost = true end, on_use = function(self, event, target, player, data) player:drawCards(2, self.name) @@ -997,14 +1016,14 @@ local jieyin = fk.CreateActiveSkill{ room:recover({ who = room:getPlayerById(effect.tos[1]), num = 1, - recoverBy = room:getPlayerById(effect.from), + recoverBy = from, skillName = self.name }) if from:isWounded() then room:recover({ - who = room:getPlayerById(effect.from), + who = from, num = 1, - recoverBy = room:getPlayerById(effect.from), + recoverBy = from, skillName = self.name }) end @@ -1034,7 +1053,7 @@ local qingnang = fk.CreateActiveSkill{ room:recover({ who = room:getPlayerById(effect.tos[1]), num = 1, - recoverBy = room:getPlayerById(effect.from), + recoverBy = from, skillName = self.name }) end,