From 79389d94444c24ba34707dd7fb812ed4c473a0e5 Mon Sep 17 00:00:00 2001 From: notify Date: Sun, 5 Mar 2023 01:28:59 +0800 Subject: [PATCH] Expand pile (#62) * fixbug: handcards in PlayerCardBox * fix lightning * fix translation * gamelogic:getcurrentevent * exppattern and pile * complete pile --- lua/client/client.lua | 5 +++ lua/client/client_util.lua | 4 ++ lua/core/exppattern.lua | 11 ++++- lua/core/skill_type/active.lua | 3 +- lua/core/util.lua | 3 +- lua/server/ai/ai.lua | 2 +- lua/server/ai/random_ai.lua | 4 +- lua/server/gamelogic.lua | 6 ++- lua/server/room.lua | 8 ++-- packages/standard/i18n/en_US.lua | 4 +- packages/standard_cards/init.lua | 7 ++- packages/test/init.lua | 9 +++- qml/Pages/RoomElement/Dashboard.qml | 58 ++++++++++++++++++++++++- qml/Pages/RoomElement/PlayerCardBox.qml | 16 +++---- 14 files changed, 114 insertions(+), 26 deletions(-) diff --git a/lua/client/client.lua b/lua/client/client.lua index 11c277d0..ef83be7a 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -59,6 +59,11 @@ function Client:getCardArea(cardId) if table.contains(Self.player_cards[Player.Equip], cardId) then return Card.PlayerEquip end + for _, t in pairs(Self.special_cards) do + if table.contains(t, cardId) then + return Card.PlayerSpecial + end + end error("Client:getCardArea can only judge cards in your hand or equip area") end diff --git a/lua/client/client_util.lua b/lua/client/client_util.lua index f81d0002..5ce9da8f 100644 --- a/lua/client/client_util.lua +++ b/lua/client/client_util.lua @@ -121,6 +121,10 @@ function GetPile(id, name) return json.encode(ClientInstance:getPlayerById(id):getPile(name) or {}) end +function GetAllPiles(id) + return json.encode(ClientInstance:getPlayerById(id).special_cards or {}) +end + ---@param card string | integer ---@param player integer function CanUseCard(card, player) diff --git a/lua/core/exppattern.lua b/lua/core/exppattern.lua index f8d03e8f..04545b7c 100644 --- a/lua/core/exppattern.lua +++ b/lua/core/exppattern.lua @@ -73,8 +73,17 @@ local function matchCard(matcher, card) matcher.place, placetable[Fk:currentRoom():getCardArea(card.id)] ) then + if ClientInstance then + return Self:getPileNameOfId(card.id) and true or false + else + for _, p in ipairs(RoomInstance.alive_players) do + local pile = p:getPileNameOfId(card.id) + if pile then return true end + end + end return false end + -- TODO: generalName if matcher.cardType and not table.contains(matcher.cardType, typetable[card.type]) then @@ -172,7 +181,7 @@ local function parseMatcher(str) end ret.suit = not table.contains(t[3], ".") and t[3] or nil - ret.place = not table.contains(t[4], ".") and t[4] or nil + ret.place = not table.contains(t[4], ".") and t[4] or { "hand", "equip" } ret.generalName = not table.contains(t[5], ".") and t[5] or nil ret.cardType = not table.contains(t[6], ".") and t[6] or nil diff --git a/lua/core/skill_type/active.lua b/lua/core/skill_type/active.lua index 23d2be3b..efa09c31 100644 --- a/lua/core/skill_type/active.lua +++ b/lua/core/skill_type/active.lua @@ -41,7 +41,8 @@ end ---@param to_select integer @ id of the target ---@param selected integer[] @ ids of selected targets ---@param selected_cards integer[] @ ids of selected cards -function ActiveSkill:targetFilter(to_select, selected, selected_cards) +---@param card Card @ helper +function ActiveSkill:targetFilter(to_select, selected, selected_cards, card) return false end diff --git a/lua/core/util.lua b/lua/core/util.lua index 0d58288f..6f735de7 100644 --- a/lua/core/util.lua +++ b/lua/core/util.lua @@ -139,6 +139,7 @@ end ---@return T|T[] function table.random(tab, n) n = n or 1 + local n0 = n if #tab == 0 then return nil end local tmp = {table.unpack(tab)} local ret = {} @@ -147,7 +148,7 @@ function table.random(tab, n) table.insert(ret, table.remove(tmp, i)) n = n - 1 end - return n == 1 and ret[1] or ret + return n0 == 1 and ret[1] or ret end ---@param delimiter string diff --git a/lua/server/ai/ai.lua b/lua/server/ai/ai.lua index a0642043..b1eb2051 100644 --- a/lua/server/ai/ai.lua +++ b/lua/server/ai/ai.lua @@ -35,7 +35,7 @@ function AI:makeReply() local start = os.getms() local ret = self.cb_table[self.command] and self.cb_table[self.command](self, self.jsonData) or "__cancel" local to_delay = 500 - (os.getms() - start) / 1000 - print(to_delay) + -- print(to_delay) self.room:delay(to_delay) return ret end diff --git a/lua/server/ai/random_ai.lua b/lua/server/ai/random_ai.lua index 0e1604c8..d1a52770 100644 --- a/lua/server/ai/random_ai.lua +++ b/lua/server/ai/random_ai.lua @@ -27,7 +27,7 @@ local function useActiveSkill(self, skill, card) while not skill:feasible(selected_targets, selected_cards, self.player, card) do if max_try_times <= 0 then break end local avail_targets = table.filter(self.room:getAlivePlayers(), function(p) - local ret = skill:targetFilter(p.id, selected_targets, selected_cards) + local ret = skill:targetFilter(p.id, selected_targets, selected_cards, card or Fk:cloneCard'zixing') if ret and card then local r = self.room local status_skills = r.status_skills[ProhibitSkill] or {} @@ -58,7 +58,7 @@ local function useActiveSkill(self, skill, card) }, targets = selected_targets, } - print(ret) + -- print(ret) return ret end return "" diff --git a/lua/server/gamelogic.lua b/lua/server/gamelogic.lua index 9351dd2b..24381823 100644 --- a/lua/server/gamelogic.lua +++ b/lua/server/gamelogic.lua @@ -277,8 +277,12 @@ function GameLogic:trigger(event, target, data) return broken end +function GameLogic:getCurrentEvent() + return self.game_event_stack.t[self.game_event_stack.p] +end + function GameLogic:breakEvent(ret) - coroutine.yield("__breakEvent", false) + coroutine.yield("__breakEvent", ret) end return GameLogic diff --git a/lua/server/room.lua b/lua/server/room.lua index 9865bd05..15196acd 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -64,9 +64,9 @@ function Room:initialize(_room) local request_co = coroutine.create(function(rest) self:requestLoop(rest) end) - local ret, err_msg = true, true + local ret, err_msg, rest_time = true, true while not self.game_finished do - ret, _, err_msg = coroutine.resume(main_co, err_msg) + ret, err_msg, rest_time = coroutine.resume(main_co, err_msg) -- handle error if ret == false then @@ -75,9 +75,7 @@ function Room:initialize(_room) break end - -- If ret == true, then err_msg is the millisecond left - - ret, err_msg = coroutine.resume(request_co, err_msg) + ret, err_msg = coroutine.resume(request_co, rest_time) if ret == false then fk.qCritical(err_msg) print(debug.traceback(request_co)) diff --git a/packages/standard/i18n/en_US.lua b/packages/standard/i18n/en_US.lua index 75933e75..d521a089 100644 --- a/packages/standard/i18n/en_US.lua +++ b/packages/standard/i18n/en_US.lua @@ -136,7 +136,7 @@ Fk:loadTranslationTable({ }, "en_US") -- aux skills -Fk:loadTranslationTable{ +Fk:loadTranslationTable({ ["discard_skill"] = "Discard", ["choose_players_skill"] = "Choose players", -} +}, "en_US") diff --git a/packages/standard_cards/init.lua b/packages/standard_cards/init.lua index 3e0208e3..7cc94e7b 100644 --- a/packages/standard_cards/init.lua +++ b/packages/standard_cards/init.lua @@ -574,7 +574,12 @@ local lightningSkill = fk.CreateActiveSkill{ end, on_nullified = function(self, room, effect) local to = room:getPlayerById(effect.to) - local nextp = to:getNextAlive() + local nextp + repeat + nextp = to:getNextAlive() + if nextp == to then return end + until not nextp:hasDelayedTrick("lightning") + room:moveCards{ ids = room:getSubcardsByRule(effect.card, { Card.Processing }), to = nextp.id, diff --git a/packages/test/init.lua b/packages/test/init.lua index abbf1c8d..3135f256 100644 --- a/packages/test/init.lua +++ b/packages/test/init.lua @@ -60,6 +60,10 @@ local test_active = fk.CreateActiveSkill{ can_use = function(self, player) return true end, + card_filter = function(self, card) + local c = Fk:getCardById(card) + return Self:getPileNameOfId(card) == self.name and c.color == Card.Red + end, target_filter = function() return true end, on_use = function(self, room, effect) --room:doSuperLightBox("packages/test/qml/Test.qml") @@ -72,8 +76,9 @@ local test_active = fk.CreateActiveSkill{ -- room:takeAG(from, id) -- room:delay(2000) -- room:closeAG(from) - local cards = room:askForCardsChosen(from, room:getPlayerById(effect.tos[1]), 2, 3, "hej", "") - p(cards) + local cards = room:askForCardsChosen(from, from, 2, 3, "hej", "") + from:addToPile(self.name, cards) + -- p(cards) end, } local test2 = General(extension, "mouxusheng", "wu", 4, 4, General.Female) diff --git a/qml/Pages/RoomElement/Dashboard.qml b/qml/Pages/RoomElement/Dashboard.qml index 034877e4..713d9ab1 100644 --- a/qml/Pages/RoomElement/Dashboard.qml +++ b/qml/Pages/RoomElement/Dashboard.qml @@ -75,7 +75,6 @@ RowLayout { let component = Qt.createComponent("CardItem.qml"); let parentPos = roomScene.mapFromItem(selfPhoto, 0, 0); - // FIXME: only expand equip area here. modify this if need true pile expanded_piles[pile] = []; if (pile === "_equip") { let equips = selfPhoto.equipArea.getAllCards(); @@ -88,6 +87,18 @@ RowLayout { handcardAreaItem.add(card); }) handcardAreaItem.updateCardPosition(); + } else { + let ids = JSON.parse(Backend.callLuaFunction("GetPile", [selfPhoto.playerid, pile])); + ids.forEach(id => { + let data = JSON.parse(Backend.callLuaFunction("GetCardData", [id])); + data.x = parentPos.x; + data.y = parentPos.y; + let card = component.createObject(roomScene, data); + card.footnoteVisible = true; + card.footnote = Backend.translate(pile); + handcardAreaItem.add(card); + }); + handcardAreaItem.updateCardPosition(); } } @@ -109,6 +120,16 @@ RowLayout { card.goBack(true); }) handcardAreaItem.updateCardPosition(); + } else { + let ids = JSON.parse(Backend.callLuaFunction("GetPile", [selfPhoto.playerid, pile])); + ids.forEach(id => { + let card = handcardAreaItem.remove([id])[0]; + card.origX = parentPos.x; + card.origY = parentPos.y; + card.destroyOnStop(); + card.goBack(true); + }); + handcardAreaItem.updateCardPosition(); } } @@ -139,6 +160,23 @@ RowLayout { } }); + let pile_data = JSON.parse(Backend.callLuaFunction("GetAllPiles", [selfPhoto.playerid])); + if (!(pile_data instanceof Array)) { + for (let pile_name in pile_data) { + pile_data[pile_name].forEach(cid => { + if (JSON.parse(Backend.callLuaFunction( + "CardFitPattern", + [cid, cname] + ))) { + ids.push(cid); + if (!expanded_piles[pile_name]) { + expandPile(pile_name); + } + } + }); + } + } + handcardAreaItem.enableCards(ids); return; } @@ -212,6 +250,24 @@ RowLayout { } } }) + + let pile_data = JSON.parse(Backend.callLuaFunction("GetAllPiles", [selfPhoto.playerid])); + if (!(pile_data instanceof Array)) { + for (let pile_name in pile_data) { + pile_data[pile_name].forEach(cid => { + if (JSON.parse(Backend.callLuaFunction( + "ActiveCardFilter", + [pending_skill, cid, pendings, targets] + ))) { + enabled_cards.push(cid); + if (!expanded_piles[pile_name]) { + expandPile(pile_name); + } + } + }); + } + } + handcardAreaItem.enableCards(enabled_cards); if (JSON.parse(Backend.callLuaFunction( diff --git a/qml/Pages/RoomElement/PlayerCardBox.qml b/qml/Pages/RoomElement/PlayerCardBox.qml index c8fa0085..13e0583a 100644 --- a/qml/Pages/RoomElement/PlayerCardBox.qml +++ b/qml/Pages/RoomElement/PlayerCardBox.qml @@ -64,12 +64,12 @@ GraphicsBox { model: handcards CardItem { - name: "card-back" - cid: -1 - suit: "" - number: 0 + cid: model.cid + name: model.name || "" + suit: model.suit || "" + number: model.number || 0 autoBack: false - known: false + known: model.cid !== -1 selectable: true onClicked: { if (!root.multiChoose) { @@ -220,7 +220,7 @@ GraphicsBox { function addHandcards(cards) { if (cards instanceof Array) { - for (var i = 0; i < cards.length; i++) + for (let i = 0; i < cards.length; i++) handcards.append(cards[i]); } else { handcards.append(cards); @@ -230,7 +230,7 @@ GraphicsBox { function addEquips(cards) { if (cards instanceof Array) { - for (var i = 0; i < cards.length; i++) + for (let i = 0; i < cards.length; i++) equips.append(cards[i]); } else { equips.append(cards); @@ -240,7 +240,7 @@ GraphicsBox { function addDelayedTricks(cards) { if (cards instanceof Array) { - for (var i = 0; i < cards.length; i++) + for (let i = 0; i < cards.length; i++) delayedTricks.append(cards[i]); } else { delayedTricks.append(cards);