diff --git a/image/generals/caojinyu.jpg b/image/generals/caojinyu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d5f68ae160e4ea65bbdb352e00530f1f86192253 Binary files /dev/null and b/image/generals/caojinyu.jpg differ diff --git a/image/generals/guozhao.jpg b/image/generals/guozhao.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f80e23e6ba443e5784c48cc8f6ef2e4fe6f487ce Binary files /dev/null and b/image/generals/guozhao.jpg differ diff --git a/image/generals/zhujianping.jpg b/image/generals/zhujianping.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1e253a8fc0ed82a0f77d2f06f8ac761f601e68ac Binary files /dev/null and b/image/generals/zhujianping.jpg differ diff --git a/init.lua b/init.lua index 136cd70c91dca46c141f4993f77a3ac7e63ae2b5..56fbe7d8282d91187685bff66301e41d509425ef 100644 --- a/init.lua +++ b/init.lua @@ -1146,4 +1146,411 @@ Fk:loadTranslationTable{ ["#yingyuan-give"] = "你可以选择1名其他角色,并将 %arg 交给他", } + +function getCardByPattern(room, pattern, fromPiles) --TODO: move this! + pattern = pattern or "." + fromPiles = room.draw_pile + + local cards = {} + for i = 1, #fromPiles, 1 do + local card = Fk:getCardById(fromPiles[i]) + if card:matchPattern(pattern) then + table.insertIfNeed(cards, fromPiles[i]) + end + end + if #cards > 0 then + return(cards[math.random(1, #cards)]) + else + return nil + end +end + + +local guozhao = General(extension, "guozhao", "wei", 3, 3, General.Female) +local pianchong = fk.CreateTriggerSkill{ + name = "pianchong", + anim_type = "drawcard", + events = {fk.EventPhaseStart}, + can_trigger = function(self, event, target, player, data) + return target == player and player:hasSkill(self.name) and player.phase == Player.Draw + end, + on_use = function(self, event, target, player, data) + local room = player.room + local cards = {} + table.insert(cards, getCardByPattern(room, ".|.|heart,diamond")) + table.insert(cards, getCardByPattern(room, ".|.|spade,club")) + if #cards > 0 then + room:moveCards({ + ids = cards, + to = player.id, + toArea = Card.PlayerHand, + moveReason = fk.ReasonPrey, + proposer = player.id, + skillName = self.name, + }) + end + local choice = room:askForChoice(player, {"red", "black"}, self.name) + room:setPlayerMark(player, "@pianchong", choice) + return true + end, + + refresh_events = {fk.EventPhaseStart, fk.AfterCardsMove}, + can_refresh = function(self, event, target, player, data) + if player:hasSkill(self.name) and not player.dead and player:getMark("@pianchong") ~= 0 then + if event == fk.EventPhaseStart then + return target == player and player.phase == Player.Start + else + local 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.PlayerHand or info.fromArea == Card.PlayerEquip then + local color = player:getMark("@pianchong") + if Fk:getCardById(info.cardId):getColorString() == color then + times = times + 1 + end + end + end + end + end + if times > 0 then + player.room:setPlayerMark(player, self.name, times) + return true + end + end + end + end, + on_refresh = function(self, event, target, player, data) + local room = player.room + if event == fk.EventPhaseStart then + room:setPlayerMark(player, "@pianchong", 0) + else + local pattern + local color = player:getMark("@pianchong") + if color == "red" then + pattern = ".|.|spade,club" + else + pattern = ".|.|heart,diamond" + end + local n = player:getMark(self.name) + room:setPlayerMark(player, self.name, 0) + local cards = {} + for i = 1, n, 1 do + table.insert(cards, getCardByPattern(room, pattern)) + end + if #cards > 0 then + room:moveCards({ + ids = cards, + to = player.id, + toArea = Card.PlayerHand, + moveReason = fk.ReasonPrey, + proposer = player.id, + skillName = self.name, + }) + end + end + end, +} +local zunwei = fk.CreateActiveSkill{ + name = "zunwei", + anim_type = "drawcard", + can_use = function(self, player) + if player:usedSkillTimes(self.name) == 0 then + for i = 1, 3, 1 do + if player:getMark(self.name .. tostring(i)) == 0 then + return true + end + end + end + return false + end, + card_filter = function() + return false + end, + target_filter = function(self, to_select, selected) + if #selected == 0 then + local target = Fk:currentRoom():getPlayerById(to_select) + local player = Fk:currentRoom():getPlayerById(Self.id) + return (player:getMark("zunwei1") == 0 and #player.player_cards[Player.Hand] < #target.player_cards[Player.Hand]) or + (player:getMark("zunwei2") == 0 and #player.player_cards[Player.Equip] < #target.player_cards[Player.Equip]) or + (player:getMark("zunwei3") == 0 and player:isWounded() and player.hp < target.hp) + end + return false + end, + target_num = 1, + card_num = 0, + on_use = function(self, room, effect) + local player = room:getPlayerById(effect.from) + local target = room:getPlayerById(effect.tos[1]) + local choices = {} + if player:getMark("zunwei1") == 0 and #player.player_cards[Player.Hand] < #target.player_cards[Player.Hand] then + table.insert(choices, "zunwei1") + end + if player:getMark("zunwei2") == 0 and #player.player_cards[Player.Equip] < #target.player_cards[Player.Equip] then + table.insert(choices, "zunwei2") + end + if player:getMark("zunwei3") == 0 and player:isWounded() and player.hp < target.hp then + table.insert(choices, "zunwei3") + end + local choice = room:askForChoice(player, choices, self.name) + if choice == "zunwei1" then + player:drawCards(math.min(#target.player_cards[Player.Hand] - #player.player_cards[Player.Hand], 5)) + elseif choice == "zunwei2" then + local n = #target.player_cards[Player.Equip] - #player.player_cards[Player.Equip] + for i = 1, n, 1 do + local types = {Card.SubtypeWeapon, Card.SubtypeArmor, Card.SubtypeDefensiveRide, Card.SubtypeOffensiveRide, Card.SubtypeTreasure} + local cards = {} + for i = 1, #room.draw_pile, 1 do + local card = Fk:getCardById(room.draw_pile[i]) + for _, type in ipairs(types) do + if card.sub_type == type and player:getEquipment(type) == nil then + table.insertIfNeed(cards, room.draw_pile[i]) + end + end + end + if #cards > 0 then + local equip = cards[math.random(1, #cards)] + room:useCard({ + from = player.id, + tos = {{player.id}}, + card = Fk:getCardById(equip), + }) + end + end + elseif choice == "zunwei3" then + room:recover{who = player, num = math.min(player:getLostHp(), target.hp - player.hp), skillName = self.name} + end + room:setPlayerMark(player, choice, 1) + end, +} +guozhao:addSkill(pianchong) +guozhao:addSkill(zunwei) +Fk:loadTranslationTable{ + ["guozhao"] = "郭照", + ["pianchong"] = "偏宠", + [":pianchong"] = "摸牌阶段,你可以改为从牌堆获得红牌和黑牌各一张,然后选择一项直到你的下回合开始:1.你每失去一张红色牌时摸一张黑色牌,2.你每失去一张黑色牌时摸一张红色牌。", + ["zunwei"] = "尊位", + [":zunwei"] = "出牌阶段限一次,你可以选择一名其他角色,并选择执行以下一项,然后移除该选项:1.将手牌数摸至与该角色相同(最多摸五张);2.随机使用牌堆中的装备牌至与该角色相同;3.将体力回复至与该角色相同。", + ["@pianchong"] = "偏宠", + ["zunwei1"] = "将手牌摸至与其相同(最多摸五张)", + ["zunwei2"] = "使用装备至与其相同", + ["zunwei3"] = "回复体力至与其相同", +} + +local caojinyu = General(extension, "caojinyu", "wei", 3, 3, General.Female) +local yuqi = fk.CreateTriggerSkill{ + name = "yuqi", + anim_type = "masochism", + events = {fk.Damaged}, + can_trigger = function(self, event, target, player, data) + return player:hasSkill(self.name) and not player.dead and not target.dead and + (target == player or player:distanceTo(target) <= player:getMark("yuqi1")) and player:getMark(self.name) < 2 + end, + on_use = function(self, event, target, player, data) + local room = player.room + room:addPlayerMark(player, self.name, 1) + --local card_ids = room:getNCards(player:getMark("yuqi2")) + + --FIXME: askForCardsChosen? or yiji? + local n1, n2 = 0, 0 + if player:getMark("yuqi2") >= player:getMark("yuqi4") then + n2 = player:getMark("yuqi4") + n1 = math.min(player:getMark("yuqi3"), player:getMark("yuqi2") - player:getMark("yuqi4")) + else + n2 = player:getMark("yuqi2") + end + target:drawCards(n1) + player:drawCards(n2) + end, + + refresh_events = {fk.DrawInitialCards, fk.EventPhaseStart}, -- FIXME: can't trigger at fk.GameStart? + can_refresh = function(self, event, target, player, data) + if event == fk.DrawInitialCards then + return target == player and target:hasSkill(self.name) + else + return target.phase == Player.NotActive + end + end, + on_refresh = function(self, event, target, player, data) + local room = player.room + if event == fk.DrawInitialCards then + room:setPlayerMark(player, "yuqi2", 3) + room:setPlayerMark(player, "yuqi3", 1) + room:setPlayerMark(player, "yuqi4", 1) + room:setPlayerMark(player, "@" .. self.name, string.format("%d-%d-%d-%d", 0, 3, 1, 1)) + else + room:setPlayerMark(player, self.name, 0) + end + end, +} +local function AddYuqi(player, skillName, num) + local room = player.room + local choices = {} + for i = 1, 4, 1 do + if player:getMark("yuqi" .. tostring(i)) < 5 then + table.insert(choices, "yuqi" .. tostring(i)) + end + end + if #choices > 0 then + local choice = room:askForChoice(player, choices, skillName) + local x = player:getMark(choice) + if x + num < 6 then + x = x + num + else + x = 5 + end + room:setPlayerMark(player, choice, x) + room:setPlayerMark(player, "@yuqi", string.format("%d-%d-%d-%d", + player:getMark("yuqi1"), + player:getMark("yuqi2"), + player:getMark("yuqi3"), + player:getMark("yuqi4"))) + end +end +local shanshen = fk.CreateTriggerSkill{ + name = "shanshen", + anim_type = "control", + events = {fk.Death}, + can_trigger = function(self, event, target, player, data) + return player:hasSkill(self.name) and target ~= player and not player.dead + end, + on_use = function(self, event, target, player, data) + local room = player.room + AddYuqi(player, self.name, 2) + if target:getMark(self.name) == 0 and player:isWounded() then + room:recover{ + who = player, + num = 1, + skillName = self.name, + } + end + end, + refresh_events = {fk.DamageCaused}, + can_refresh = function(self, event, target, player, data) + return target == player and target:hasSkill(self.name) and data.to:getMark(self.name) == 0 + end, + on_refresh = function(self, event, target, player, data) + player.room:setPlayerMark(data.to, self.name, 1) + end, +} +local xianjing = fk.CreateTriggerSkill{ + name = "xianjing", + anim_type = "control", + events = {fk.EventPhaseStart}, + can_trigger = function(self, event, target, player, data) + if target == player and player:hasSkill(self.name) and player.phase == Player.Start then + for i = 1, 4, 1 do + if player:getMark("yuqi" .. tostring(i)) < 5 then + return true + end + end + end + return false + end, + on_use = function(self, event, target, player, data) + AddYuqi(player, self.name, 1) + if not player:isWounded() then + AddYuqi(player, self.name, 1) + end + end, +} +caojinyu:addSkill(yuqi) +caojinyu:addSkill(shanshen) +caojinyu:addSkill(xianjing) +Fk:loadTranslationTable{ + ["caojinyu"] = "曹金玉", + ["yuqi"] = "隅泣", + [":yuqi"] = "当有角色受到伤害后,若你与其距离0或者更少,你可以观看牌堆顶的三张牌,将其中至多一张交给受伤角色,至多一张自己获得,剩余的牌放回牌堆顶。(每回合限触发2次)", + ["shanshen"] = "善身", + [":shanshen"] = "当有角色死亡时,你可令“隅泣”中的一个数字+2(单项不能超过5)。然后若你没有对死亡角色造成过伤害,你回复1点体力。", + ["xianjing"] = "娴静", + [":xianjing"] = "准备阶段,你可令“隅泣”中的一个数字+1(单项不能超过5)。若你满体力值,则再令“隅泣”中的一个数字+1。", + ["@yuqi"] = "隅泣", + ["yuqi1"] = "距离", + ["yuqi2"] = "观看牌数", + ["yuqi3"] = "交给受伤角色牌数", + ["yuqi4"] = "自己获得牌数", +} + +local zhujianping = General(extension, "zhujianping", "qun", 3) +local xiangmian = fk.CreateActiveSkill{ + name = "xiangmian", + anim_type = "offensive", + can_use = function(self, player) + return player:usedSkillTimes(self.name) < 1 + end, + card_filter = function() + 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 + end, + target_num = 1, + on_use = function(self, room, effect) + local target = room:getPlayerById(effect.tos[1]) + local judge = { + who = target, + reason = self.name, + pattern = ".", + } + room:judge(judge) + room:setPlayerMark(target, "@xiangmian", string.format("%s-%d", + Fk:translate(judge.card:getSuitString()), + judge.card.number)) + room:setPlayerMark(target, "xiangmian_suit", judge.card:getSuitString()) + room:setPlayerMark(target, "xiangmian_num", judge.card.number) + end, +} +local xiangmian_kill = fk.CreateTriggerSkill{ + name = "#xiangmian_kill", + refresh_events = {fk.CardUseFinished}, + can_refresh = function(self, event, target, player, data) + return target == player and target:getMark("xiangmian_num") > 0 + end, + on_refresh = function(self, event, target, player, data) + 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:loseHp(target, target.hp, "xiangmian") + end + end, +} +local tianji = fk.CreateTriggerSkill{ + name = "tianji", + events = {fk.FinishJudge}, + frequency = Skill.Compulsory, + can_trigger = function(self, event, target, player, data) + return player:hasSkill(self.name) + end, + on_use = function(self, event, target, player, data) + local room = player.room + local card = data.card + local cards = {} + table.insert(cards, getCardByPattern(room, ".|.|.|.|.|"..card:getTypeString())) + table.insert(cards, getCardByPattern(room, ".|.|"..card:getSuitString())) + table.insert(cards, getCardByPattern(room, ".|"..card.number)) + if #cards > 0 then + room:moveCards({ + ids = cards, + to = player.id, + toArea = Card.PlayerHand, + moveReason = fk.ReasonPrey, + proposer = player.id, + skillName = self.name, + }) + end + end, +} +xiangmian:addRelatedSkill(xiangmian_kill) +zhujianping:addSkill(xiangmian) +zhujianping:addSkill(tianji) +Fk:loadTranslationTable{ + ["zhujianping"] = "朱建平", + ["xiangmian"] = "相面", + [":xiangmian"] = "出牌阶段限一次,你可以令一名其他角色进行一次判定,当该角色使用判定花色的牌或使用第X张牌后(X为判定点数),其失去所有体力。每名其他角色限一次。", + ["tianji"] = "天机", + [":tianji"] = "锁定技,生效后的判定牌进入弃牌堆后,你从牌堆随机获得与该牌类型、花色和点数相同的牌各一张。", + ["@xiangmian"] = "相面", +} + return {extension}