diff --git a/image/generals/rfenghou__xushao.jpg b/image/generals/rfenghou__xushao.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..002c598fc4aff79c6c6422bcaebf3a56b001f3b9
Binary files /dev/null and b/image/generals/rfenghou__xushao.jpg differ
diff --git a/rfenghou_qun.lua b/rfenghou_qun.lua
index efbb3884a8ae5069540943688da6a2c40f0d0a40..40124c40e3e9f50610cbdbaf92dcf7bb8ea5397c 100644
--- a/rfenghou_qun.lua
+++ b/rfenghou_qun.lua
@@ -1028,4 +1028,233 @@ Fk:loadTranslationTable{
["#rfenghou__beikou-give"] = "备寇:你可以将这些牌分配给等量的群势力角色",
}
+
+local xushao = General(extension, "rfenghou__xushao", "qun", 3)
+---@param player ServerPlayer
+local addFangkeSkill = function(player, skillName)
+ local room = player.room
+ local skill = Fk.skills[skillName]
+ if (not skill) or skill.lordSkill or skill.switchSkillName
+ or skill.frequency > 3 -- 锁定技=3 后面的都是特殊标签
+ or player:hasSkill(skill, true) then
+ return
+ end
+
+ local fangke_skills = player:getMark("rfenghou_fangke_skills")
+ if fangke_skills == 0 then fangke_skills = {} end
+ table.insert(fangke_skills, skillName)
+ room:setPlayerMark(player, "rfenghou_fangke_skills", fangke_skills)
+
+ --[[
+ -- room:handleAddLoseSkills(player, skillName, nil, false)
+ player:doNotify("AddSkill", json.encode{ player.id, skillName })
+
+ if skill:isInstanceOf(TriggerSkill) or table.find(skill.related_skills,
+ function(s) return s:isInstanceOf(TriggerSkill) end) then
+ player:doNotify("AddSkill", json.encode{ player.id, skillName, true })
+ end
+
+ if skill.frequency ~= Skill.Compulsory then
+ end
+ --]]
+
+ player:addFakeSkill(skill)
+ player:prelightSkill(skill.name, true)
+end
+
+---@param player ServerPlayer
+local removeFangkeSkill = function(player, skillName)
+ local room = player.room
+ local skill = Fk.skills[skillName]
+
+ local fangke_skills = player:getMark("rfenghou_fangke_skills")
+ if fangke_skills == 0 then return end
+ if not table.contains(fangke_skills, skillName) then
+ return
+ end
+ table.removeOne(fangke_skills, skillName)
+ room:setPlayerMark(player, "rfenghou_fangke_skills", fangke_skills)
+
+ --[[
+ if player:hasSkill(skillName) then -- FIXME: 预亮的bug,预亮技能会导致服务器为玩家直接添加技能
+ player:loseSkill(Fk.skills[skillName])
+ end
+ player:doNotify("LoseSkill", json.encode{ player.id, skillName })
+
+ if skill:isInstanceOf(TriggerSkill) or table.find(skill.related_skills,
+ function(s) return s:isInstanceOf(TriggerSkill) end) then
+ player:doNotify("LoseSkill", json.encode{ player.id, skillName, true })
+ end
+ --]]
+
+ player:loseFakeSkill(skill)
+end
+
+---@param player ServerPlayer
+---@param general General
+local function addFangke(player, general, addSkill)
+ local room = player.room
+ local glist = player:getTableMark("@&rfenghou_fangke")
+ table.insertIfNeed(glist, general.name)
+ room:setPlayerMark(player, "@&rfenghou_fangke", glist)
+
+ if not addSkill then return end
+ for _, s in ipairs(general.skills) do
+ addFangkeSkill(player, s.name)
+ end
+ for _, sname in ipairs(general.other_skills) do
+ addFangkeSkill(player, sname)
+ end
+end
+
+local banned_fangke = {
+ "starsp__xiahoudun", -- 原因:无敌
+ "shichangshi", -- 原因:变将与休整
+ "godjiaxu", "zhangfei","rfenghou__huangzhong", "liyixiejing", "olz__wangyun", "yanyan", "duanjiong", "wolongfengchu", "wuanguo",
+ "os__wangling", -- 原因:没有可用技能
+ "os__xia__liubei", -- 原因:发动技能逻辑缺陷
+}
+
+local yingmen = fk.CreateTriggerSkill{
+ name = "yingmen",
+ events = {fk.GameStart, fk.TurnStart},
+ frequency = Skill.Compulsory,
+ can_trigger = function(self, event, target, player, _)
+ if event == fk.GameStart then
+ return player:hasSkill(self)
+ else
+ return target == player and player:hasSkill(self) and #player:getTableMark("@&rfenghou_fangke") < 4
+ end
+ end,
+ on_use = function (self, event, target, player, data)
+ local room = player.room
+ local exclude_list = table.map(room.players, function(p)
+ return p.general
+ end)
+ table.insertTable(exclude_list, banned_fangke)
+ for _, p in ipairs(room.players) do
+ local deputy = p.deputyGeneral
+ if deputy and deputy ~= "" then
+ table.insert(exclude_list, deputy)
+ end
+ end
+
+ local m = player:getMark("@&rfenghou_fangke")
+ local n = 4
+ if event ~= fk.GameStart then
+ n = 4 - #player:getTableMark("@&rfenghou_fangke")
+ end
+ local generals = table.random(room.general_pile, n)
+ for _, g in ipairs(generals) do
+ addFangke(player, Fk.generals[g], player:hasSkill("rfenghou__pingjian", true))
+ end
+ end,
+
+ refresh_events = {fk.SkillEffect},
+ can_refresh = function (self, event, target, player, data)
+ return target == player and player:getMark("rfenghou_fangke_skills") ~= 0 and
+ table.contains(player:getMark("rfenghou_fangke_skills"), data.name)
+ end,
+ on_refresh = function (self, event, target, player, data)
+ local room = player.room
+ for _, s in ipairs(data.related_skills) do
+ if s:isInstanceOf(StatusSkill) then
+ room.status_skills[s.class] = room.status_skills[s.class] or {}
+ table.insertIfNeed(room.status_skills[s.class], s)
+ room:doBroadcastNotify("AddSkill", json.encode{player.id, s.name})
+ end
+ end
+ end,
+}
+
+xushao:addSkill(yingmen)
+
+---@param player ServerPlayer
+---@param general_name string
+local function removeFangke(player, general_name)
+ local room = player.room
+ local glist = player:getMark("@&rfenghou_fangke")
+ if glist == 0 then return end
+ table.removeOne(glist, general_name)
+ room:setPlayerMark(player, "@&rfenghou_fangke", #glist > 0 and glist or 0)
+
+ local general = Fk.generals[general_name]
+ for _, s in ipairs(general.skills) do
+ removeFangkeSkill(player, s.name)
+ end
+ for _, sname in ipairs(general.other_skills) do
+ removeFangkeSkill(player, sname)
+ end
+end
+
+local pingjian = fk.CreateTriggerSkill{
+ name = "rfenghou__pingjian",
+ events = {fk.AfterSkillEffect},
+ can_trigger = function(self, _, target, player, data)
+ return target == player and player:hasSkill(self) and #player:getTableMark("@&rfenghou_fangke") > 0
+ and player:getMark("rfenghou_fangke_skills") ~= 0 and
+ table.contains(player:getMark("rfenghou_fangke_skills"), data.name)
+ end,
+ on_cost = Util.TrueFunc,
+ on_use = function(self, _, target, player, data)
+ local room = player.room
+ local choices = player:getMark("@&rfenghou_fangke")
+ local owner = table.find(choices, function (name)
+ local general = Fk.generals[name]
+ return table.contains(general:getSkillNameList(), data.name)
+ end) or "?"
+ local choice = choices[1]
+ if #choices > 1 then
+ local result = player.room:askForCustomDialog(player, self.name,
+ "packages/utility/qml/ChooseGeneralsAndChoiceBox.qml", {
+ choices,
+ {"OK"},
+ "#rfenghou_lose_fangke:::"..owner,
+ })
+ if result ~= "" then
+ local reply = json.decode(result)
+ choice = reply.cards[1]
+ end
+ end
+ removeFangke(player, choice)
+ if choice == owner and not player.dead then
+ player:drawCards(1, self.name)
+ end
+ end,
+
+ refresh_events = {fk.EventLoseSkill},
+ can_refresh = function (self, event, target, player, data)
+ return target == player and data == self and player:getMark("@&rfenghou_fangke") ~= 0
+ end,
+ on_refresh = function (self, event, target, player, data)
+ for _, g in ipairs(player:getMark("@&rfenghou_fangke")) do
+ removeFangke(player, g)
+ end
+ end,
+}
+xushao:addSkill(pingjian)
+Fk:loadTranslationTable{
+ ["rfenghou__xushao"] = "许劭",
+ ["#rfenghou__xushao"] = "识人读心",
+ ["cv:rfenghou__xushao"] = "樰默",
+ ["illustrator:rfenghou__xushao"] = "凡果",
+
+ ["rfenghou__yingmen"] = "盈门",
+ [":rfenghou__yingmen"] = "锁定技,游戏开始时,你在剩余武将牌堆中随机获得四张武将牌置于你的武将牌上,称为“访客”;回合开始前,若你的“访客”数少于四张,"..
+ "则你从剩余武将牌堆中将“访客”补至四张。",
+ ["@&rfenghou_fangke"] = "访客",
+ ["#rfenghou_lose_fangke"] = "评鉴:移除一张访客,若移除 %arg 则摸牌",
+ ["rfenghou__pingjian"] = "评鉴",
+ [":rfenghou__pingjian"] = "当“访客”上的无类型标签或者只有锁定技标签的技能满足发动时机时,你可以发动该技能。"..
+ "此技能的效果结束后,你须移除一张“访客”,若移除的是含有该技能的“访客”,你摸一张牌。" ..
+ '
(注:由于判断发动技能的相关机制尚不完善,请不要汇报发动技能后某些情况下访客不丢的bug)',
+
+ --CV:樰默
+ ["$rfenghou__yingmen1"] = "韩侯不顾?德高,门楣自盈。",
+ ["$rfenghou__yingmen2"] = "贫而不阿,名广,胜友满座。",
+ ["$rfenghou__pingjian1"] = "太丘道广,广则不周。仲举性峻,峻则少通。",
+ ["$rfenghou__pingjian2"] = "君生清平则为奸逆,处乱世当居豪雄。",
+ ["~rfenghou__xushao"] = "运去朋友散,满屋余风雨……",
+}
+
return extension