多后缀与bugFix (#321)
- 正式添加对多后缀标记的支持 - 添加了一点注释 - 搬运了moveCardIntoEquip和canMoveCardIntoEquip - 为选牌的默认prompt添加了目标 - 完善了朱雀羽扇的判定 - 修复了抽选武将牌堆时未删除已选武将的bug - 修复了maxCard标记不识别“-turn”以外标记的bug - 修复了obtaincard实际不能接受id数组的bug
This commit is contained in:
parent
6fbaf9d055
commit
380ca120e9
|
@ -1107,7 +1107,7 @@ callbacks["AskForCardChosen"] = (jsonData) => {
|
||||||
const reason = data._reason;
|
const reason = data._reason;
|
||||||
const prompt = data._prompt;
|
const prompt = data._prompt;
|
||||||
if (prompt === "") {
|
if (prompt === "") {
|
||||||
roomScene.promptText = luatr("#AskForChooseCard")
|
roomScene.promptText = luatr(processPrompt("#AskForChooseCard:" + data._id))
|
||||||
.arg(luatr(reason));
|
.arg(luatr(reason));
|
||||||
} else {
|
} else {
|
||||||
roomScene.setPrompt(processPrompt(prompt), true);
|
roomScene.setPrompt(processPrompt(prompt), true);
|
||||||
|
@ -1139,7 +1139,7 @@ callbacks["AskForCardsChosen"] = (jsonData) => {
|
||||||
const reason = data._reason;
|
const reason = data._reason;
|
||||||
const prompt = data._prompt;
|
const prompt = data._prompt;
|
||||||
if (prompt === "") {
|
if (prompt === "") {
|
||||||
roomScene.promptText = luatr("#AskForChooseCards")
|
roomScene.promptText = luatr(processPrompt("#AskForChooseCards:" + data._id))
|
||||||
.arg(luatr(reason)).arg(min).arg(max);
|
.arg(luatr(reason)).arg(min).arg(max);
|
||||||
} else {
|
} else {
|
||||||
roomScene.setPrompt(processPrompt(prompt), true);
|
roomScene.setPrompt(processPrompt(prompt), true);
|
||||||
|
|
|
@ -378,6 +378,7 @@ fk.client_callback["AskForCardChosen"] = function(jsonData)
|
||||||
judge = {}
|
judge = {}
|
||||||
end
|
end
|
||||||
ui_data = {
|
ui_data = {
|
||||||
|
_id = id,
|
||||||
_reason = reason,
|
_reason = reason,
|
||||||
card_data = {},
|
card_data = {},
|
||||||
_prompt = prompt,
|
_prompt = prompt,
|
||||||
|
@ -413,6 +414,7 @@ fk.client_callback["AskForCardsChosen"] = function(jsonData)
|
||||||
judge = {}
|
judge = {}
|
||||||
end
|
end
|
||||||
ui_data = {
|
ui_data = {
|
||||||
|
_id = id,
|
||||||
_min = min,
|
_min = min,
|
||||||
_max = max,
|
_max = max,
|
||||||
_reason = reason,
|
_reason = reason,
|
||||||
|
|
|
@ -185,12 +185,13 @@ Fk:loadTranslationTable({
|
||||||
["AskForKingdom"] = "Choosing kingdom",
|
["AskForKingdom"] = "Choosing kingdom",
|
||||||
["AskForPindian"] = "Point fight",
|
["AskForPindian"] = "Point fight",
|
||||||
["AskForMoveCardInBoard"] = "Moving cards",
|
["AskForMoveCardInBoard"] = "Moving cards",
|
||||||
|
["replaceEquip"] = "Replacing Equip",
|
||||||
["PlayCard"] = "Playing card",
|
["PlayCard"] = "Playing card",
|
||||||
|
|
||||||
["AskForCardChosen"] = "Choosing card",
|
["AskForCardChosen"] = "Choosing card",
|
||||||
["AskForCardsChosen"] = "Choosing card",
|
["AskForCardsChosen"] = "Choosing card",
|
||||||
["#AskForChooseCard"] = "%1: please choose a card",
|
["#AskForChooseCard"] = "%1: please choose a card from %src",
|
||||||
["#AskForChooseCards"] = "%1: please choose %2~%3 cards",
|
["#AskForChooseCards"] = "%1: please choose %2~%3 cards from %src",
|
||||||
["$ChooseCard"] = "Choose a card",
|
["$ChooseCard"] = "Choose a card",
|
||||||
["$ChooseCards"] = "Choose %1~%2 cards",
|
["$ChooseCards"] = "Choose %1~%2 cards",
|
||||||
["$Hand"] = "Hand",
|
["$Hand"] = "Hand",
|
||||||
|
@ -209,6 +210,7 @@ Fk:loadTranslationTable({
|
||||||
["#AskForCard"] = "Please choose %arg cards (%arg2 at least)",
|
["#AskForCard"] = "Please choose %arg cards (%arg2 at least)",
|
||||||
["#AskForDistribution"] = "Please distribute cards (%arg at least , %arg2 total)",
|
["#AskForDistribution"] = "Please distribute cards (%arg at least , %arg2 total)",
|
||||||
["@DistributionTo"] = "",
|
["@DistributionTo"] = "",
|
||||||
|
["#replaceEquip"] = "Please Choose a Equip Card to be replaced",
|
||||||
["#askForPindian"] = "%arg: please choose a hand card for point fight",
|
["#askForPindian"] = "%arg: please choose a hand card for point fight",
|
||||||
["#StartPindianReason"] = "%from started point fight (%arg)",
|
["#StartPindianReason"] = "%from started point fight (%arg)",
|
||||||
["#ShowPindianCard"] = "The point fight card of %from is %card",
|
["#ShowPindianCard"] = "The point fight card of %from is %card",
|
||||||
|
|
|
@ -239,12 +239,13 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
||||||
["AskForKingdom"] = "选择势力",
|
["AskForKingdom"] = "选择势力",
|
||||||
["AskForPindian"] = "拼点",
|
["AskForPindian"] = "拼点",
|
||||||
["AskForMoveCardInBoard"] = "移动卡牌",
|
["AskForMoveCardInBoard"] = "移动卡牌",
|
||||||
|
["replaceEquip"] = "替换装备",
|
||||||
["PlayCard"] = "出牌",
|
["PlayCard"] = "出牌",
|
||||||
|
|
||||||
["AskForCardChosen"] = "选牌",
|
["AskForCardChosen"] = "选牌",
|
||||||
["AskForCardsChosen"] = "选牌",
|
["AskForCardsChosen"] = "选牌",
|
||||||
["#AskForChooseCard"] = "%1:请选择其一张卡牌",
|
["#AskForChooseCard"] = "%1:请选择%src的一张卡牌",
|
||||||
["#AskForChooseCards"] = "%1:请选择其%2至%3张卡牌",
|
["#AskForChooseCards"] = "%1:请选择%src的%2至%3张卡牌",
|
||||||
["$ChooseCard"] = "请选择一张卡牌",
|
["$ChooseCard"] = "请选择一张卡牌",
|
||||||
["$ChooseCards"] = "请选择%1至%2张卡牌",
|
["$ChooseCards"] = "请选择%1至%2张卡牌",
|
||||||
["$Hand"] = "手牌区",
|
["$Hand"] = "手牌区",
|
||||||
|
@ -263,6 +264,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
||||||
["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张",
|
["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张",
|
||||||
["#AskForDistribution"] = "请分配这些牌,至少 %arg 张,至多 %arg2 张",
|
["#AskForDistribution"] = "请分配这些牌,至少 %arg 张,至多 %arg2 张",
|
||||||
["@DistributionTo"] = "",
|
["@DistributionTo"] = "",
|
||||||
|
["#replaceEquip"] = "选择一张装备牌替换之",
|
||||||
["#askForPindian"] = "%arg:请选择一张手牌作为拼点牌",
|
["#askForPindian"] = "%arg:请选择一张手牌作为拼点牌",
|
||||||
["#StartPindianReason"] = "%from 由于 %arg 而发起拼点",
|
["#StartPindianReason"] = "%from 由于 %arg 而发起拼点",
|
||||||
["#ShowPindianCard"] = "%from 的拼点牌是 %card",
|
["#ShowPindianCard"] = "%from 的拼点牌是 %card",
|
||||||
|
|
|
@ -71,7 +71,7 @@ function General:__tostring()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- 为武将增加技能,需要注意增加其他武将技能时的处理方式。
|
--- 为武将增加技能,需要注意增加其他武将技能时的处理方式。
|
||||||
---@param skill Skill @ (单个)武将技能
|
---@param skill Skill|string @ (单个)武将技能
|
||||||
function General:addSkill(skill)
|
function General:addSkill(skill)
|
||||||
if (type(skill) == "string") then
|
if (type(skill) == "string") then
|
||||||
table.insert(self.other_skills, skill)
|
table.insert(self.other_skills, skill)
|
||||||
|
@ -82,7 +82,7 @@ function General:addSkill(skill)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- 为武将增加相关技能,需要注意增加其他武将技能时的处理方式。
|
--- 为武将增加相关技能,需要注意增加其他武将技能时的处理方式。
|
||||||
---@param skill Skill @ (单个)武将技能
|
---@param skill Skill|string @ (单个)武将技能
|
||||||
function General:addRelatedSkill(skill)
|
function General:addRelatedSkill(skill)
|
||||||
if (type(skill) == "string") then
|
if (type(skill) == "string") then
|
||||||
table.insert(self.related_other_skills, skill)
|
table.insert(self.related_other_skills, skill)
|
||||||
|
|
|
@ -475,9 +475,17 @@ end
|
||||||
|
|
||||||
--- 获取角色是否被移除。
|
--- 获取角色是否被移除。
|
||||||
function Player:isRemoved()
|
function Player:isRemoved()
|
||||||
return self:getMark(MarkEnum.PlayerRemoved) ~= 0 or table.find(MarkEnum.TempMarkSuffix, function(s)
|
for mark, _ in pairs(self.mark) do
|
||||||
return self:getMark(MarkEnum.PlayerRemoved .. s) ~= 0
|
if mark == MarkEnum.PlayerRemoved then return true end
|
||||||
end)
|
if mark:startsWith(MarkEnum.PlayerRemoved .. "-") then
|
||||||
|
for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do
|
||||||
|
if mark:find(suffix, 1, true) then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- return self:getMark(MarkEnum.PlayerRemoved) ~= 0 or table.find(MarkEnum.TempMarkSuffix, function(s)
|
||||||
|
-- return self:getMark(MarkEnum.PlayerRemoved .. s) ~= 0
|
||||||
|
-- end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- 修改玩家与其他角色的固定距离。
|
--- 修改玩家与其他角色的固定距离。
|
||||||
|
@ -950,13 +958,21 @@ function Player:prohibitReveal(isDeputy)
|
||||||
if type(self:getMark(MarkEnum.RevealProhibited)) == "table" and table.contains(self:getMark(MarkEnum.RevealProhibited), place) then
|
if type(self:getMark(MarkEnum.RevealProhibited)) == "table" and table.contains(self:getMark(MarkEnum.RevealProhibited), place) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
|
||||||
return self:getMark(MarkEnum.RevealProhibited .. s)
|
for mark, value in pairs(self.mark) do
|
||||||
end)) do
|
if mark:startsWith(MarkEnum.RevealProhibited .. "-") and type(value) == "table" then
|
||||||
if type(m) == "table" and table.contains(m, place) then
|
for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do
|
||||||
return true
|
if mark:find(suffix, 1, true) then return true end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
-- for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
||||||
|
-- return self:getMark(MarkEnum.RevealProhibited .. s)
|
||||||
|
-- end)) do
|
||||||
|
-- if type(m) == "table" and table.contains(m, place) then
|
||||||
|
-- return true
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -981,6 +997,21 @@ function Player:canPindian(to, ignoreFromKong, ignoreToKong)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- 判断一张牌能否移动至某角色的装备区
|
||||||
|
---@param cardId integer @ 移动的牌
|
||||||
|
---@param convert? boolean @ 是否可以替换装备(默认可以)
|
||||||
|
---@return boolean
|
||||||
|
function Player:canMoveCardIntoEquip(cardId, convert)
|
||||||
|
convert = (convert == nil) and true or convert
|
||||||
|
local card = Fk:getCardById(cardId)
|
||||||
|
if not (card.sub_type >= 3 and card.sub_type <= 7) then return false end
|
||||||
|
if self.dead or table.contains(self:getCardIds("e"), cardId) then return false end
|
||||||
|
if self:hasEmptyEquipSlot(card.sub_type) or (#self:getEquipments(card.sub_type) > 0 and convert) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
--转换技状态阳
|
--转换技状态阳
|
||||||
fk.SwitchYang = 0
|
fk.SwitchYang = 0
|
||||||
--转换技状态阴
|
--转换技状态阴
|
||||||
|
|
|
@ -155,21 +155,38 @@ function ActiveSkill:withinDistanceLimit(player, isattack, card, to)
|
||||||
|
|
||||||
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
||||||
local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix)
|
local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix)
|
||||||
table.insert(temp_suf, 1, "")
|
|
||||||
table.insert(temp_suf, "-tmp")
|
---@param object Card|Player
|
||||||
table.insert(card_temp_suf, 1, "")
|
---@param markname string
|
||||||
|
---@param suffixes string[]
|
||||||
|
---@return boolean
|
||||||
|
local function hasMark(object, markname, suffixes)
|
||||||
|
if not object then return false end
|
||||||
|
for mark, _ in pairs(object.mark) do
|
||||||
|
if mark == markname then return true end
|
||||||
|
if mark:startsWith(markname .. "-") then
|
||||||
|
for _, suffix in ipairs(suffixes) do
|
||||||
|
if mark:find(suffix, 1, true) then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
return (isattack and player:inMyAttackRange(to)) or
|
return (isattack and player:inMyAttackRange(to)) or
|
||||||
(player:distanceTo(to) > 0 and player:distanceTo(to) <= self:getDistanceLimit(player, card, to)) or
|
(player:distanceTo(to) > 0 and player:distanceTo(to) <= self:getDistanceLimit(player, card, to)) or
|
||||||
(card and table.find(card_temp_suf, function(s)
|
hasMark(card, MarkEnum.BypassDistancesLimit, card_temp_suf) or
|
||||||
return card:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
hasMark(player, MarkEnum.BypassDistancesLimit, temp_suf) or
|
||||||
end)) or
|
hasMark(to, MarkEnum.BypassDistancesLimitTo, temp_suf)
|
||||||
(table.find(temp_suf, function(s)
|
-- (card and table.find(card_temp_suf, function(s)
|
||||||
return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
-- return card:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
||||||
end)) or
|
-- end)) or
|
||||||
(to and (table.find(temp_suf, function(s)
|
-- (table.find(temp_suf, function(s)
|
||||||
return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0
|
-- return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0
|
||||||
end)))
|
-- end)) or
|
||||||
|
-- (to and (table.find(temp_suf, function(s)
|
||||||
|
-- return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0
|
||||||
|
-- end)))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Determine if selected cards and targets are valid for this skill
|
--- Determine if selected cards and targets are valid for this skill
|
||||||
|
|
|
@ -40,20 +40,37 @@ function UsableSkill:withinTimesLimit(player, scope, card, card_name, to)
|
||||||
card_name = card_name or card.trueName
|
card_name = card_name or card.trueName
|
||||||
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix)
|
||||||
local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix)
|
local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix)
|
||||||
table.insert(temp_suf, 1, "")
|
|
||||||
table.insert(temp_suf, "-tmp")
|
---@param object Card|Player
|
||||||
table.insert(card_temp_suf, 1, "")
|
---@param markname string
|
||||||
|
---@param suffixes string[]
|
||||||
|
---@return boolean
|
||||||
|
local function hasMark(object, markname, suffixes)
|
||||||
|
if not object then return false end
|
||||||
|
for mark, _ in pairs(object.mark) do
|
||||||
|
if mark == markname then return true end
|
||||||
|
if mark:startsWith(markname .. "-") then
|
||||||
|
for _, suffix in ipairs(suffixes) do
|
||||||
|
if mark:find(suffix, 1, true) then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
return player:usedCardTimes(card_name, scope) < self:getMaxUseTime(player, scope, card, to) or
|
return player:usedCardTimes(card_name, scope) < self:getMaxUseTime(player, scope, card, to) or
|
||||||
(card and table.find(card_temp_suf, function(s)
|
hasMark(card, MarkEnum.BypassTimesLimit, card_temp_suf) or
|
||||||
return card:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
hasMark(player, MarkEnum.BypassTimesLimit, temp_suf) or
|
||||||
end)) or
|
hasMark(to, MarkEnum.BypassTimesLimitTo, temp_suf)
|
||||||
(table.find(temp_suf, function(s)
|
-- (card and table.find(card_temp_suf, function(s)
|
||||||
return player:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
-- return card:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
||||||
end)) or
|
-- end)) or
|
||||||
(to and (table.find(temp_suf, function(s)
|
-- (table.find(temp_suf, function(s)
|
||||||
return to:getMark(MarkEnum.BypassTimesLimitTo .. s) ~= 0
|
-- return player:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0
|
||||||
end)))
|
-- end)) or
|
||||||
|
-- (to and (table.find(temp_suf, function(s)
|
||||||
|
-- return to:getMark(MarkEnum.BypassTimesLimitTo .. s) ~= 0
|
||||||
|
-- end)))
|
||||||
end
|
end
|
||||||
|
|
||||||
return UsableSkill
|
return UsableSkill
|
||||||
|
|
|
@ -114,6 +114,73 @@ function fk.sorted_pairs(t, val_func, reverse)
|
||||||
return iter, nil, 1
|
return iter, nil, 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- frequenly used filter & map functions
|
||||||
|
|
||||||
|
--- 返回ID
|
||||||
|
Util.IdMapper = function(e) return e.id end
|
||||||
|
--- 根据卡牌ID返回卡牌
|
||||||
|
Util.Id2CardMapper = function(id) return Fk:getCardById(id) end
|
||||||
|
--- 根据玩家ID返回玩家
|
||||||
|
Util.Id2PlayerMapper = function(id)
|
||||||
|
return Fk:currentRoom():getPlayerById(id)
|
||||||
|
end
|
||||||
|
--- 返回武将名
|
||||||
|
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
|
||||||
|
--- 返回译文
|
||||||
|
Util.TranslateMapper = function(str) return Fk:translate(str) end
|
||||||
|
|
||||||
|
-- for card preset
|
||||||
|
|
||||||
|
--- 全局卡牌(包括自己)的canUse
|
||||||
|
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
|
||||||
|
|
||||||
|
--- AOE卡牌(不包括自己)的canUse
|
||||||
|
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
|
||||||
|
|
||||||
|
--- 全局卡牌(包括自己)的onUse
|
||||||
|
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
|
||||||
|
|
||||||
|
--- AOE卡牌(不包括自己)的onUse
|
||||||
|
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
|
||||||
|
|
||||||
|
-- Table
|
||||||
|
|
||||||
---@param func fun(element, index, array)
|
---@param func fun(element, index, array)
|
||||||
function table:forEach(func)
|
function table:forEach(func)
|
||||||
for i, v in ipairs(self) do
|
for i, v in ipairs(self) do
|
||||||
|
@ -164,66 +231,6 @@ function table:map(func)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
-- frequenly used filter & map functions
|
|
||||||
|
|
||||||
--- 返回ID
|
|
||||||
Util.IdMapper = function(e) return e.id end
|
|
||||||
--- 根据卡牌ID返回卡牌
|
|
||||||
Util.Id2CardMapper = function(id) return Fk:getCardById(id) end
|
|
||||||
--- 根据玩家ID返回玩家
|
|
||||||
Util.Id2PlayerMapper = function(id)
|
|
||||||
return Fk:currentRoom():getPlayerById(id)
|
|
||||||
end
|
|
||||||
--- 返回武将名
|
|
||||||
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
|
|
||||||
--- 返回译文
|
|
||||||
Util.TranslateMapper = function(str) return Fk:translate(str) 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
|
---@generic T
|
||||||
---@param self T[]
|
---@param self T[]
|
||||||
---@return T[]
|
---@return T[]
|
||||||
|
|
|
@ -174,7 +174,7 @@ GameEvent.cleaners[GameEvent.Round] = function(self)
|
||||||
p:setCardUseHistory("", 0, Player.HistoryRound)
|
p:setCardUseHistory("", 0, Player.HistoryRound)
|
||||||
p:setSkillUseHistory("", 0, Player.HistoryRound)
|
p:setSkillUseHistory("", 0, Player.HistoryRound)
|
||||||
for name, _ in pairs(p.mark) do
|
for name, _ in pairs(p.mark) do
|
||||||
if name:endsWith("-round") then
|
if name:find("-round", 1, true) then
|
||||||
room:setPlayerMark(p, name, 0)
|
room:setPlayerMark(p, name, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -182,7 +182,7 @@ GameEvent.cleaners[GameEvent.Round] = function(self)
|
||||||
|
|
||||||
for cid, cmark in pairs(room.card_marks) do
|
for cid, cmark in pairs(room.card_marks) do
|
||||||
for name, _ in pairs(cmark) do
|
for name, _ in pairs(cmark) do
|
||||||
if name:endsWith("-round") then
|
if name:find("-round", 1, true) then
|
||||||
room:setCardMark(Fk:getCardById(cid), name, 0)
|
room:setCardMark(Fk:getCardById(cid), name, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -249,7 +249,7 @@ GameEvent.cleaners[GameEvent.Turn] = function(self)
|
||||||
p:setCardUseHistory("", 0, Player.HistoryTurn)
|
p:setCardUseHistory("", 0, Player.HistoryTurn)
|
||||||
p:setSkillUseHistory("", 0, Player.HistoryTurn)
|
p:setSkillUseHistory("", 0, Player.HistoryTurn)
|
||||||
for name, _ in pairs(p.mark) do
|
for name, _ in pairs(p.mark) do
|
||||||
if name:endsWith("-turn") then
|
if name:find("-turn", 1, true) then
|
||||||
room:setPlayerMark(p, name, 0)
|
room:setPlayerMark(p, name, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -257,7 +257,7 @@ GameEvent.cleaners[GameEvent.Turn] = function(self)
|
||||||
|
|
||||||
for cid, cmark in pairs(room.card_marks) do
|
for cid, cmark in pairs(room.card_marks) do
|
||||||
for name, _ in pairs(cmark) do
|
for name, _ in pairs(cmark) do
|
||||||
if name:endsWith("-turn") then
|
if name:find("-turn", 1, true) then
|
||||||
room:setCardMark(Fk:getCardById(cid), name, 0)
|
room:setCardMark(Fk:getCardById(cid), name, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -372,7 +372,7 @@ GameEvent.cleaners[GameEvent.Phase] = function(self)
|
||||||
p:setCardUseHistory("", 0, Player.HistoryPhase)
|
p:setCardUseHistory("", 0, Player.HistoryPhase)
|
||||||
p:setSkillUseHistory("", 0, Player.HistoryPhase)
|
p:setSkillUseHistory("", 0, Player.HistoryPhase)
|
||||||
for name, _ in pairs(p.mark) do
|
for name, _ in pairs(p.mark) do
|
||||||
if name:endsWith("-phase") then
|
if name:find("-phase", 1, true) then
|
||||||
room:setPlayerMark(p, name, 0)
|
room:setPlayerMark(p, name, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -380,7 +380,7 @@ GameEvent.cleaners[GameEvent.Phase] = function(self)
|
||||||
|
|
||||||
for cid, cmark in pairs(room.card_marks) do
|
for cid, cmark in pairs(room.card_marks) do
|
||||||
for name, _ in pairs(cmark) do
|
for name, _ in pairs(cmark) do
|
||||||
if name:endsWith("-phase") then
|
if name:find("-phase", 1, true) then
|
||||||
room:setCardMark(Fk:getCardById(cid), name, 0)
|
room:setCardMark(Fk:getCardById(cid), name, 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -166,7 +166,7 @@ GameEvent.functions[GameEvent.MoveCards] = function(self)
|
||||||
|
|
||||||
local currentCard = Fk:getCardById(info.cardId)
|
local currentCard = Fk:getCardById(info.cardId)
|
||||||
for name, _ in pairs(currentCard.mark) do
|
for name, _ in pairs(currentCard.mark) do
|
||||||
if name:endsWith("-inhand") and
|
if name:find("-inhand", 1, true) and
|
||||||
realFromArea == Player.Hand and
|
realFromArea == Player.Hand and
|
||||||
data.from
|
data.from
|
||||||
then
|
then
|
||||||
|
|
|
@ -1501,6 +1501,7 @@ end
|
||||||
---@param name string @ 武将name,如找不到则查找truename,再找不到则返回nil
|
---@param name string @ 武将name,如找不到则查找truename,再找不到则返回nil
|
||||||
---@return string? @ 抽出的武将名
|
---@return string? @ 抽出的武将名
|
||||||
function Room:findGeneral(name)
|
function Room:findGeneral(name)
|
||||||
|
if not Fk.generals[name] then return nil end
|
||||||
for i, g in ipairs(self.general_pile) do
|
for i, g in ipairs(self.general_pile) do
|
||||||
if g == name or Fk.generals[g].trueName == Fk.generals[name].trueName then
|
if g == name or Fk.generals[g].trueName == Fk.generals[name].trueName then
|
||||||
return table.remove(self.general_pile, i)
|
return table.remove(self.general_pile, i)
|
||||||
|
@ -1517,13 +1518,13 @@ function Room:findGenerals(func, n)
|
||||||
n = n or 1
|
n = n or 1
|
||||||
local ret = {}
|
local ret = {}
|
||||||
local index = 1
|
local index = 1
|
||||||
repeat
|
while #ret < n and index <= #self.general_pile do
|
||||||
if func(self.general_pile[index]) then
|
if func(self.general_pile[index]) then
|
||||||
table.insert(ret, table.remove(self.general_pile, index))
|
table.insert(ret, table.remove(self.general_pile, index))
|
||||||
else
|
else
|
||||||
index = index + 1
|
index = index + 1
|
||||||
end
|
end
|
||||||
until index >= #self.general_pile or #ret >= n
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2993,8 +2994,10 @@ end
|
||||||
---@param proposer? integer @ 移动操作者的id
|
---@param proposer? integer @ 移动操作者的id
|
||||||
function Room:obtainCard(player, cid, unhide, reason, proposer)
|
function Room:obtainCard(player, cid, unhide, reason, proposer)
|
||||||
if type(cid) ~= "number" then
|
if type(cid) ~= "number" then
|
||||||
assert(cid and cid:isInstanceOf(Card))
|
assert(cid and type(cid) == "table")
|
||||||
|
if cid:isInstanceOf(Card) then
|
||||||
cid = cid:isVirtual() and cid.subcards or {cid.id}
|
cid = cid:isVirtual() and cid.subcards or {cid.id}
|
||||||
|
end
|
||||||
else
|
else
|
||||||
cid = {cid}
|
cid = {cid}
|
||||||
end
|
end
|
||||||
|
@ -3156,6 +3159,37 @@ function Room:doYiji(room, list, proposer, skillName)
|
||||||
return move_ids
|
return move_ids
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- 将一张牌移动至某角色的装备区,若不合法则置入弃牌堆。目前没做相同副类别装备同时置入的适配(甘露神典韦)
|
||||||
|
---@param target ServerPlayer @ 接受牌的角色
|
||||||
|
---@param cards integer|integer[] @ 移动的牌
|
||||||
|
---@param skillName? string @ 技能名
|
||||||
|
---@param convert? boolean @ 是否可以替换装备(默认可以)
|
||||||
|
---@param proposer? ServerPlayer @ 操作者
|
||||||
|
function Room:moveCardIntoEquip(target, cards, skillName, convert, proposer)
|
||||||
|
convert = (convert == nil) and true or convert
|
||||||
|
skillName = skillName or ""
|
||||||
|
cards = type(cards) == "table" and cards or {cards}
|
||||||
|
local moves = {}
|
||||||
|
for _, cardId in ipairs(cards) do
|
||||||
|
local card = Fk:getCardById(cardId)
|
||||||
|
local fromId = self.owner_map[cardId]
|
||||||
|
local proposerId = proposer and proposer.id or nil
|
||||||
|
if target:canMoveCardIntoEquip(cardId, convert) then
|
||||||
|
if target:hasEmptyEquipSlot(card.sub_type) then
|
||||||
|
table.insert(moves,{ids = {cardId}, from = fromId, to = target.id, toArea = Card.PlayerEquip, moveReason = fk.ReasonPut,skillName = skillName,proposer = proposerId})
|
||||||
|
else
|
||||||
|
local existingEquip = target:getEquipments(card.sub_type)
|
||||||
|
local throw = #existingEquip == 1 and existingEquip[1] or
|
||||||
|
self:askForCardChosen(proposer or target, target, {card_data = { {Util.convertSubtypeAndEquipSlot(card.sub_type),existingEquip} } }, "replaceEquip","#replaceEquip")
|
||||||
|
table.insert(moves,{ids = {throw}, from = target.id, toArea = Card.DiscardPile, moveReason = fk.ReasonPutIntoDiscardPile, skillName = skillName,proposer = proposerId})
|
||||||
|
table.insert(moves,{ids = {cardId}, from = fromId, to = target.id, toArea = Card.PlayerEquip, moveReason = fk.ReasonPut,skillName = skillName,proposer = proposerId})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(moves,{ids = {cardId}, from = fromId, toArea = Card.DiscardPile, moveReason = fk.ReasonPutIntoDiscardPile,skillName = skillName})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:moveCards(table.unpack(moves))
|
||||||
|
end
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- 其他游戏事件
|
-- 其他游戏事件
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
|
@ -366,9 +366,12 @@ local fanSkill = fk.CreateTriggerSkill{
|
||||||
card[k] = v
|
card[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not data.card:isVirtual() then
|
if data.card:isVirtual() then
|
||||||
|
card.subcards = data.card.subcards
|
||||||
|
else
|
||||||
card.id = data.card.id
|
card.id = data.card.id
|
||||||
end
|
end
|
||||||
|
card.skillNames = data.card.skillNames
|
||||||
card.skillName = "fan"
|
card.skillName = "fan"
|
||||||
data.card = card
|
data.card = card
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -129,11 +129,25 @@ local maxCardsSkill = fk.CreateMaxCardsSkill{
|
||||||
name = "max_cards_skill",
|
name = "max_cards_skill",
|
||||||
global = true,
|
global = true,
|
||||||
correct_func = function(self, player)
|
correct_func = function(self, player)
|
||||||
|
local function getMark(markname)
|
||||||
|
local v = 0
|
||||||
|
for mark, value in pairs(player.mark) do
|
||||||
|
if mark == markname then
|
||||||
|
v = v + value
|
||||||
|
elseif mark:startsWith(markname .. "-") then
|
||||||
|
for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do
|
||||||
|
if mark:find(suffix, 1, true) then
|
||||||
|
v = v + value
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
return
|
return
|
||||||
player:getMark(MarkEnum.AddMaxCards) +
|
getMark(MarkEnum.AddMaxCards) -
|
||||||
player:getMark(MarkEnum.AddMaxCardsInTurn) -
|
getMark(MarkEnum.MinusMaxCards)
|
||||||
player:getMark(MarkEnum.MinusMaxCards) -
|
|
||||||
player:getMark(MarkEnum.MinusMaxCardsInTurn)
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,15 +195,32 @@ local uncompulsoryInvalidity = fk.CreateInvaliditySkill {
|
||||||
name = "uncompulsory_invalidity",
|
name = "uncompulsory_invalidity",
|
||||||
global = true,
|
global = true,
|
||||||
invalidity_func = function(self, from, skill)
|
invalidity_func = function(self, from, skill)
|
||||||
|
---@param object Card|Player
|
||||||
|
---@param markname string
|
||||||
|
---@param suffixes string[]
|
||||||
|
---@return boolean
|
||||||
|
local function hasMark(object, markname, suffixes)
|
||||||
|
if not object then return false end
|
||||||
|
for mark, _ in pairs(object.mark) do
|
||||||
|
if mark == markname then return true end
|
||||||
|
if mark:startsWith(markname .. "-") then
|
||||||
|
for _, suffix in ipairs(suffixes) do
|
||||||
|
if mark:find(suffix, 1, true) then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
return
|
return
|
||||||
(skill.frequency ~= Skill.Compulsory and skill.frequency ~= Skill.Wake) and
|
(skill.frequency ~= Skill.Compulsory and skill.frequency ~= Skill.Wake) and
|
||||||
not (skill:isEquipmentSkill() or skill.name:endsWith("&")) and
|
not (skill:isEquipmentSkill() or skill.name:endsWith("&")) and
|
||||||
(
|
hasMark(from, MarkEnum.UncompulsoryInvalidity, MarkEnum.TempMarkSuffix)
|
||||||
from:getMark(MarkEnum.UncompulsoryInvalidity) ~= 0 or
|
-- (
|
||||||
table.find(MarkEnum.TempMarkSuffix, function(s)
|
-- from:getMark(MarkEnum.UncompulsoryInvalidity) ~= 0 or
|
||||||
return from:getMark(MarkEnum.UncompulsoryInvalidity .. s) ~= 0
|
-- table.find(MarkEnum.TempMarkSuffix, function(s)
|
||||||
end)
|
-- return from:getMark(MarkEnum.UncompulsoryInvalidity .. s) ~= 0
|
||||||
)
|
-- end)
|
||||||
|
-- )
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,15 +232,27 @@ local revealProhibited = fk.CreateInvaliditySkill {
|
||||||
if type(from:getMark(MarkEnum.RevealProhibited)) == "table" then
|
if type(from:getMark(MarkEnum.RevealProhibited)) == "table" then
|
||||||
generals = from:getMark(MarkEnum.RevealProhibited)
|
generals = from:getMark(MarkEnum.RevealProhibited)
|
||||||
end
|
end
|
||||||
for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
|
||||||
return from:getMark(MarkEnum.RevealProhibited .. s)
|
for mark, value in pairs(from.mark) do
|
||||||
end)) do
|
if mark:startsWith(MarkEnum.RevealProhibited .. "-") and type(value) == "table" then
|
||||||
if type(m) == "table" then
|
for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do
|
||||||
for _, g in ipairs(m) do
|
if mark:find(suffix, 1, true) then
|
||||||
|
for _, g in ipairs(value) do
|
||||||
table.insertIfNeed(generals, g)
|
table.insertIfNeed(generals, g)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s)
|
||||||
|
-- return from:getMark(MarkEnum.RevealProhibited .. s)
|
||||||
|
-- end)) do
|
||||||
|
-- if type(m) == "table" then
|
||||||
|
-- for _, g in ipairs(m) do
|
||||||
|
-- table.insertIfNeed(generals, g)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
if #generals == 0 then return false end
|
if #generals == 0 then return false end
|
||||||
local sname = skill.name
|
local sname = skill.name
|
||||||
|
|
|
@ -1132,9 +1132,17 @@ local role_getlogic = function()
|
||||||
lord_general = lord_generals
|
lord_general = lord_generals
|
||||||
lord_generals = {lord_general}
|
lord_generals = {lord_general}
|
||||||
end
|
end
|
||||||
|
|
||||||
generals = table.filter(generals, function(g) return not table.contains(lord_generals, g) end)
|
|
||||||
room:returnToGeneralPile(generals)
|
room:returnToGeneralPile(generals)
|
||||||
|
local index = 1
|
||||||
|
while index <= #room.general_pile do
|
||||||
|
local ret = {}
|
||||||
|
for _, gname in ipairs(lord_generals) do
|
||||||
|
if room.general_pile[index] == gname or Fk.generals[room.general_pile[index]].trueName == Fk.generals[gname].trueName then
|
||||||
|
table.insert(ret, table.remove(room.general_pile, index))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #ret == 0 then index = index + 1 end
|
||||||
|
end
|
||||||
|
|
||||||
room:setPlayerGeneral(lord, lord_general, true)
|
room:setPlayerGeneral(lord, lord_general, true)
|
||||||
room:askForChooseKingdom({lord})
|
room:askForChooseKingdom({lord})
|
||||||
|
@ -1216,14 +1224,24 @@ local role_getlogic = function()
|
||||||
room:setPlayerGeneral(p, general, true, true)
|
room:setPlayerGeneral(p, general, true, true)
|
||||||
room:setDeputyGeneral(p, deputy)
|
room:setDeputyGeneral(p, deputy)
|
||||||
else
|
else
|
||||||
|
table.insertTableIfNeed(selected, p.default_reply)
|
||||||
room:setPlayerGeneral(p, p.default_reply[1], true, true)
|
room:setPlayerGeneral(p, p.default_reply[1], true, true)
|
||||||
room:setDeputyGeneral(p, p.default_reply[2])
|
room:setDeputyGeneral(p, p.default_reply[2])
|
||||||
end
|
end
|
||||||
p.default_reply = ""
|
p.default_reply = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
generals = table.filter(generals, function(g) return not table.contains(selected, g) end)
|
|
||||||
room:returnToGeneralPile(generals)
|
room:returnToGeneralPile(generals)
|
||||||
|
local index = 1
|
||||||
|
while index <= #room.general_pile do
|
||||||
|
local ret = {}
|
||||||
|
for _, gname in ipairs(selected) do
|
||||||
|
if room.general_pile[index] == gname or Fk.generals[room.general_pile[index]].trueName == Fk.generals[gname].trueName then
|
||||||
|
table.insert(ret, table.remove(room.general_pile, index))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #ret == 0 then index = index + 1 end
|
||||||
|
end
|
||||||
|
|
||||||
room:askForChooseKingdom(nonlord)
|
room:askForChooseKingdom(nonlord)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue