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

---------

Co-authored-by: Nyutanislavsky <nyutanislavsky@qq.com>
This commit is contained in:
YoumuKon 2023-08-02 02:19:51 +08:00 committed by GitHub
parent 21fee5537a
commit 7fd39264ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 243 additions and 115 deletions

View File

@ -551,6 +551,12 @@ function updateSelectedTargets(playerid, selected) {
[card, id, selected_targets]
));
photo.selectable = ret;
if (roomScene.extra_data instanceof Object) {
const exclusived = roomScene.extra_data.exclusive_targets;
if (exclusived instanceof Array) {
if (exclusived.indexOf(id) === -1) photo.selectable = false;
}
}
})
okButton.enabled = JSON.parse(Backend.callLuaFunction(
@ -834,11 +840,17 @@ callbacks["AskForGuanxing"] = (jsonData) => {
box.areaCapacities = [max_bottom_cards];
box.areaLimits = [min_bottom_cards];
box.areaNames = [Backend.translate(bottom_area_name)];
} else {
if (max_bottom_cards === 0) {
box.areaCapacities = [max_top_cards];
box.areaLimits = [min_top_cards];
box.areaNames = [Backend.translate(top_area_name)];
} else {
box.areaCapacities = [max_top_cards, max_bottom_cards];
box.areaLimits = [min_top_cards, min_bottom_cards];
box.areaNames = [Backend.translate(top_area_name), Backend.translate(bottom_area_name)];
}
}
box.cards = cards;
box.arrangeCards();
box.accepted.connect(() => {
@ -906,7 +918,7 @@ callbacks["AskForChoice"] = (jsonData) => {
box.skill_name = skill_name;
box.all_options = all_choices;
box.accepted.connect(() => {
replyToServer(choices[box.result]);
replyToServer(all_choices[box.result]);
});
}

View File

@ -45,7 +45,7 @@ MetroButton {
box.options = choices;
box.all_options = all_choices;
box.accepted.connect(() => {
answer = choices[box.result];
answer = all_choices[box.result];
});
}

View File

@ -276,8 +276,8 @@ Fk:loadTranslationTable{
["phase_finish"] = "结束阶段",
["chained"] = "横置",
["un-chained"] = "",
["reset-general"] = "重置",
["un-chained"] = "",
["reset-general"] = "复原",
["yang"] = "",
["yin"] = "",
@ -391,7 +391,6 @@ Fk:loadTranslationTable{
["#GuanxingResult"] = "%from 的观星结果为 %arg 上 %arg2 下",
["#ChainStateChange"] = "%from %arg 了武将牌",
["#ChainDamage"] = "%from 处于连环状态,将受到传导的伤害",
["#ResetGeneral"] = "%from 复原了武将牌",
}
-- card footnote

View File

@ -61,4 +61,10 @@ function GameMode:surrenderFunc(playedTime)
return {}
end
---@param room Room @ 游戏房间
---@return boolean
function GameMode:countInFunc(room)
return true
end
return GameMode

View File

@ -50,6 +50,17 @@ function ActiveSkill:targetFilter(to_select, selected, selected_cards, card)
return false
end
--- Determine whether a target can be selected by this skill(in modifying targets)
--- only used in skill of players
---@param to_select integer @ id of the target
---@param selected integer[] @ ids of selected targets
---@param user integer @ id of the userdata
---@param card Card @ helper
---@param distance_limited boolean @ is limited by distance
function ActiveSkill:modTargetFilter(to_select, selected, user, card, distance_limited)
return false
end
function ActiveSkill:getMinTargetNum()
local ret
if self.target_num then ret = self.target_num

View File

@ -35,13 +35,15 @@ function UsableSkill:withinTimesLimit(player, scope, card, card_name, to)
if skill:bypassTimesCheck(player, self, scope, card, to) then return true end
end
card_name = card_name or card.trueName
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
table.insert(temp_suf, "-tmp")
return player:usedCardTimes(card_name, scope) < self:getMaxUseTime(player, scope, card, to) or
(player:getMark(MarkEnum.BypassTimesLimit) ~= 0 or
table.find(MarkEnum.TempMarkSuffix, function(s)
table.find(temp_suf, function(s)
return player:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
end)) or
(to:getMark(MarkEnum.BypassTimesLimitTo) ~= 0 or
table.find(MarkEnum.TempMarkSuffix, function(s)
table.find(temp_suf, function(s)
return to:getMark(MarkEnum.BypassTimesLimitTo .. s) ~= 0
end))
end
@ -55,13 +57,15 @@ function UsableSkill:withinDistanceLimit(player, isattack, card, to)
for _, skill in ipairs(status_skills) do
if skill:bypassDistancesCheck(player, self, card, to) then return true end
end
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
table.insert(temp_suf, "-tmp")
return isattack and player:inMyAttackRange(to, self:getDistanceLimit(player, card, to)) or player:distanceTo(to) <= self:getDistanceLimit(player, card, to) or
(player:getMark(MarkEnum.BypassDistancesLimit) ~= 0 or
table.find(MarkEnum.TempMarkSuffix, function(s)
table.find(temp_suf, function(s)
return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
end)) or
(to:getMark(MarkEnum.BypassDistancesLimitTo) ~= 0 or
table.find(MarkEnum.TempMarkSuffix, function(s)
table.find(temp_suf, function(s)
return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0
end))
end

View File

@ -103,6 +103,47 @@ Util.NameMapper = function(e) return e.name end
Util.Name2GeneralMapper = function(e) return Fk.generals[e] end
Util.Name2SkillMapper = function(e) return Fk.skills[e] end
-- for card preset
Util.GlobalCanUse = function(self, player, card)
local room = Fk:currentRoom()
for _, p in ipairs(room.alive_players) do
if not (card and player:isProhibited(p, card)) then
return true
end
end
end
Util.AoeCanUse = function(self, player, card)
local room = Fk:currentRoom()
for _, p in ipairs(room.alive_players) do
if p ~= player and not (card and player:isProhibited(p, card)) then
return true
end
end
end
Util.GlobalOnUse = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getAlivePlayers()) do
if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end
end
Util.AoeOnUse = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getOtherPlayers(room:getPlayerById(cardUseEvent.from))) do
if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end
end
---@generic T
---@param self T[]
---@return T[]

View File

@ -170,6 +170,7 @@ end
---@field public about_to_effect fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean|nil
---@field public on_effect fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean|nil
---@field public on_nullified fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean|nil
---@field public mod_target_filter fun(self: ActiveSkill, to_select: integer, selected: integer[], user: integer, card: Card, distance_limited: boolean): boolean|nil
---@field public prompt fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): string
---@param spec ActiveSkillSpec
@ -186,6 +187,7 @@ function fk.CreateActiveSkill(spec)
end
if spec.card_filter then skill.cardFilter = spec.card_filter end
if spec.target_filter then skill.targetFilter = spec.target_filter end
if spec.mod_target_filter then skill.modTargetFilter = spec.mod_target_filter end
if spec.feasible then
print(spec.name .. ": feasible is deprecated. Use target_num and card_num instead.")
skill.feasible = spec.feasible
@ -274,7 +276,7 @@ end
---@return DistanceSkill
function fk.CreateDistanceSkill(spec)
assert(type(spec.name) == "string")
assert(type(spec.correct_func) == "function")
assert(type(spec.correct_func) == "function" or type(spec.fixed_func) == "function")
local skill = DistanceSkill:new(spec.name)
readStatusSpecToSkill(skill, spec)
@ -556,5 +558,9 @@ function fk.CreateGameMode(spec)
assert(type(spec.surrender_func) == "function")
ret.surrenderFunc = spec.surrender_func
end
if spec.is_counted then
assert(type(spec.is_counted) == "function")
ret.countInFunc = spec.is_counted
end
return ret
end

View File

@ -155,7 +155,7 @@ GameEvent.functions[GameEvent.Round] = function(self)
GameEvent(GameEvent.Turn):exec()
if room.game_finished then break end
room.current = room.current:getNextAlive()
until p.seat > p:getNextAlive().seat
until p.seat >= p:getNextAlive().seat
logic:trigger(fk.RoundEnd, p)
end

View File

@ -105,23 +105,7 @@ function GameLogic:chooseGenerals()
end
room:setPlayerGeneral(lord, lord_general, true)
if lord.kingdom == "god" or Fk.generals[lord_general].subkingdom then
local allKingdoms = {}
if lord.kingdom == "god" then
allKingdoms = table.simpleClone(Fk.kingdoms)
local exceptedKingdoms = { "god" }
for _, kingdom in ipairs(exceptedKingdoms) do
table.removeOne(allKingdoms, kingdom)
end
else
local curGeneral = Fk.generals[lord_general]
allKingdoms = { curGeneral.kingdom, curGeneral.subkingdom }
end
lord.kingdom = room:askForChoice(lord, allKingdoms, "AskForKingdom", "#ChooseInitialKingdom")
room:broadcastProperty(lord, "kingdom")
end
room:askForChooseKingdom({lord})
room:broadcastProperty(lord, "general")
room:setDeputyGeneral(lord, deputy)
room:broadcastProperty(lord, "deputyGeneral")

View File

@ -19,18 +19,18 @@ MarkEnum.MinusMaxCards = "MinusMaxCards"
--于本回合内减少标记值数量的手牌上限
MarkEnum.MinusMaxCardsInTurn = "MinusMaxCards-turn"
--使用牌无次数限制,可带清除标记后缀
---使用牌无次数限制,可带清除标记后缀-tmp为请求专用
MarkEnum.BypassTimesLimit = "BypassTimesLimit"
--使用牌无距离限制,可带清除标记后缀
---使用牌无距离限制,可带清除标记后缀-tmp为请求专用
MarkEnum.BypassDistancesLimit = "BypassDistancesLimit"
--对其使用牌无次数限制,可带清除标记后缀
---对其使用牌无次数限制,可带清除标记后缀
MarkEnum.BypassTimesLimitTo = "BypassTimesLimitTo"
--对其使用牌无距离限制,可带清除标记后缀
---对其使用牌无距离限制,可带清除标记后缀
MarkEnum.BypassDistancesLimitTo = "BypassDistancesLimitTo"
--非锁定技失效,可带清除标记后缀
---非锁定技失效,可带清除标记后缀
MarkEnum.UncompulsoryInvalidity = "UncompulsoryInvalidity"
--各种清除标记后缀
---各种清除标记后缀
MarkEnum.TempMarkSuffix = { "-phase", "-turn", "-round" }
---卡牌标记版本的清除标记后缀

View File

@ -1453,6 +1453,60 @@ function Room:askForSkillInvoke(player, skill_name, data, prompt)
return invoked
end
--枚举法为使用牌重选目标(无距离限制)
---@param player ServerPlayer @ 执行的玩家
---@param targets ServerPlayer[] @ 可选的目标范围
---@param num integer @ 可选的目标数
---@param can_minus boolean @ 是否可减少
---@param distance_limited boolean @ 是否受距离限制
---@param prompt string @ 提示信息
---@param skillName string @ 技能名
---@param data CardUseStruct @ 使用数据
function Room:askForAddTarget(player, targets, num, can_minus, distance_limited, prompt, skillName, data)
num = num or 1
can_minus = can_minus or false
prompt = prompt or ""
skillName = skillName or ""
local room = player.room
local tos = {}
local orig_tos = table.simpleClone(AimGroup:getAllTargets(data.tos))
if can_minus and #orig_tos > 1 then --默认不允许减目标至0
tos = table.map(table.filter(targets, function(p)
return table.contains(AimGroup:getAllTargets(data.tos), p.id) end), Util.IdMapper)
end
for _, p in ipairs(targets) do
if not table.contains(AimGroup:getAllTargets(data.tos), p.id) and not room:getPlayerById(data.from):isProhibited(p, data.card) then
if data.card.skill:modTargetFilter(p.id, orig_tos, player.id, data.card, distance_limited) then
table.insertIfNeed(tos, p.id)
end
end
end
if #tos > 0 then
tos = room:askForChoosePlayers(player, tos, 1, num, prompt, skillName, true)
--借刀……!
if data.card.name ~= "collateral" then
return tos
else
local result = {}
for _, id in ipairs(tos) do
local to = room:getPlayerById(id)
local target = room:askForChoosePlayers(player, table.map(table.filter(room:getOtherPlayers(player), function(v)
return to:inMyAttackRange(v) end), function(p) return p.id end), 1, 1,
"#collateral-choose::"..to.id..":"..data.card:toLogString(), "collateral_skill", true)
if #target > 0 then
table.insert(result, {id, target[1]})
end
end
if #result > 0 then
return result
else
return {}
end
end
end
return {}
end
-- TODO: guanxing type
--- 询问玩家对若干牌进行观星。
---
@ -1462,7 +1516,7 @@ end
---@param top_limit integer[]|nil @ 置于牌堆顶的牌的限制(下限,上限),不填写则不限
---@param bottom_limit integer[]|nil @ 置于牌堆底的牌的限制(下限,上限),不填写则不限
---@param customNotify string|null @ 自定义读条操作提示
--@param prompt string|null @ 观星框的标题(暂时雪藏)
---param prompt string|null @ 观星框的标题(暂时雪藏)
---@param noPut boolean|null @ 是否进行放置牌操作
---@param areaNames string[]|null @ 左侧提示信息
---@return table<"top"|"bottom", integer[]>
@ -1666,10 +1720,10 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
if extra_data then
if extra_data.bypass_distances then
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit, 1)
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 1)
end
if extra_data.bypass_times then
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit, 1)
if extra_data.bypass_times == nil or extra_data.bypass_times then
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 1)
end
end
local command = "AskForUseCard"
@ -1689,8 +1743,8 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
self.logic:trigger(fk.AskForCardUse, player, askForUseCardData)
if askForUseCardData.result and type(askForUseCardData.result) == 'table' then
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit, 0)
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit, 0)
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0)
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0)
return askForUseCardData.result
else
local data = {card_name, pattern, prompt, cancelable, extra_data}
@ -1700,13 +1754,13 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
Fk.currentResponsePattern = nil
if result ~= "" then
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit, 0)
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit, 0)
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0)
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0)
return self:handleUseCardReply(player, result)
end
end
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit, 0)
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit, 0)
player.room:setPlayerMark(player, MarkEnum.BypassDistancesLimit .. "-tmp", 0)
player.room:setPlayerMark(player, MarkEnum.BypassTimesLimit .. "-tmp", 0)
return nil
end
@ -2970,10 +3024,6 @@ end
---@param room Room
local function shouldUpdateWinRate(room)
if room.settings.gameMode == "heg_mode" then return false end
if room.settings.gameMode == "aaa_role_mode" and #room.players < 5 then
return false
end
if room.settings.enableFreeAssign then
return false
end
@ -2983,7 +3033,7 @@ local function shouldUpdateWinRate(room)
for _, p in ipairs(room.players) do
if p.id < 0 then return false end
end
return true
return Fk.game_modes[room.settings.gameMode]:countInFunc(room)
end
--- 结束一局游戏。

