FreeKill/packages/standard/init.lua
YoumuKon 7fd39264ee
bugfix (#229)
- 为需要无视描述的请求添加-tmp标签(……)
- 修改铁索相关描述
- 修复了可以通过取消目标以跳过exclusive_targets的bug
- 修复了观星只控顶时还有底部标签的bug
- 修复了没有correct_func时的报错
- 修复了一个人且未分胜负时无限循环的bug
- 将AOE的函数调到了Util内方便其他DIY快速调用
- 将AskForAddTarget转正
- 主动技添加modTargetFilter,负责重新定义目标(借刀摆烂了)
- 游戏模式添加countInFunc(room),负责检测本局游戏是否可以纳入胜率统计(默认true)

---------

Co-authored-by: Nyutanislavsky <nyutanislavsky@qq.com>
2023-08-02 02:19:51 +08:00

1203 lines
37 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- SPDX-License-Identifier: GPL-3.0-or-later
local extension = Package:new("standard")
extension.metadata = require "packages.standard.metadata"
dofile "packages/standard/game_rule.lua"
dofile "packages/standard/aux_skills.lua"
local jianxiong = fk.CreateTriggerSkill{
name = "jianxiong",
anim_type = "masochism",
events = {fk.Damaged},
can_trigger = function(self, event, target, player, data)
local room = target.room
return target == player and player:hasSkill(self.name) and data.card and
table.find(data.card:isVirtual() and data.card.subcards or {data.card.id}, function(id) return room:getCardArea(id) == Card.Processing end)
end,
on_use = function(self, event, target, player, data)
local room = player.room
local dummy = Fk:cloneCard("jueying")
dummy:addSubcards(table.filter(data.card:isVirtual() and data.card.subcards or {data.card.id}, function(id) return room:getCardArea(id) == Card.Processing end))
room:obtainCard(player.id, dummy, false, fk.ReasonJustMove)
end,
}
local hujia = fk.CreateViewAsSkill{
name = "hujia$",
anim_type = "defensive",
pattern = "jink",
card_filter = function(self, to_select, selected)
return false
end,
view_as = function(self, cards)
if #cards ~= 0 then
return nil
end
local c = Fk:cloneCard("jink")
c.skillName = self.name
return c
end,
enabled_at_play = function(self, player)
return false
end,
enabled_at_response = function(self, player)
return not table.every(Fk:currentRoom().alive_players, function(p)
return p == player or p.kingdom ~= "wei"
end)
end,
}
local hujiaResponse = fk.CreateTriggerSkill{
name = "#hujiaResponse",
events = {fk.PreCardUse, fk.PreCardRespond},
mute = true,
priority = 10,
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name, true) and table.contains(data.card.skillNames, "hujia")
end,
on_cost = function(self, event, target, player, data)
local room = player.room
room:doIndicate(player.id, TargetGroup:getRealTargets(data.tos))
return true
end,
on_use = function(self, event, target, player, data)
local room = player.room
for _, p in ipairs(room:getOtherPlayers(player)) do
if p.kingdom == "wei" then
local cardResponded = room:askForResponse(p, "jink", "jink", "#hujia-ask:" .. player.id, true)
if cardResponded then
room:responseCard({
from = p.id,
card = cardResponded,
skipDrop = true,
})
data.card = cardResponded
return false
end
end
end
if event == fk.PreCardUse and player.phase == Player.Play then
room:setPlayerMark(player, "hujia-failed-phase", 1)
end
return true
end,
refresh_events = {fk.CardUsing},
can_refresh = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name, true) and player:getMark("hujia-failed-phase") > 0
end,
on_refresh = function(self, event, target, player, data)
player.room:setPlayerMark(player, "hujia-failed-phase", 0)
end,
}
hujia:addRelatedSkill(hujiaResponse)
local caocao = General:new(extension, "caocao", "wei", 4)
caocao:addSkill(jianxiong)
caocao:addSkill(hujia)
local guicai = fk.CreateTriggerSkill{
name = "guicai",
anim_type = "control",
events = {fk.AskForRetrial},
can_trigger = function(self, event, target, player, data)
return player:hasSkill(self.name) and not player:isKongcheng()
end,
on_cost = function(self, event, target, player, data)
local room = player.room
local prompt = "#guicai-ask::" .. target.id
local card = room:askForResponse(player, self.name, ".|.|.|hand", prompt, true)
if card ~= nil then
self.cost_data = card
return true
end
end,
on_use = function(self, event, target, player, data)
local room = player.room
room:retrial(self.cost_data, player, data, self.name)
end,
}
local fankui = fk.CreateTriggerSkill{
name = "fankui",
anim_type = "masochism",
events = {fk.Damaged},
can_trigger = function(self, event, target, player, data)
if target == player and player:hasSkill(self.name) and data.from and not data.from.dead then
if data.from == player then
return #player.player_cards[Player.Equip] > 0
else
return not data.from:isNude()
end
end
end,
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 card = room:askForCardChosen(player, from, flag, self.name)
room:obtainCard(player.id, card, false, fk.ReasonPrey)
end
}
local simayi = General:new(extension, "simayi", "wei", 3)
simayi:addSkill(guicai)
simayi:addSkill(fankui)
local ganglie = fk.CreateTriggerSkill{
name = "ganglie",
anim_type = "masochism",
events = {fk.Damaged},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name)
end,
on_use = function(self, event, target, player, data)
local room = player.room
local from = data.from
if from and not from.dead then room:doIndicate(player.id, {from.id}) end
local judge = {
who = player,
reason = self.name,
pattern = ".|.|^heart",
}
room:judge(judge)
if judge.card.suit ~= Card.Heart and from and not from.dead then
local discards = room:askForDiscard(from, 2, 2, false, self.name, true)
if #discards == 0 then
room:damage{
from = player,
to = from,
damage = 1,
skillName = self.name,
}
end
end
end,
}
local xiahoudun = General:new(extension, "xiahoudun", "wei", 4)
xiahoudun:addSkill(ganglie)
local tuxi = fk.CreateTriggerSkill{
name = "tuxi",
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.Draw and
table.find(player.room:getOtherPlayers(player), function(p) return not p:isKongcheng() end)
end,
on_cost = function(self, event, target, player, data)
local room = player.room
local targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
return not p:isKongcheng() end), function (p) return p.id end)
local result = room:askForChoosePlayers(player, targets, 1, 2, "#tuxi-ask", self.name)
if #result > 0 then
self.cost_data = result
return true
end
end,
on_use = function(self, event, target, player, data)
local room = player.room
for _, id in ipairs(self.cost_data) do
if player.dead then return end
local p = room:getPlayerById(id)
if not p.dead then
local c = room:askForCardChosen(player, p, "h", self.name)
room:obtainCard(player.id, c, false, fk.ReasonPrey)
end
end
return true
end,
}
local zhangliao = General:new(extension, "zhangliao", "wei", 4)
zhangliao:addSkill(tuxi)
local luoyi = fk.CreateTriggerSkill{
name = "luoyi",
anim_type = "offensive",
events = {fk.DrawNCards},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and data.n > 0
end,
on_use = function(self, event, target, player, data)
data.n = data.n - 1
end,
}
local luoyi_trigger = fk.CreateTriggerSkill{
name = "#luoyi_trigger",
mute = true,
events = {fk.DamageCaused},
can_trigger = function(self, event, target, player, data)
return target == player and player:usedSkillTimes("luoyi", Player.HistoryTurn) > 0 and
not data.chain and data.card and (data.card.trueName == "slash" or data.card.name == "duel")
end,
on_cost = function(self, event, target, player, data)
return true
end,
on_use = function(self, event, target, player, data)
local room = player.room
room:broadcastSkillInvoke("luoyi")
room:notifySkillInvoked(player, "luoyi")
data.damage = data.damage + 1
end,
}
local xuchu = General:new(extension, "xuchu", "wei", 4)
luoyi:addRelatedSkill(luoyi_trigger)
xuchu:addSkill(luoyi)
local tiandu = fk.CreateTriggerSkill{
name = "tiandu",
anim_type = "drawcard",
events = {fk.FinishJudge},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and player.room:getCardArea(data.card) == Card.Processing
end,
on_use = function(self, event, target, player, data)
player.room:obtainCard(player.id, data.card, true, fk.ReasonJustMove)
end,
}
local yiji = fk.CreateTriggerSkill{
name = "yiji",
anim_type = "masochism",
events = {fk.Damaged},
on_trigger = function(self, event, target, player, data)
self.cancel_cost = false
for i = 1, data.damage do
if self.cancel_cost then break end
self:doCost(event, target, player, data)
end
end,
on_cost = function(self, event, target, player, data)
local room = player.room
if room:askForSkillInvoke(player, self.name, data) then
return true
end
self.cancel_cost = true
end,
on_use = function(self, event, target, player, data)
-- TODO: yiji logic
player:drawCards(2)
end,
}
local guojia = General:new(extension, "guojia", "wei", 3)
guojia:addSkill(tiandu)
guojia:addSkill(yiji)
local luoshen = fk.CreateTriggerSkill{
name = "luoshen",
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.Start
end,
on_use = function(self, event, target, player, data)
local room = player.room
while true do
local judge = {
who = player,
reason = self.name,
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
break
end
end
end,
}
local qingguo = fk.CreateViewAsSkill{
name = "qingguo",
anim_type = "defensive",
pattern = "jink",
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.Equip
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
end
local c = Fk:cloneCard("jink")
c.skillName = self.name
c:addSubcard(cards[1])
return c
end,
}
local zhenji = General:new(extension, "zhenji", "wei", 3, 3, General.Female)
zhenji:addSkill(luoshen)
zhenji:addSkill(qingguo)
local rende = fk.CreateActiveSkill{
name = "rende",
anim_type = "support",
card_filter = function(self, to_select, selected)
return Fk:currentRoom():getCardArea(to_select) ~= Card.PlayerEquip
end,
target_filter = function(self, to_select, selected)
return #selected == 0 and to_select ~= Self.id
end,
target_num = 1,
min_card_num = 1,
on_use = function(self, room, effect)
local target = room:getPlayerById(effect.tos[1])
local player = room:getPlayerById(effect.from)
local cards = effect.cards
local marks = player:getMark("_rende_cards-phase")
local dummy = Fk:cloneCard'slash'
dummy:addSubcards(cards)
room:obtainCard(target.id, dummy, false, fk.ReasonGive)
room:addPlayerMark(player, "_rende_cards-phase", #cards)
if marks < 2 and marks + #cards >= 2 and player:isWounded() then
room:recover{
who = player,
num = 1,
recoverBy = player,
skillName = self.name
}
end
end,
}
local jijiang = fk.CreateViewAsSkill{
name = "jijiang$",
anim_type = "offensive",
pattern = "slash",
card_filter = function(self, to_select, selected)
return false
end,
view_as = function(self, cards)
if #cards ~= 0 then
return nil
end
local c = Fk:cloneCard("slash")
c.skillName = self.name
return c
end,
enabled_at_play = function(self, player)
return player:getMark("jijiang-failed-phase") == 0 and not table.every(Fk:currentRoom().alive_players, function(p)
return p == player or p.kingdom ~= "shu"
end)
end,
enabled_at_response = function(self, player)
return not table.every(Fk:currentRoom().alive_players, function(p)
return p == player or p.kingdom ~= "shu"
end)
end,
}
local jijiangResponse = fk.CreateTriggerSkill{
name = "#jijiangResponse",
events = {fk.PreCardUse, fk.PreCardRespond},
mute = true,
priority = 10,
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name, true) and table.contains(data.card.skillNames, "jijiang")
end,
on_cost = function(self, event, target, player, data)
local room = player.room
room:doIndicate(player.id, TargetGroup:getRealTargets(data.tos))
return true
end,
on_use = function(self, event, target, player, data)
local room = player.room
for _, p in ipairs(room:getOtherPlayers(player)) do
if p.kingdom == "shu" then
local cardResponded = room:askForResponse(p, "slash", "slash", "#jijiang-ask:" .. player.id, true)
if cardResponded then
room:responseCard({
from = p.id,
card = cardResponded,
skipDrop = true,
})
data.card = cardResponded
return false
end
end
end
if event == fk.PreCardUse and player.phase == Player.Play then
room:setPlayerMark(player, "jijiang-failed-phase", 1)
end
return true
end,
refresh_events = {fk.CardUsing},
can_refresh = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name, true) and player:getMark("jijiang-failed-phase") > 0
end,
on_refresh = function(self, event, target, player, data)
player.room:setPlayerMark(player, "jijiang-failed-phase", 0)
end,
}
jijiang:addRelatedSkill(jijiangResponse)
local liubei = General:new(extension, "liubei", "shu", 4)
liubei:addSkill(rende)
liubei:addSkill(jijiang)
local wusheng = fk.CreateViewAsSkill{
name = "wusheng",
anim_type = "offensive",
pattern = "slash",
card_filter = function(self, to_select, selected)
if #selected == 1 then return false end
return Fk:getCardById(to_select).color == Card.Red
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
end
local c = Fk:cloneCard("slash")
c.skillName = self.name
c:addSubcard(cards[1])
return c
end,
}
local guanyu = General:new(extension, "guanyu", "shu", 4)
guanyu:addSkill(wusheng)
local paoxiaoAudio = fk.CreateTriggerSkill{
name = "#paoxiaoAudio",
refresh_events = {fk.CardUsing},
can_refresh = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
data.card.trueName == "slash" and
player:usedCardTimes("slash") > 1
end,
on_refresh = function(self, event, target, player, data)
player.room:broadcastSkillInvoke("paoxiao")
player.room:doAnimate("InvokeSkill", {
name = "paoxiao",
player = player.id,
skill_type = "offensive",
})
end,
}
local paoxiao = fk.CreateTargetModSkill{
name = "paoxiao",
bypass_times = function(self, player, skill, scope)
if player:hasSkill(self.name) and skill.trueName == "slash_skill"
and scope == Player.HistoryPhase then
return true
end
end,
}
paoxiao:addRelatedSkill(paoxiaoAudio)
local zhangfei = General:new(extension, "zhangfei", "shu", 4)
zhangfei:addSkill(paoxiao)
local guanxing = fk.CreateTriggerSkill{
name = "guanxing",
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.Start
end,
on_use = function(self, event, target, player, data)
local room = player.room
room:askForGuanxing(player, room:getNCards(math.min(5, #room.alive_players)))
end,
}
local kongchengAudio = fk.CreateTriggerSkill{
name = "#kongchengAudio",
refresh_events = {fk.AfterCardsMove},
can_refresh = function(self, event, target, player, data)
if not player:hasSkill(self.name) then return end
if not player:isKongcheng() then return end
for _, move in ipairs(data) do
if move.from == player.id then
for _, info in ipairs(move.moveInfo) do
if info.fromArea == Card.PlayerHand then
return true
end
end
end
end
end,
on_refresh = function(self, event, target, player, data)
player.room:broadcastSkillInvoke("kongcheng")
player.room:notifySkillInvoked(player, "kongcheng", "defensive")
end,
}
local kongcheng = fk.CreateProhibitSkill{
name = "kongcheng",
frequency = Skill.Compulsory,
is_prohibited = function(self, from, to, card)
if to:hasSkill(self.name) and to:isKongcheng() then
return card.trueName == "slash" or card.trueName == "duel"
end
end,
}
kongcheng:addRelatedSkill(kongchengAudio)
local zhugeliang = General:new(extension, "zhugeliang", "shu", 3)
zhugeliang:addSkill(guanxing)
zhugeliang:addSkill(kongcheng)
local longdan = fk.CreateViewAsSkill{
name = "longdan",
pattern = "slash,jink",
card_filter = function(self, to_select, selected)
if #selected == 1 then return false end
local _c = Fk:getCardById(to_select)
local c
if _c.trueName == "slash" then
c = Fk:cloneCard("jink")
elseif _c.name == "jink" then
c = Fk:cloneCard("slash")
else
return false
end
return (Fk.currentResponsePattern == nil and c.skill:canUse(Self)) or (Fk.currentResponsePattern and Exppattern:Parse(Fk.currentResponsePattern):match(c))
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
end
local _c = Fk:getCardById(cards[1])
local c
if _c.trueName == "slash" then
c = Fk:cloneCard("jink")
elseif _c.name == "jink" then
c = Fk:cloneCard("slash")
end
c.skillName = self.name
c:addSubcard(cards[1])
return c
end,
}
local zhaoyun = General:new(extension, "zhaoyun", "shu", 4)
zhaoyun:addSkill(longdan)
local mashu = fk.CreateDistanceSkill{
name = "mashu",
frequency = Skill.Compulsory,
correct_func = function(self, from, to)
if from:hasSkill(self.name) then
return -1
end
end,
}
local tieqi = fk.CreateTriggerSkill{
name = "tieqi",
anim_type = "offensive",
events = {fk.TargetSpecified},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
data.card.trueName == "slash"
end,
on_use = function(self, event, target, player, data)
local room = player.room
local judge = {
who = player,
reason = self.name,
pattern = ".|.|heart,diamond",
}
room:judge(judge)
if judge.card.color == Card.Red then
data.disresponsive = true
end
end,
}
local machao = General:new(extension, "machao", "shu", 4)
machao:addSkill(mashu)
machao:addSkill(tieqi)
local jizhi = fk.CreateTriggerSkill{
name = "jizhi",
anim_type = "drawcard",
events = {fk.CardUsing},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and data.card:isCommonTrick()
end,
on_use = function(self, event, target, player, data)
player:drawCards(1, self.name)
end,
}
local qicai = fk.CreateTargetModSkill{
name = "qicai",
frequency = Skill.Compulsory,
bypass_distances = function(self, player, skill, card)
return player:hasSkill(self.name) and card and card.type == Card.TypeTrick
end,
}
local huangyueying = General:new(extension, "huangyueying", "shu", 3, 3, General.Female)
huangyueying:addSkill(jizhi)
huangyueying:addSkill(qicai)
local zhiheng = fk.CreateActiveSkill{
name = "zhiheng",
anim_type = "drawcard",
can_use = function(self, player)
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
end,
target_num = 0,
min_card_num = 1,
on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from)
room:throwCard(effect.cards, self.name, from, from)
from:drawCards(#effect.cards, self.name)
end
}
local jiuyuan = fk.CreateTriggerSkill{
name = "jiuyuan$",
anim_type = "support",
frequency = Skill.Compulsory,
events = {fk.PreHpRecover},
can_trigger = function(self, event, target, player, data)
return
target == player and
player:hasSkill(self.name) and
data.card and
data.card.trueName == "peach" and
data.recoverBy and
data.recoverBy.kingdom == "wu" and
data.recoverBy ~= player
end,
on_use = function(self, event, target, player, data)
data.num = data.num + 1
end,
}
local sunquan = General:new(extension, "sunquan", "wu", 4)
sunquan:addSkill(zhiheng)
sunquan:addSkill(jiuyuan)
local qixi = fk.CreateViewAsSkill{
name = "qixi",
anim_type = "control",
pattern = "dismantlement",
card_filter = function(self, to_select, selected)
if #selected == 1 then return false end
return Fk:getCardById(to_select).color == Card.Black
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
end
local c = Fk:cloneCard("dismantlement")
c.skillName = self.name
c:addSubcard(cards[1])
return c
end,
}
local ganning = General:new(extension, "ganning", "wu", 4)
ganning:addSkill(qixi)
local keji = fk.CreateTriggerSkill{
name = "keji",
anim_type = "defensive",
events = {fk.EventPhaseChanging},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
data.to == Player.Discard and
player:usedCardTimes("slash") < 1 and
player:getMark("_keji_played_slash") == 0
end,
on_use = function(self, event, target, player, data)
return true
end,
refresh_events = {fk.CardResponding, fk.EventPhaseStart},
can_refresh = function(self, event, target, player, data)
if not (target == player and player:hasSkill(self.name)) then
return false
end
if event == fk.CardResponding then
return player.phase == Player.Play and data.card.trueName == "slash"
elseif event == fk.EventPhaseStart then
return player.phase == Player.NotActive
end
end,
on_refresh = function(self, event, target, player, data)
local room = player.room
if event == fk.CardResponding then
room:addPlayerMark(player, "_keji_played_slash", 1)
elseif event == fk.EventPhaseStart then
room:setPlayerMark(player, "_keji_played_slash", 0)
end
end
}
local lvmeng = General:new(extension, "lvmeng", "wu", 4)
lvmeng:addSkill(keji)
local kurou = fk.CreateActiveSkill{
name = "kurou",
anim_type = "drawcard",
card_filter = function(self, to_select, selected, selected_targets)
return false
end,
on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from)
room:loseHp(from, 1, self.name)
if from:isAlive() then
from:drawCards(2, self.name)
end
end
}
local huanggai = General:new(extension, "huanggai", "wu", 4)
huanggai:addSkill(kurou)
local yingzi = fk.CreateTriggerSkill{
name = "yingzi",
anim_type = "drawcard",
events = {fk.DrawNCards},
on_use = function(self, event, target, player, data)
data.n = data.n + 1
end,
}
local fanjian = fk.CreateActiveSkill{
name = "fanjian",
can_use = function(self, player)
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0 and not player:isKongcheng()
end,
card_filter = function() return false end,
target_filter = function(self, to_select, selected)
return #selected == 0 and to_select ~= Self.id
end,
target_num = 1,
on_use = function(self, room, effect)
local player = room:getPlayerById(effect.from)
local target = room:getPlayerById(effect.tos[1])
local choice = room:askForChoice(target, {"spade", "heart", "club", "diamond"}, self.name)
local card = room:askForCardChosen(target, player, 'h', self.name)
room:obtainCard(target.id, card, true, fk.ReasonPrey)
if Fk:getCardById(card):getSuitString() ~= choice then
room:damage{
from = player,
to = target,
damage = 1,
skillName = self.name,
}
end
end,
}
local zhouyu = General:new(extension, "zhouyu", "wu", 3)
zhouyu:addSkill(yingzi)
zhouyu:addSkill(fanjian)
local guose = fk.CreateViewAsSkill{
name = "guose",
anim_type = "control",
pattern = "indulgence",
card_filter = function(self, to_select, selected)
if #selected == 1 then return false end
return Fk:getCardById(to_select).suit == Card.Diamond
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
end
local c = Fk:cloneCard("indulgence")
c.skillName = self.name
c:addSubcard(cards[1])
return c
end,
}
local liuli = fk.CreateTriggerSkill{
name = "liuli",
anim_type = "defensive",
events = {fk.TargetConfirming},
can_trigger = function(self, event, target, player, data)
local ret = target == player and player:hasSkill(self.name) and
data.card.trueName == "slash"
if ret then
self.target_list = {}
local room = player.room
for _, p in ipairs(room:getOtherPlayers(player)) do
if p.id ~= data.from and player:inMyAttackRange(p) then
table.insert(self.target_list, p.id)
end
end
return #self.target_list > 0
end
end,
on_cost = function(self, event, target, player, data)
local room = player.room
local prompt = "#liuli-target"
local plist, cid = room:askForChooseCardAndPlayers(player, self.target_list, 1, 1, nil, prompt, self.name, true)
if #plist > 0 then
self.cost_data = {plist[1], cid}
return true
end
end,
on_use = function(self, event, target, player, data)
local room = player.room
local to = self.cost_data[1]
room:doIndicate(player.id, { to })
room:throwCard(self.cost_data[2], self.name, player, player)
TargetGroup:removeTarget(data.targetGroup, player.id)
TargetGroup:pushTargets(data.targetGroup, to)
end,
}
local daqiao = General:new(extension, "daqiao", "wu", 3, 3, General.Female)
daqiao:addSkill(guose)
daqiao:addSkill(liuli)
local qianxun = fk.CreateProhibitSkill{
name = "qianxun",
frequency = Skill.Compulsory,
is_prohibited = function(self, from, to, card)
if to:hasSkill(self.name) then
return card.name == "indulgence" or card.name == "snatch"
end
end,
}
local lianying = fk.CreateTriggerSkill{
name = "lianying",
anim_type = "drawcard",
events = {fk.AfterCardsMove},
can_trigger = function(self, event, target, player, data)
if not player:hasSkill(self.name) then return end
if not player:isKongcheng() then return end
for _, move in ipairs(data) do
if move.from == player.id then
for _, info in ipairs(move.moveInfo) do
if info.fromArea == Card.PlayerHand then
return true
end
end
end
end
end,
on_use = function(self, event, target, player, data)
player:drawCards(1, self.name)
end,
}
local luxun = General:new(extension, "luxun", "wu", 3)
luxun:addSkill(qianxun)
luxun:addSkill(lianying)
local xiaoji = fk.CreateTriggerSkill{
name = "xiaoji",
anim_type = "drawcard",
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
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
end
end,
on_use = function(self, event, target, player, data)
player:drawCards(2, self.name)
end,
}
local jieyin = fk.CreateActiveSkill{
name = "jieyin",
anim_type = "support",
can_use = function(self, player)
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
end,
card_filter = function(self, to_select, selected)
return #selected < 2 and Fk:currentRoom():getCardArea(to_select) ~= Player.Equip
end,
target_filter = function(self, to_select, selected)
local target = Fk:currentRoom():getPlayerById(to_select)
return target:isWounded() and
target.gender == General.Male
and #selected < 1
end,
target_num = 1,
card_num = 2,
on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from)
room:throwCard(effect.cards, self.name, from, from)
room:recover({
who = room:getPlayerById(effect.tos[1]),
num = 1,
recoverBy = room:getPlayerById(effect.from),
skillName = self.name
})
if from:isWounded() then
room:recover({
who = room:getPlayerById(effect.from),
num = 1,
recoverBy = room:getPlayerById(effect.from),
skillName = self.name
})
end
end
}
local sunshangxiang = General:new(extension, "sunshangxiang", "wu", 3, 3, General.Female)
sunshangxiang:addSkill(xiaoji)
sunshangxiang:addSkill(jieyin)
local qingnang = fk.CreateActiveSkill{
name = "qingnang",
anim_type = "support",
can_use = function(self, player)
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
end,
card_filter = function(self, to_select, selected, targets)
return #selected == 0 and Fk:currentRoom():getCardArea(to_select) ~= Player.Equip
end,
target_filter = function(self, to_select, selected, cards)
return #selected == 0 and Fk:currentRoom():getPlayerById(to_select):isWounded()
end,
target_num = 1,
card_num = 1,
on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from)
room:throwCard(effect.cards, self.name, from, from)
room:recover({
who = room:getPlayerById(effect.tos[1]),
num = 1,
recoverBy = room:getPlayerById(effect.from),
skillName = self.name
})
end,
}
local jijiu = fk.CreateViewAsSkill{
name = "jijiu",
anim_type = "support",
pattern = "peach",
card_filter = function(self, to_select, selected)
if #selected == 1 then return false end
return Fk:getCardById(to_select).color == Card.Red
end,
view_as = function(self, cards)
if #cards ~= 1 then
return nil
end
local c = Fk:cloneCard("peach")
c.skillName = self.name
c:addSubcard(cards[1])
return c
end,
enabled_at_play = function(self, player)
return false
end,
enabled_at_response = function(self, player)
return player.phase == Player.NotActive
end,
}
local huatuo = General:new(extension, "huatuo", "qun", 3)
huatuo:addSkill(qingnang)
huatuo:addSkill(jijiu)
local wushuang = fk.CreateTriggerSkill{
name = "wushuang",
anim_type = "offensive",
frequency = Skill.Compulsory,
events = {fk.TargetSpecified, fk.TargetConfirmed},
can_trigger = function(self, event, target, player, data)
if not player:hasSkill(self.name) then
return false
end
if event == fk.TargetSpecified then
return target == player and table.contains({ "slash", "duel" }, data.card.trueName)
else
return data.to == player.id and data.card.trueName == "duel"
end
end,
on_use = function(self, event, target, player, data)
data.fixedResponseTimes = data.fixedResponseTimes or {}
if data.card.trueName == "slash" then
data.fixedResponseTimes["jink"] = 2
else
data.fixedResponseTimes["slash"] = 2
data.fixedAddTimesResponsors = data.fixedAddTimesResponsors or {}
table.insert(data.fixedAddTimesResponsors, (event == fk.TargetSpecified and data.to or data.from))
end
end,
}
local lvbu = General:new(extension, "lvbu", "qun", 4)
lvbu:addSkill(wushuang)
local lijian = fk.CreateActiveSkill{
name = "lijian",
anim_type = "offensive",
can_use = function(self, player)
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
end,
card_filter = function(self, to_select, selected)
return #selected == 0
end,
target_filter = function(self, to_select, selected)
return #selected < 2 and to_select ~= Self.id and
Fk:currentRoom():getPlayerById(to_select).gender == General.Male
end,
target_num = 2,
min_card_num = 1,
on_use = function(self, room, use)
local player = room:getPlayerById(use.from)
room:throwCard(use.cards, self.name, player, player)
local duel = Fk:cloneCard("duel")
duel.skillName = self.name
local new_use = { ---@type CardUseStruct
from = use.tos[2],
tos = { { use.tos[1] } },
card = duel,
prohibitedCardNames = { "nullification" },
}
room:useCard(new_use)
end,
}
local biyue = fk.CreateTriggerSkill{
name = "biyue",
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.Finish
end,
on_use = function(self, event, target, player, data)
player:drawCards(1, self.name)
end,
}
local diaochan = General:new(extension, "diaochan", "qun", 3, 3, General.Female)
diaochan:addSkill(lijian)
diaochan:addSkill(biyue)
local role_mode = fk.CreateGameMode{
name = "aaa_role_mode", -- just to let it at the top of list
minPlayer = 2,
maxPlayer = 8,
countInFunc = function(self, room)
return #room.players >= 5
end,
surrender_func = function(self, playedTime)
local roleCheck = false
local roleText = ""
local roleTable = {
{ "lord" },
{ "lord", "rebel" },
{ "lord", "rebel", "renegade" },
{ "lord", "loyalist", "rebel", "renegade" },
{ "lord", "loyalist", "rebel", "rebel", "renegade" },
{ "lord", "loyalist", "rebel", "rebel", "rebel", "renegade" },
{ "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "renegade" },
{ "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
}
roleTable = roleTable[#Fk:currentRoom().players]
if Self.role == "renegade" then
local rebelNum = #table.filter(roleTable, function(role)
return role == "rebel"
end)
for _, p in ipairs(Fk:currentRoom().players) do
if p.role == "rebel" then
if not p.dead then
break
else
rebelNum = rebelNum - 1
end
end
end
roleCheck = rebelNum == 0
roleText = "left lord and loyalist alive"
elseif Self.role == "rebel" then
local rebelNum = #table.filter(roleTable, function(role)
return role == "rebel"
end)
local renegadeDead = not table.find(roleTable, function(role)
return role == "renegade"
end)
for _, p in ipairs(Fk:currentRoom().players) do
if p.role == "renegade" and p.dead then
renegadeDead = true
end
if p ~= Self and p.role == "rebel" then
if not p.dead then
break
else
rebelNum = rebelNum - 1
end
end
end
roleCheck = renegadeDead and rebelNum == 1
roleText = "left one rebel alive"
else
if Self.role == "loyalist" then
return { { text = "loyalist never surrender", passed = false } }
else
if #Fk:currentRoom().alive_players == 2 then
roleCheck = true
else
local lordNum = #table.filter(roleTable, function(role)
return role == "lord" or role == "loyalist"
end)
local renegadeDead = not table.find(roleTable, function(role)
return role == "renegade"
end)
for _, p in ipairs(Fk:currentRoom().players) do
if p.role == "renegade" and p.dead then
renegadeDead = true
end
if p ~= Self and (p.role == "lord" or p.role == "loyalist") then
if not p.dead then
break
else
lordNum = lordNum - 1
end
end
end
roleCheck = renegadeDead and lordNum == 1
end
end
roleText = "left you alive"
end
return {
{ text = "time limitation: 5 min", passed = playedTime >= 300 },
{ text = roleText, passed = roleCheck },
}
end,
}
extension:addGameMode(role_mode)
Fk:loadTranslationTable{
["time limitation: 5 sec"] = "游戏时长达到5秒测试用",
["left lord and loyalist alive"] = "仅剩你和主忠方存活",
["left one rebel alive"] = "反贼仅剩你存活且不存在存活内奸",
["left you alive"] = "主忠方仅剩你存活且其他阵营仅剩一方",
["loyalist never surrender"] = "忠臣永不投降!",
}
local anjiang = General(extension, "anjiang", "unknown", 5)
anjiang.gender = General.Agender
anjiang.total_hidden = true
Fk:loadTranslationTable{
["anjiang"] = "暗将",
}
local heg_mode = require "packages.standard.hegemony"
extension:addGameMode(heg_mode)
-- load translations of this package
dofile "packages/standard/i18n/init.lua"
return extension