diff --git a/image/generals/zhouxuan.jpg b/image/generals/zhouxuan.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fb9ff4fa4e1d981aa4c545f6f807a526d0519bf3 Binary files /dev/null and b/image/generals/zhouxuan.jpg differ diff --git a/init.lua b/init.lua index 56fbe7d8282d91187685bff66301e41d509425ef..fc1efa08350d35b534f4f5fe0d0d48aa3732b5c0 100644 --- a/init.lua +++ b/init.lua @@ -1147,10 +1147,23 @@ Fk:loadTranslationTable{ } -function getCardByPattern(room, pattern, fromPiles) --TODO: move this! +---@param pattern string +---@param fromPiles integer[] +---@return integer[] | nil +function getCardByPattern(room, pattern, fromPiles) pattern = pattern or "." fromPiles = room.draw_pile + --THIS IS STUPID! + if pattern == "damage_card" then + pattern = "slash,duel,savage_assault,archery_attack,fire_attack,thunder" + elseif pattern == "nondamage_card" then + pattern = "jink,peach,dismantlement,snatch,collateral,nullification,indulgence,amazing_grace,god_salvation".. + "crossbow,double_swords,qinggang_sword,ice_sword,axe,spear,blade,halberd,kylin_bow,eight_diagram,nioh_shield,chitu,dayuan,dilu,jueying,zixing,zhuahuangfeidian".. + "analeptic,iron_chain,supply_shortage".. + "guding_blade,fan,silver_lion,vine,hualiu" + end + local cards = {} for i = 1, #fromPiles, 1 do local card = Fk:getCardById(fromPiles[i]) @@ -1483,7 +1496,7 @@ local xiangmian = fk.CreateActiveSkill{ return false end, target_filter = function(self, to_select, selected) - return #selected == 0 and to_select ~= Self.id and Fk:currentRoom():getPlayerById(to_select):getMark("@xiangmian") == 0 + return #selected == 0 and to_select ~= Self.id and Fk:currentRoom():getPlayerById(to_select):getMark("xiangmian_suit") == 0 end, target_num = 1, on_use = function(self, room, effect) @@ -1511,6 +1524,8 @@ local xiangmian_kill = fk.CreateTriggerSkill{ local room = player.room room:addPlayerMark(target, self.name, 1) if data.card:getSuitString() == target:getMark("xiangmian_suit") or target:getMark(self.name) == target:getMark("xiangmian_num") then + room:setPlayerMark(target, "xiangmian_num", 0) + room:setPlayerMark(target, "@xiangmian", 0) room:loseHp(target, target.hp, "xiangmian") end end, @@ -1553,4 +1568,221 @@ Fk:loadTranslationTable{ ["@xiangmian"] = "相面", } +local zhouxuan = General(extension, "zhouxuan", "wei", 3) +local wumei = fk.CreateTriggerSkill{ + name = "wumei", + anim_type = "control", + events = {fk.EventPhaseStart}, + can_trigger = function(self, event, target, player, data) + return target == player and player:hasSkill(self.name) and player.phase == Player.RoundStart and player:getMark("wumei") == 0 + end, + on_cost = function(self, event, target, player, data) + local p = player.room:askForChoosePlayers(player, table.map(player.room:getAlivePlayers(), function(p) return p.id end), 1, 1, "#wumei-choose", self.name) + if #p > 0 then + self.cost_data = p[1] + return true + end + end, + on_use = function(self, event, target, player, data) + local room = player.room + room:addPlayerMark(player, "wumei", 1) + for _, p in ipairs(room:getAlivePlayers()) do + room:setPlayerMark(p, "wumei_hp", p.hp) + end + local to = room:getPlayerById(self.cost_data) + room:addPlayerMark(to, "wumei_extra", 1) + to:gainAnExtraTurn() + end, + + refresh_events = {fk.EventPhaseStart, fk.TurnStart}, + can_refresh = function(self, event, target, player, data) + if event == fk.EventPhaseStart then + return player.phase == Player.NotActive and player:getMark("wumei_extra") > 0 + else + return target.seat == 1 + end + end, + on_refresh = function(self, event, target, player, data) + local room = player.room + if event == fk.EventPhaseStart then + room:setPlayerMark(player, "wumei_extra", 0) + for _, p in ipairs(room:getAlivePlayers()) do + p.hp = p:getMark("wumei_hp") + room:broadcastProperty(p, "hp") + room:setPlayerMark(p, "wumei_hp", 0) + end + else + for _, p in ipairs(room:getAlivePlayers()) do + if p:getMark("wumei") > 0 then + room:setPlayerMark(p, "wumei", 0) + end + end + end + end, +} +local zhanmeng = fk.CreateTriggerSkill{ + name = "zhanmeng", + events = {fk.CardUsing}, + can_trigger = function(self, event, target, player, data) + if target == player and player:hasSkill(self.name) then + for i = 1, 3, 1 do + if player:getMark(self.name .. tostring(i)) == 0 then + return true + end + end + end + end, + on_cost = function(self, event, target, player, data) + local room = player.room + local choices = {"Cancel"} + self.cost_data = {} + if player:getMark("zhanmeng1") == 0 and table.contains(room:getTag("zhanmeng1"), data.card.trueName) then + table.insert(choices, "zhanmeng1") + end + if player:getMark("zhanmeng2") == 0 then + table.insert(choices, "zhanmeng2") + end + local tos = {} + if player:getMark("zhanmeng3") == 0 then + for _, p in ipairs(room:getOtherPlayers(player)) do + if #p.player_cards[Player.Hand] + #p.player_cards[Player.Equip] > 1 then + table.insertIfNeed(choices, "zhanmeng3") + table.insert(tos, p) + end + end + end + local choice = room:askForChoice(player, choices, self.name) + if choice == "Cancel" then return end + self.cost_data[1] = choice + if choice == "zhanmeng3" then + local p = room:askForChoosePlayers(player, table.map(tos, function(p) return p.id end), 1, 1, "#zhanmeng-choose", self.name) + if #p > 0 then + self.cost_data[2] = p[1] + end + end + return #self.cost_data > 0 + end, + on_use = function(self, event, target, player, data) + local room = player.room + local choice = self.cost_data[1] + room:setPlayerMark(player, choice, 1) + if choice == "zhanmeng1" then + local card = {getCardByPattern(room, "nondamage_card")} + if #card > 0 then + room:moveCards({ + ids = card, + to = player.id, + toArea = Card.PlayerHand, + moveReason = fk.ReasonPrey, + proposer = player.id, + skillName = self.name, + }) + end + elseif choice == "zhanmeng2" then + room:setPlayerMark(player, "zhanmeng2_invoke", data.card.trueName) + elseif choice == "zhanmeng3" then + local p = room:getPlayerById(self.cost_data[2]) + --ATTENTION: this skill may discard cards after target filted, so cards like dismantlement,snatch,collateral,fire_attack should check again before effect! + local discards = room:askForDiscard(p, 2, 2, true, self.name, false) + if Fk:getCardById(discards[1]).number + Fk:getCardById(discards[2]).number > 10 then + room:damage{ + from = player, + to = p, + damage = 1, + damageType = fk.FireDamage, + skillName = self.name, + } + end + end + end, + + refresh_events = {fk.EventPhaseStart}, + can_refresh = function(self, event, target, player, data) + return target == player and player:hasSkill(self.name) and player.phase == Player.NotActive + end, + on_refresh = function(self, event, target, player, data) + for i = 1, 3, 1 do + player.room:setPlayerMark(player, self.name .. tostring(i), 0) + end + end, +} +local zhanmeng_record = fk.CreateTriggerSkill{ + name = "#zhanmeng_record", + + refresh_events = {fk.CardUsing, fk.EventPhaseStart}, + can_refresh = function(self, event, target, player, data) + if target == player then + if event == fk.CardUsing then + return true + else + return player.phase == Player.Start or player.phase == Player.NotActive + end + end + end, + on_refresh = function(self, event, target, player, data) + local room = player.room + if event == fk.CardUsing then + local zhanmeng2 = room:getTag("zhanmeng2") + if type(zhanmeng2) ~= "table" then + zhanmeng2 = {} + end + if not table.contains(zhanmeng2, data.card.trueName) then + table.insert(zhanmeng2, data.card.trueName) + room:setTag("zhanmeng2", zhanmeng2) + end + for _, p in ipairs(room:getAlivePlayers()) do + if p:getMark("zhanmeng2_get") == data.card.trueName then + room:setPlayerMark(p, "zhanmeng2_get", 0) + local card = {getCardByPattern(room, "damage_card")} + if #card > 0 then + room:moveCards({ + ids = card, + to = p.id, + toArea = Card.PlayerHand, + moveReason = fk.ReasonPrey, + proposer = p.id, + skillName = "zhanmeng", + }) + end + end + end + else + if player.phase == Player.Start then + local zhanmeng2 = room:getTag("zhanmeng2") + if type(zhanmeng2) ~= "table" then + zhanmeng2 = {} + end + room:setTag("zhanmeng1", zhanmeng2) --cards used in last turn + zhanmeng2 = {} + room:setTag("zhanmeng2", zhanmeng2) --cards used in current turn + for _, p in ipairs(room:getAlivePlayers()) do + if type(p:getMark("zhanmeng2_invoke")) == "string" then + room:setPlayerMark(p, "zhanmeng2_get", p:getMark("zhanmeng2_invoke")) + room:setPlayerMark(p, "zhanmeng2_invoke", 0) + end + end + elseif player.phase == Player.NotActive then + for _, p in ipairs(room:getAlivePlayers()) do + room:setPlayerMark(p, "zhanmeng2_get", 0) + end + end + end + end, +} +zhanmeng:addRelatedSkill(zhanmeng_record) +zhouxuan:addSkill(wumei) +zhouxuan:addSkill(zhanmeng) +Fk:loadTranslationTable{ + ["zhouxuan"] = "周宣", + ["wumei"] = "寤寐", + [":wumei"] = "每轮限一次,回合开始前,你可以令一名角色执行一个额外的回合:该回合结束时,将所有存活角色的体力值调整为此额外回合开始时的数值。", + ["zhanmeng"] = "占梦", + [":zhanmeng"] = "你使用牌时,可以执行以下一项(每回合每项各限一次):1.上一回合内,若没有同名牌被使用,你获得一张非伤害牌。2.下一回合内,当同名牌首次被使用后,你获得一张伤害牌。3.令一名其他角色弃置两张牌,若点数之和大于10,对其造成1点火焰伤害。", + ["#wumei-choose"] = "占梦: 你可以令一名角色执行一个额外的回合", + ["zhanmeng1"] = "你获得一张非伤害牌", + ["zhanmeng2"] = "下一回合内,当同名牌首次被使用后,你获得一张伤害牌", + ["zhanmeng3"] = "令一名其他角色弃置两张牌,若点数之和大于10,对其造成1点火焰伤害", + ["#zhanmeng-choose"] = "占梦: 令一名其他角色弃置两张牌,若点数之和大于10,对其造成1点火焰伤害", +} + return {extension}