View File

@ -661,8 +661,9 @@ end
function ServerPlayer:reset()
self.room:sendLog{
type = "#ResetGeneral",
type = "#ChainStateChange",
from = self.id,
arg = "reset-general"
}
self:setChainState(false)
if not self.faceup then self:turnOver() end

View File

@ -9,6 +9,7 @@ local thunderSlashSkill = fk.CreateActiveSkill{
max_phase_use_time = 1,
target_num = 1,
can_use = slash.skill.canUse,
mod_target_filter = slash.skill.modTargetFilter,
target_filter = slash.skill.targetFilter,
on_effect = function(self, room, effect)
local to = effect.to
@ -47,6 +48,7 @@ local fireSlashSkill = fk.CreateActiveSkill{
max_phase_use_time = 1,
target_num = 1,
can_use = slash.skill.canUse,
mod_target_filter = slash.skill.modTargetFilter,
target_filter = slash.skill.targetFilter,
on_effect = function(self, room, effect)
local to = effect.to
@ -79,8 +81,14 @@ extension:addCards{
local analepticSkill = fk.CreateActiveSkill{
name = "analeptic_skill",
max_turn_use_time = 1,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return self:withinTimesLimit(Fk:currentRoom():getPlayerById(to_select), Player.HistoryTurn, card, "analeptic", Fk:currentRoom():getPlayerById(to_select)) and
not table.find(Fk:currentRoom().players, function(p)
return p.dying
end)
end,
can_use = function(self, player, card)
return self:withinTimesLimit(player, Player.HistoryTurn, card, "analeptic", player)
return self:modTargetFilter(player.id, Util.DummyTable, player.id, card)
end,
on_use = function(self, room, use)
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
@ -171,6 +179,9 @@ local ironChainCardSkill = fk.CreateActiveSkill{
name = "iron_chain_skill",
min_target_num = 1,
max_target_num = 2,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
target_filter = function() return true end,
on_effect = function(self, room, cardEffectEvent)
local to = room:getPlayerById(cardEffectEvent.to)
@ -196,9 +207,12 @@ extension:addCards{
local fireAttackSkill = fk.CreateActiveSkill{
name = "fire_attack_skill",
target_num = 1,
target_filter = function(self, to_select)
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return not Fk:currentRoom():getPlayerById(to_select):isKongcheng()
end,
target_filter = function(self, to_select)
return self:modTargetFilter(to_select)
end,
on_effect = function(self, room, cardEffectEvent)
local from = room:getPlayerById(cardEffectEvent.from)
local to = room:getPlayerById(cardEffectEvent.to)

View File

@ -362,6 +362,7 @@ heg = fk.CreateGameMode{
maxPlayer = 8,
rule = heg_rule,
logic = heg_getlogic,
countInFunc = Util.FalseFunc
}
Fk:loadTranslationTable{

View File

@ -52,7 +52,7 @@ Fk:loadTranslationTable{
["xuchu"] = "许褚",
["~xuchu"] = "冷,好冷啊……",
["$luoyi1"] = "",
["$luoyi1"] = "",
["$luoyi2"] = "谁来与我大战三百回合?",
["luoyi"] = "裸衣",
[":luoyi"] = "摸牌阶段,你可以少摸一张牌,若如此做,本回合你使用【杀】或【决斗】对目标角色造成伤害时,此伤害+1。",

View File

@ -1075,6 +1075,9 @@ 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 = ""

View File

@ -16,7 +16,7 @@ Fk:loadTranslationTable{
["diamond"] = "方块",
["suit"] = "花色",
["color"] = "颜色",
["figure"] = "点数",
["number"] = "点数",
["basic_char"] = "",
["trick_char"] = "",

View File

@ -3,46 +3,6 @@
local extension = Package:new("standard_cards", Package.CardPack)
extension.metadata = require "packages.standard_cards.metadata"
local global_can_use = function(self, player, card)
local room = Fk:currentRoom()
for _, p in ipairs(room.alive_players) do
if not (card and player:isProhibited(p, card)) then
return true
end
end
end
local aoe_can_use = function(self, player, card)
local room = Fk:currentRoom()
for _, p in ipairs(room.alive_players) do
if p ~= player and not (card and player:isProhibited(p, card)) then
return true
end
end
end
local global_on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getAlivePlayers()) do
if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end
end
local aoe_on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getOtherPlayers(room:getPlayerById(cardUseEvent.from))) do
if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end
end
local slashSkill = fk.CreateActiveSkill{
name = "slash_skill",
max_phase_use_time = 1,
@ -53,10 +13,15 @@ local slashSkill = fk.CreateActiveSkill{
return self:withinTimesLimit(player, Player.HistoryPhase, card, "slash", p)
end)
end,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
local player = Fk:currentRoom():getPlayerById(to_select)
local from = Fk:currentRoom():getPlayerById(user)
return from ~= player and not (distance_limited and not self:withinDistanceLimit(from, true, card, player))
end,
target_filter = function(self, to_select, selected, _, card)
if #selected < self:getMaxTargetNum(Self, card) then
local player = Fk:currentRoom():getPlayerById(to_select)
return Self ~= player and self:withinDistanceLimit(Self, true, card, player) and
return self:modTargetFilter(to_select, selected, Self.id, true, card) and
(#selected > 0 or self:withinTimesLimit(Self, Player.HistoryPhase, card, "slash", player))
end
end,
@ -158,6 +123,12 @@ extension:addCards({
local peachSkill = fk.CreateActiveSkill{
name = "peach_skill",
mod_target_filter = function(self, to_select)
return Fk:currentRoom():getPlayerById(to_select):isWounded() and
not table.find(Fk:currentRoom().players, function(p)
return p.dying
end)
end,
can_use = function(self, player)
return player:isWounded()
end,
@ -201,10 +172,13 @@ extension:addCards({
local dismantlementSkill = fk.CreateActiveSkill{
name = "dismantlement_skill",
target_num = 1,
mod_target_filter = function(self, to_select, selected, user)
local player = Fk:currentRoom():getPlayerById(to_select)
return Fk:currentRoom():getPlayerById(user) ~= player and not player:isAllNude()
end,
target_filter = function(self, to_select, selected)
if #selected < self:getMaxTargetNum(Self) then
local player = Fk:currentRoom():getPlayerById(to_select)
return Self ~= player and not player:isAllNude()
return self:modTargetFilter(to_select, selected, Self.id)
end
end,
on_effect = function(self, room, effect)
@ -236,13 +210,14 @@ extension:addCards({
local snatchSkill = fk.CreateActiveSkill{
name = "snatch_skill",
distance_limit = 1,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
local player = Fk:currentRoom():getPlayerById(to_select)
local from = Fk:currentRoom():getPlayerById(user)
return from ~= player and not (player:isAllNude() or (distance_limited and not self:withinDistanceLimit(from, true, card, player)))
end,
target_filter = function(self, to_select, selected, _, card)
if #selected == 0 then
local player = Fk:currentRoom():getPlayerById(to_select)
return
Self ~= player and
self:withinDistanceLimit(Self, false, card, player) and -- for no distance limit for snatch
not player:isAllNude()
return self:modTargetFilter(to_select, selected, Self.id, card, true)
end
end,
target_num = 1,
@ -272,10 +247,12 @@ extension:addCards({
local duelSkill = fk.CreateActiveSkill{
name = "duel_skill",
mod_target_filter = function(self, to_select, selected, user)
return user ~= to_select
end,
target_filter = function(self, to_select, selected)
if #selected == 0 then
local player = Fk:currentRoom():getPlayerById(to_select)
return Self ~= player
return self:modTargetFilter(to_select, selected, Self.id)
end
end,
target_num = 1,
@ -355,6 +332,10 @@ extension:addCards({
local collateralSkill = fk.CreateActiveSkill{
name = "collateral_skill",
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
local player = Fk:currentRoom():getPlayerById(to_select)
return user ~= player.id and player:getEquipment(Card.SubtypeWeapon)
end,
target_filter = function(self, to_select, selected)
local player = Fk:currentRoom():getPlayerById(to_select)
if #selected == 0 then
@ -399,6 +380,9 @@ extension:addCards({
local exNihiloSkill = fk.CreateActiveSkill{
name = "ex_nihilo_skill",
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = { { cardUseEvent.from } }
@ -453,8 +437,11 @@ extension:addCards({
local savageAssaultSkill = fk.CreateActiveSkill{
name = "savage_assault_skill",
can_use = aoe_can_use,
on_use = aoe_on_use,
can_use = Util.AoeCanUse,
on_use = Util.AoeOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return user ~= to_select
end,
on_effect = function(self, room, effect)
local cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'slash', nil, nil, false, nil, effect)
@ -493,8 +480,11 @@ extension:addCards({
local archeryAttackSkill = fk.CreateActiveSkill{
name = "archery_attack_skill",
can_use = aoe_can_use,
on_use = aoe_on_use,
can_use = Util.AoeCanUse,
on_use = Util.AoeOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return user ~= to_select
end,
on_effect = function(self, room, effect)
local cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'jink', nil, nil, false, nil, effect)
@ -531,8 +521,11 @@ extension:addCards({
local godSalvationSkill = fk.CreateActiveSkill{
name = "god_salvation_skill",
can_use = global_can_use,
on_use = global_on_use,
can_use = Util.GlobalCanUse,
on_use = Util.GlobalOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
about_to_effect = function(self, room, effect)
if not room:getPlayerById(effect.to):isWounded() then
return true
@ -566,8 +559,11 @@ extension:addCards({
local amazingGraceSkill = fk.CreateActiveSkill{
name = "amazing_grace_skill",
can_use = global_can_use,
on_use = global_on_use,
can_use = Util.GlobalCanUse,
on_use = Util.GlobalOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
on_effect = function(self, room, effect)
local to = room:getPlayerById(effect.to)
if not (effect.extra_data and effect.extra_data.AGFilled) then