modify process & quest skill (#166)
This commit is contained in:
parent
910bf6a215
commit
5128100083
|
@ -30,7 +30,7 @@ Item {
|
|||
|
||||
Text {
|
||||
id: x
|
||||
opacity: skilltype === "limit" ? 1 : 0
|
||||
opacity: (skilltype === "limit" || skilltype === "quest") ? 1 : 0
|
||||
text: "X"
|
||||
font.family: fontLibian.name
|
||||
font.pixelSize: 28
|
||||
|
@ -62,6 +62,12 @@ Item {
|
|||
} else if (skilltype === 'switch') {
|
||||
visible = true;
|
||||
bg.source = SkinBank.LIMIT_SKILL_DIR + (usedtimes < 1 ? 'switch' : 'switch-yin');
|
||||
} else if (skilltype === 'quest') {
|
||||
visible = true
|
||||
if (usedtimes > 1) {
|
||||
x.visible = true;
|
||||
bg.source = SkinBank.LIMIT_SKILL_DIR + "limit-used";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -541,7 +541,7 @@ local function updateLimitSkill(pid, skill, times)
|
|||
if skill:isSwitchSkill() then
|
||||
times = ClientInstance:getPlayerById(pid):getSwitchSkillState(skill.switchSkillName) == fk.SwitchYang and 0 or 1
|
||||
ClientInstance:notifyUI("UpdateLimitSkill", json.encode{ pid, skill.switchSkillName, times })
|
||||
elseif skill.frequency == Skill.Limited or skill.frequency == Skill.Wake then
|
||||
elseif skill.frequency == Skill.Limited or skill.frequency == Skill.Wake or skill.frequency == Skill.Quest then
|
||||
ClientInstance:notifyUI("UpdateLimitSkill", json.encode{ pid, skill.name, times })
|
||||
end
|
||||
end
|
||||
|
@ -557,6 +557,10 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
|||
ClientInstance:notifyUI("AddSkill", jsonData)
|
||||
end
|
||||
|
||||
if skill.frequency == Skill.Quest then
|
||||
return
|
||||
end
|
||||
|
||||
updateLimitSkill(id, skill, target:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||
end
|
||||
|
||||
|
@ -663,7 +667,9 @@ fk.client_callback["AddSkillUseHistory"] = function(jsonData)
|
|||
local playerid, skill_name, time = data[1], data[2], data[3]
|
||||
local player = ClientInstance:getPlayerById(playerid)
|
||||
player:addSkillUseHistory(skill_name, time)
|
||||
if not Fk.skills[skill_name] then return end
|
||||
|
||||
local skill = Fk.skills[skill_name]
|
||||
if not skill or skill.frequency == Skill.Quest then return end
|
||||
updateLimitSkill(playerid, Fk.skills[skill_name], player:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||
end
|
||||
|
||||
|
@ -672,7 +678,9 @@ fk.client_callback["SetSkillUseHistory"] = function(jsonData)
|
|||
local id, skill_name, time, scope = data[1], data[2], data[3], data[4]
|
||||
local player = ClientInstance:getPlayerById(id)
|
||||
player:setSkillUseHistory(skill_name, time, scope)
|
||||
if not Fk.skills[skill_name] then return end
|
||||
|
||||
local skill = Fk.skills[skill_name]
|
||||
if not skill or skill.frequency == Skill.Quest then return end
|
||||
updateLimitSkill(id, Fk.skills[skill_name], player:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||
end
|
||||
|
||||
|
@ -702,6 +710,12 @@ fk.client_callback["ChangeSelf"] = function(jsonData)
|
|||
ClientInstance:notifyUI("ChangeSelf", data.id)
|
||||
end
|
||||
|
||||
fk.client_callback["UpdateQuestSkillUI"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
local player, skillName, usedTimes = data[1], data[2], data[3]
|
||||
updateLimitSkill(player, Fk.skills[skillName], usedTimes)
|
||||
end
|
||||
|
||||
-- Create ClientInstance (used by Lua)
|
||||
ClientInstance = Client:new()
|
||||
dofile "lua/client/client_util.lua"
|
||||
|
|
|
@ -286,6 +286,8 @@ function GetSkillData(skill_name)
|
|||
frequency = "limit"
|
||||
elseif skill.frequency == Skill.Wake then
|
||||
frequency = "wake"
|
||||
elseif skill.frequency == Skill.Quest then
|
||||
frequency = "quest"
|
||||
end
|
||||
return json.encode{
|
||||
skill = Fk:translate(skill_name),
|
||||
|
|
|
@ -154,6 +154,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["AskForChoice"] = "选择",
|
||||
["AskForKingdom"] = "选择势力",
|
||||
["AskForPindian"] = "拼点",
|
||||
["AskForMoveCardInBoard"] = "移动卡牌",
|
||||
["PlayCard"] = "出牌",
|
||||
|
||||
["AskForCardChosen"] = "选牌",
|
||||
|
|
|
@ -372,7 +372,7 @@ function Player:getAttackRange()
|
|||
|
||||
local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or {}
|
||||
for _, skill in ipairs(status_skills) do
|
||||
local correct = skill:getCorrect(self, other)
|
||||
local correct = skill:getCorrect(self)
|
||||
baseAttackRange = baseAttackRange + correct
|
||||
end
|
||||
|
||||
|
@ -429,6 +429,14 @@ function Player:inMyAttackRange(other)
|
|||
if self == other then
|
||||
return false
|
||||
end
|
||||
|
||||
local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or {}
|
||||
for _, skill in ipairs(status_skills) do
|
||||
if skill:withinAttackRange(self, other) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local baseAttackRange = self:getAttackRange()
|
||||
return self:distanceTo(other) <= baseAttackRange
|
||||
end
|
||||
|
@ -743,6 +751,10 @@ function Player:getSwitchSkillState(skillName, afterUse)
|
|||
end
|
||||
|
||||
function Player:canMoveCardInBoardTo(to, id)
|
||||
if self == to then
|
||||
return false
|
||||
end
|
||||
|
||||
local card = Fk:getCardById(id)
|
||||
assert(card.type == Card.TypeEquip or card.sub_type == Card.SubtypeDelayedTrick)
|
||||
|
||||
|
@ -755,4 +767,34 @@ function Player:canMoveCardInBoardTo(to, id)
|
|||
end
|
||||
end
|
||||
|
||||
function Player:canMoveCardsInBoardTo(to, flag)
|
||||
if self == to then
|
||||
return false
|
||||
end
|
||||
|
||||
assert(flag == nil or flag == "e" or flag == "j")
|
||||
|
||||
local areas = {}
|
||||
if flag == "e" then
|
||||
table.insert(areas, Player.Equip)
|
||||
elseif flag == "j" then
|
||||
table.insert(areas, Player.Judge)
|
||||
else
|
||||
areas = { Player.Equip, Player.Judge }
|
||||
end
|
||||
|
||||
for _, cardId in ipairs(self:getCardIds(areas)) do
|
||||
if self:canMoveCardInBoardTo(to, cardId) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function Player:getQuestSkillState(skillName)
|
||||
local questSkillState = self:getMark(MarkEnum.QuestSkillPreName .. skillName)
|
||||
return type(questSkillState) == "string" and questSkillState or nil
|
||||
end
|
||||
|
||||
return Player
|
||||
|
|
|
@ -22,6 +22,7 @@ Skill.NotFrequent = 2
|
|||
Skill.Compulsory = 3
|
||||
Skill.Limited = 4
|
||||
Skill.Wake = 5
|
||||
Skill.Quest = 6
|
||||
|
||||
--- 构造函数,不可随意调用。
|
||||
---@param name string @ 技能名
|
||||
|
|
|
@ -120,11 +120,11 @@ function ActiveSkill:getMaxCardNum()
|
|||
end
|
||||
end
|
||||
|
||||
function ActiveSkill:getDistanceLimit(player, card)
|
||||
function ActiveSkill:getDistanceLimit(player, card, to)
|
||||
local ret = self.distance_limit or 0
|
||||
local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or {}
|
||||
for _, skill in ipairs(status_skills) do
|
||||
local correct = skill:getDistanceLimit(player, self, card)
|
||||
local correct = skill:getDistanceLimit(player, self, card, to)
|
||||
if correct == nil then correct = 0 end
|
||||
ret = ret + correct
|
||||
end
|
||||
|
|
|
@ -6,8 +6,12 @@ local AttackRangeSkill = StatusSkill:subclass("AttackRangeSkill")
|
|||
---@param from Player
|
||||
---@param to Player
|
||||
---@return integer
|
||||
function AttackRangeSkill:getCorrect(from, to)
|
||||
function AttackRangeSkill:getCorrect(from)
|
||||
return 0
|
||||
end
|
||||
|
||||
function AttackRangeSkill:withinAttackRange(from, to)
|
||||
return false
|
||||
end
|
||||
|
||||
return AttackRangeSkill
|
||||
|
|
|
@ -7,14 +7,14 @@ local TargetModSkill = StatusSkill:subclass("TargetModSkill")
|
|||
---@param card_skill ActiveSkill
|
||||
---@param scope integer
|
||||
---@param card Card
|
||||
function TargetModSkill:getResidueNum(player, card_skill, scope, card)
|
||||
function TargetModSkill:getResidueNum(player, card_skill, scope, card, to)
|
||||
return 0
|
||||
end
|
||||
|
||||
---@param player Player
|
||||
---@param card_skill ActiveSkill
|
||||
---@param card Card
|
||||
function TargetModSkill:getDistanceLimit(player, card_skill, card)
|
||||
function TargetModSkill:getDistanceLimit(player, card_skill, card, to)
|
||||
return 0
|
||||
end
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ function UsableSkill:initialize(name, frequency)
|
|||
self.max_use_time = {9999, 9999, 9999, 9999}
|
||||
end
|
||||
|
||||
function UsableSkill:getMaxUseTime(player, scope, card)
|
||||
function UsableSkill:getMaxUseTime(player, scope, card, to)
|
||||
scope = scope or Player.HistoryTurn
|
||||
local ret = self.max_use_time[scope]
|
||||
local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or {}
|
||||
for _, skill in ipairs(status_skills) do
|
||||
local correct = skill:getResidueNum(player, self, scope, card)
|
||||
local correct = skill:getResidueNum(player, self, scope, card, to)
|
||||
if correct == nil then correct = 0 end
|
||||
ret = ret + correct
|
||||
end
|
||||
|
|
|
@ -300,17 +300,23 @@ function fk.CreateProhibitSkill(spec)
|
|||
end
|
||||
|
||||
---@class AttackRangeSpec: StatusSkillSpec
|
||||
---@field public correct_func fun(self: AttackRangeSkill, from: Player, to: Player)
|
||||
---@field public correct_func fun(self: AttackRangeSkill, from: Player)
|
||||
---@field public within_func fun(self: AttackRangeSkill, from: Player, to: Player)
|
||||
|
||||
---@param spec AttackRangeSpec
|
||||
---@return AttackRangeSkill
|
||||
function fk.CreateAttackRangeSkill(spec)
|
||||
assert(type(spec.name) == "string")
|
||||
assert(type(spec.correct_func) == "function")
|
||||
assert(type(spec.correct_func) == "function" or type(spec.within_func) == "function")
|
||||
|
||||
local skill = AttackRangeSkill:new(spec.name)
|
||||
readStatusSpecToSkill(skill, spec)
|
||||
skill.getCorrect = spec.correct_func
|
||||
if spec.correct_func then
|
||||
skill.getCorrect = spec.correct_func
|
||||
end
|
||||
if spec.within_func then
|
||||
skill.withinAttackRange = spec.within_func
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
@ -338,8 +344,8 @@ function fk.CreateMaxCardsSkill(spec)
|
|||
end
|
||||
|
||||
---@class TargetModSpec: StatusSkillSpec
|
||||
---@field public residue_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, scope: integer, card: Card)
|
||||
---@field public distance_limit_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, card: Card)
|
||||
---@field public residue_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, scope: integer, card: Card, to: Player)
|
||||
---@field public distance_limit_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, card: Card, to: Player)
|
||||
---@field public extra_target_func fun(self: TargetModSkill, player: Player, skill: ActiveSkill, card: Card)
|
||||
|
||||
---@param spec TargetModSpec
|
||||
|
|
|
@ -43,7 +43,9 @@ fk.FinishJudge = 27
|
|||
fk.RoundStart = 28
|
||||
fk.RoundEnd = 29
|
||||
|
||||
fk.BeforeTurnOver = 79
|
||||
fk.TurnedOver = 30
|
||||
fk.BeforeChainStateChange = 80
|
||||
fk.ChainStateChanged = 31
|
||||
|
||||
fk.PreDamage = 32
|
||||
|
@ -106,4 +108,7 @@ fk.CardShown = 77
|
|||
|
||||
-- 78 = GamePrepared
|
||||
|
||||
fk.NumOfEvents = 79
|
||||
-- 79 = BeforeTurnOver
|
||||
-- 80 = BeforeChainStateChange
|
||||
|
||||
fk.NumOfEvents = 81
|
||||
|
|
|
@ -101,6 +101,14 @@ end
|
|||
GameEvent.functions[GameEvent.Damage] = function(self)
|
||||
local damageStruct = table.unpack(self.data)
|
||||
local self = self.room
|
||||
if damageStruct.card and damageStruct.skillName == damageStruct.card.name .. "_skill" and not damageStruct.chain then
|
||||
local cardEffectData = self.logic:getCurrentEvent():findParent(GameEvent.CardEffect)
|
||||
if cardEffectData then
|
||||
local cardEffectEvent = cardEffectData.data[1]
|
||||
damageStruct.damage = damageStruct.damage + (cardEffectEvent.additionalDamage or 0)
|
||||
end
|
||||
end
|
||||
|
||||
if damageStruct.damage < 1 then
|
||||
return false
|
||||
end
|
||||
|
@ -131,6 +139,15 @@ GameEvent.functions[GameEvent.Damage] = function(self)
|
|||
return false
|
||||
end
|
||||
|
||||
if damageStruct.card and damageStruct.damage > 0 then
|
||||
local parentUseData = self.logic:getCurrentEvent():findParent(GameEvent.UseCard)
|
||||
if parentUseData then
|
||||
local cardUseEvent = parentUseData.data[1]
|
||||
cardUseEvent.damageDealt = cardUseEvent.damageDealt or {}
|
||||
cardUseEvent.damageDealt[damageStruct.to.id] = (cardUseEvent.damageDealt[damageStruct.to.id] or 0) + damageStruct.damage
|
||||
end
|
||||
end
|
||||
|
||||
-- 先扣减护甲,再扣体力值
|
||||
local shield_to_lose = math.min(damageStruct.damage, damageStruct.to.shield)
|
||||
self:changeShield(damageStruct.to, -shield_to_lose)
|
||||
|
@ -191,6 +208,14 @@ end
|
|||
GameEvent.functions[GameEvent.Recover] = function(self)
|
||||
local recoverStruct = table.unpack(self.data)
|
||||
local self = self.room
|
||||
if recoverStruct.card then
|
||||
local cardEffectData = self.logic:getCurrentEvent():findParent(GameEvent.CardEffect)
|
||||
if cardEffectData then
|
||||
local cardEffectEvent = cardEffectData.data[1]
|
||||
recoverStruct.num = recoverStruct.num + (cardEffectEvent.additionalRecover or 0)
|
||||
end
|
||||
end
|
||||
|
||||
if recoverStruct.num < 1 then
|
||||
return false
|
||||
end
|
||||
|
|
|
@ -18,6 +18,7 @@ dofile "lua/server/events/movecard.lua"
|
|||
|
||||
GameEvent.UseCard = 9
|
||||
GameEvent.RespondCard = 10
|
||||
GameEvent.CardEffect = 20
|
||||
dofile "lua/server/events/usecard.lua"
|
||||
|
||||
GameEvent.SkillEffect = 11
|
||||
|
@ -51,6 +52,7 @@ local eventTranslations = {
|
|||
[GameEvent.MoveCards] = "GameEvent.MoveCards",
|
||||
[GameEvent.UseCard] = "GameEvent.UseCard",
|
||||
[GameEvent.RespondCard] = "GameEvent.RespondCard",
|
||||
[GameEvent.CardEffect] = "GameEvent.CardEffect",
|
||||
[GameEvent.SkillEffect] = "GameEvent.SkillEffect",
|
||||
[GameEvent.Judge] = "GameEvent.Judge",
|
||||
[GameEvent.DrawInitial] = "GameEvent.DrawInitial",
|
||||
|
|
|
@ -275,3 +275,39 @@ GameEvent.cleaners[GameEvent.RespondCard] = function(self)
|
|||
})
|
||||
end
|
||||
end
|
||||
|
||||
GameEvent.functions[GameEvent.CardEffect] = function(self)
|
||||
local cardEffectEvent = table.unpack(self.data)
|
||||
local self = self.room
|
||||
|
||||
for _, event in ipairs({ fk.PreCardEffect, fk.BeforeCardEffect, fk.CardEffecting, fk.CardEffectFinished }) do
|
||||
if cardEffectEvent.isCancellOut then
|
||||
local user = cardEffectEvent.from and self:getPlayerById(cardEffectEvent.from) or nil
|
||||
if self.logic:trigger(fk.CardEffectCancelledOut, user, cardEffectEvent) then
|
||||
cardEffectEvent.isCancellOut = false
|
||||
else
|
||||
self.logic:breakEvent()
|
||||
end
|
||||
end
|
||||
|
||||
if
|
||||
not cardEffectEvent.toCard and
|
||||
(
|
||||
not (self:getPlayerById(cardEffectEvent.to):isAlive() and cardEffectEvent.to)
|
||||
or #self:deadPlayerFilter(TargetGroup:getRealTargets(cardEffectEvent.tos)) == 0
|
||||
)
|
||||
then
|
||||
self.logic:breakEvent()
|
||||
end
|
||||
|
||||
if table.contains((cardEffectEvent.nullifiedTargets or {}), cardEffectEvent.to) then
|
||||
self.logic:breakEvent()
|
||||
end
|
||||
|
||||
if cardEffectEvent.from and self.logic:trigger(event, self:getPlayerById(cardEffectEvent.from), cardEffectEvent) then
|
||||
self.logic:breakEvent()
|
||||
end
|
||||
|
||||
self:handleCardEffect(event, cardEffectEvent)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,4 +5,16 @@ MarkEnum = {}
|
|||
---@field StraightToWake string @ 跳过觉醒标记(值为技能名通过+连接)
|
||||
MarkEnum.StraightToWake = "_straight_to_wake"
|
||||
|
||||
---@field SwithSkillPreName string @ 转换技状态标记前缀(整体为前缀+转换技技能)
|
||||
MarkEnum.SwithSkillPreName = "__switcher_"
|
||||
---@field SwithSkillPreName string @ 转换技状态标记前缀(整体为前缀+转换技技能)
|
||||
MarkEnum.QuestSkillPreName = "__questPre_"
|
||||
|
||||
---@field AddMaxCards string @ 增加标记值数量的手牌上限
|
||||
MarkEnum.AddMaxCards = "AddMaxCards"
|
||||
---@field AddMaxCardsInTurn string @ 于本回合内增加标记值数量的手牌上限
|
||||
MarkEnum.AddMaxCardsInTurn = "AddMaxCards-turn"
|
||||
---@field MinusMaxCards string @ 减少标记值数量的手牌上限
|
||||
MarkEnum.MinusMaxCards = "MinusMaxCards"
|
||||
---@field AddMaxCards string @ 于本回合内减少标记值数量的手牌上限
|
||||
MarkEnum.MinusMaxCardsInTurn = "MinusMaxCards-turn"
|
||||
|
|
|
@ -927,7 +927,7 @@ Room.askForUseViewAsSkill = Room.askForUseActiveSkill
|
|||
---@param pattern string @ 弃牌需要符合的规则
|
||||
---@param prompt string @ 提示信息
|
||||
---@return integer[] @ 弃掉的牌的id列表,可能是空的
|
||||
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt)
|
||||
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt, skipDiscard)
|
||||
cancelable = cancelable or false
|
||||
pattern = pattern or ""
|
||||
|
||||
|
@ -975,7 +975,10 @@ function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, can
|
|||
toDiscard = table.random(canDiscards, minNum)
|
||||
end
|
||||
|
||||
self:throwCard(toDiscard, skillName, player, player)
|
||||
if not skipDiscard then
|
||||
self:throwCard(toDiscard, skillName, player, player)
|
||||
end
|
||||
|
||||
return toDiscard
|
||||
end
|
||||
|
||||
|
@ -1390,6 +1393,23 @@ end
|
|||
---@param event_data CardEffectEvent|nil @ 事件信息
|
||||
---@return CardUseStruct | nil @ 返回关于本次使用牌的数据,以便后续处理
|
||||
function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extra_data, event_data)
|
||||
if event_data and (event_data.disresponsive or table.contains(event_data.disresponsiveList or {}, player.id)) then
|
||||
return nil
|
||||
end
|
||||
|
||||
if event_data and event_data.prohibitedCardNames and card_name then
|
||||
local splitedCardNames = card_name:split(",")
|
||||
splitedCardNames = table.filter(splitedCardNames, function(name)
|
||||
return not table.contains(event_data.prohibitedCardNames, name)
|
||||
end)
|
||||
|
||||
if #splitedCardNames == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
card_name = table.concat(splitedCardNames, ",")
|
||||
end
|
||||
|
||||
local command = "AskForUseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = cancelable or false
|
||||
|
@ -1429,8 +1449,13 @@ end
|
|||
---@param prompt string @ 提示信息
|
||||
---@param cancelable boolean @ 能否取消
|
||||
---@param extra_data any @ 额外数据
|
||||
---@param effectData CardEffectEvent @ 关联的卡牌生效流程
|
||||
---@return Card | nil @ 打出的牌
|
||||
function Room:askForResponse(player, card_name, pattern, prompt, cancelable, extra_data)
|
||||
function Room:askForResponse(player, card_name, pattern, prompt, cancelable, extra_data, effectData)
|
||||
if effectData and (effectData.disresponsive or table.contains(effectData.disresponsiveList or {}, player.id)) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local command = "AskForResponseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = cancelable or false
|
||||
|
@ -1576,44 +1601,63 @@ end
|
|||
---@field targetOne ServerPlayer
|
||||
---@field targetTwo ServerPlayer
|
||||
---@field skillName string
|
||||
---@field flag string|null
|
||||
---@field moveFrom ServerPlayer|null
|
||||
---@return cardId
|
||||
function Room:askForMoveCardInBoard(player, targetOne, targetTwo, skillName)
|
||||
function Room:askForMoveCardInBoard(player, targetOne, targetTwo, skillName, flag, moveFrom)
|
||||
if flag then
|
||||
assert(flag == "e" or flag == "j")
|
||||
end
|
||||
|
||||
local cards = {}
|
||||
local cardsPosition = {}
|
||||
for _, equipId in ipairs(targetOne:getCardIds(Player.Equip)) do
|
||||
if targetOne:canMoveCardInBoardTo(targetTwo, equipId) then
|
||||
table.insert(cards, equipId)
|
||||
|
||||
if not flag or flag == "e" then
|
||||
if not moveFrom or moveFrom == targetOne then
|
||||
for _, equipId in ipairs(targetOne:getCardIds(Player.Equip)) do
|
||||
if targetOne:canMoveCardInBoardTo(targetTwo, equipId) then
|
||||
table.insert(cards, equipId)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, equipId in ipairs(targetTwo:getCardIds(Player.Equip)) do
|
||||
if targetTwo:canMoveCardInBoardTo(targetOne, equipId) then
|
||||
table.insert(cards, equipId)
|
||||
if not moveFrom or moveFrom == targetTwo then
|
||||
for _, equipId in ipairs(targetTwo:getCardIds(Player.Equip)) do
|
||||
if targetTwo:canMoveCardInBoardTo(targetOne, equipId) then
|
||||
table.insert(cards, equipId)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #cards > 0 then
|
||||
table.sort(cards, function(prev, next)
|
||||
local prevSubType = Fk:getCardById(prev).sub_type
|
||||
local nextSubType = Fk:getCardById(next).sub_type
|
||||
|
||||
return prevSubType < nextSubType
|
||||
end)
|
||||
|
||||
for _, id in ipairs(cards) do
|
||||
table.insert(cardsPosition, self:getCardOwner(id) == targetOne and 0 or 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #cards > 0 then
|
||||
table.sort(cards, function(prev, next)
|
||||
local prevSubType = Fk:getCardById(prev).sub_type
|
||||
local nextSubType = Fk:getCardById(next).sub_type
|
||||
|
||||
return prevSubType < nextSubType
|
||||
end)
|
||||
|
||||
for _, id in ipairs(cards) do
|
||||
table.insert(cardsPosition, self:getCardOwner(id) == targetOne and 0 or 1)
|
||||
if not flag or flag == "j" then
|
||||
if not moveFrom or moveFrom == targetOne then
|
||||
for _, trickId in ipairs(targetOne:getCardIds(Player.Judge)) do
|
||||
if targetOne:canMoveCardInBoardTo(targetTwo, trickId) then
|
||||
table.insert(cards, trickId)
|
||||
table.insert(cardsPosition, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, trickId in ipairs(targetOne:getCardIds(Player.Judge)) do
|
||||
if targetOne:canMoveCardInBoardTo(targetTwo, trickId) then
|
||||
table.insert(cards, trickId)
|
||||
table.insert(cardsPosition, 0)
|
||||
end
|
||||
end
|
||||
for _, trickId in ipairs(targetTwo:getCardIds(Player.Judge)) do
|
||||
if targetTwo:canMoveCardInBoardTo(targetOne, trickId) then
|
||||
table.insert(cards, trickId)
|
||||
table.insert(cardsPosition, 1)
|
||||
if not moveFrom or moveFrom == targetTwo then
|
||||
for _, trickId in ipairs(targetTwo:getCardIds(Player.Judge)) do
|
||||
if targetTwo:canMoveCardInBoardTo(targetOne, trickId) then
|
||||
table.insert(cards, trickId)
|
||||
table.insert(cardsPosition, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1648,6 +1692,42 @@ function Room:askForMoveCardInBoard(player, targetOne, targetTwo, skillName)
|
|||
)
|
||||
end
|
||||
|
||||
--- 询问一名玩家从targets中选择若干名玩家出来。
|
||||
---@param player ServerPlayer @ 要做选择的玩家
|
||||
---@param prompt string @ 提示信息
|
||||
---@param skillName string @ 技能名
|
||||
---@param cancelable boolean|null @ 是否可以取消选择
|
||||
---@param flag string|null @ 限定可移动的区域,值为‘e’或‘j’
|
||||
---@return integer[] @ 选择的玩家id列表,可能为空
|
||||
function Room:askForChooseToMoveCardInBoard(player, prompt, skillName, cancelable, flag)
|
||||
if flag then
|
||||
assert(flag == "e" or flag == "j")
|
||||
end
|
||||
cancelable = (not cancelable) and false or true
|
||||
|
||||
local data = {
|
||||
flag = flag,
|
||||
skillName = skillName,
|
||||
}
|
||||
local _, ret = self:askForUseActiveSkill(
|
||||
player,
|
||||
"choose_players_to_move_card_in_board",
|
||||
prompt or "",
|
||||
cancelable,
|
||||
data
|
||||
)
|
||||
|
||||
if ret then
|
||||
return ret.targets
|
||||
else
|
||||
if cancelable then
|
||||
return {}
|
||||
else
|
||||
return self:canMoveCardInBoard(flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- 使用牌
|
||||
------------------------------------------------------------------------
|
||||
|
@ -1698,6 +1778,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
tos = aimGroup,
|
||||
firstTarget = firstTarget,
|
||||
additionalDamage = cardUseEvent.additionalDamage,
|
||||
additionalRecover = cardUseEvent.additionalRecover,
|
||||
extra_data = cardUseEvent.extra_data,
|
||||
}
|
||||
|
||||
|
@ -1884,7 +1965,9 @@ function Room:doCardUseEffect(cardUseEvent)
|
|||
disresponsiveList = cardUseEvent.disresponsiveList,
|
||||
unoffsetableList = cardUseEvent.unoffsetableList,
|
||||
additionalDamage = cardUseEvent.additionalDamage,
|
||||
additionalRecover = cardUseEvent.additionalRecover,
|
||||
cardIdsResponded = cardUseEvent.nullifiedTargets,
|
||||
prohibitedCardNames = cardUseEvent.prohibitedCardNames,
|
||||
extra_data = cardUseEvent.extra_data,
|
||||
}
|
||||
|
||||
|
@ -1905,6 +1988,7 @@ function Room:doCardUseEffect(cardUseEvent)
|
|||
|
||||
cardEffectEvent.subTargets = curAimEvent.subTargets
|
||||
cardEffectEvent.additionalDamage = curAimEvent.additionalDamage
|
||||
cardEffectEvent.additionalRecover = curAimEvent.additionalRecover
|
||||
|
||||
if curAimEvent.disresponsiveList then
|
||||
for _, disresponsivePlayer in ipairs(curAimEvent.disresponsiveList) do
|
||||
|
@ -1938,118 +2022,109 @@ end
|
|||
--- 对卡牌效果数据进行生效
|
||||
---@param cardEffectEvent CardEffectEvent
|
||||
function Room:doCardEffect(cardEffectEvent)
|
||||
for _, event in ipairs({ fk.PreCardEffect, fk.BeforeCardEffect, fk.CardEffecting, fk.CardEffectFinished }) do
|
||||
if cardEffectEvent.isCancellOut then
|
||||
local user = cardEffectEvent.from and self:getPlayerById(cardEffectEvent.from) or nil
|
||||
if self.logic:trigger(fk.CardEffectCancelledOut, user, cardEffectEvent) then
|
||||
cardEffectEvent.isCancellOut = false
|
||||
else
|
||||
break
|
||||
return execGameEvent(GameEvent.CardEffect, cardEffectEvent)
|
||||
end
|
||||
|
||||
---@param cardEffectEvent CardEffectEvent
|
||||
function Room:handleCardEffect(event, cardEffectEvent)
|
||||
if event == fk.PreCardEffect then
|
||||
if cardEffectEvent.card.skill:aboutToEffect(self, cardEffectEvent) then return end
|
||||
if
|
||||
cardEffectEvent.card.trueName == "slash" and
|
||||
not (cardEffectEvent.unoffsetable or table.contains(cardEffectEvent.unoffsetableList or {}, cardEffectEvent.to))
|
||||
then
|
||||
local loopTimes = 1
|
||||
if cardEffectEvent.fixedResponseTimes then
|
||||
if type(cardEffectEvent.fixedResponseTimes) == "table" then
|
||||
loopTimes = cardEffectEvent.fixedResponseTimes["jink"] or 1
|
||||
elseif type(cardEffectEvent.fixedResponseTimes) == "number" then
|
||||
loopTimes = cardEffectEvent.fixedResponseTimes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not cardEffectEvent.toCard and (not (self:getPlayerById(cardEffectEvent.to):isAlive() and cardEffectEvent.to) or #self:deadPlayerFilter(TargetGroup:getRealTargets(cardEffectEvent.tos)) == 0) then
|
||||
break
|
||||
end
|
||||
|
||||
if table.contains((cardEffectEvent.nullifiedTargets or {}), cardEffectEvent.to) then
|
||||
break
|
||||
end
|
||||
|
||||
if cardEffectEvent.from and self.logic:trigger(event, self:getPlayerById(cardEffectEvent.from), cardEffectEvent) then
|
||||
return
|
||||
end
|
||||
|
||||
if event == fk.PreCardEffect then
|
||||
if cardEffectEvent.card.skill:aboutToEffect(self, cardEffectEvent) then return end
|
||||
if cardEffectEvent.card.trueName == "slash" and
|
||||
not (
|
||||
cardEffectEvent.disresponsive or
|
||||
cardEffectEvent.unoffsetable or
|
||||
table.contains(cardEffectEvent.disresponsiveList or {}, cardEffectEvent.to) or
|
||||
table.contains(cardEffectEvent.unoffsetableList or {}, cardEffectEvent.to)
|
||||
) then
|
||||
local loopTimes = 1
|
||||
if cardEffectEvent.fixedResponseTimes then
|
||||
if type(cardEffectEvent.fixedResponseTimes) == "table" then
|
||||
loopTimes = cardEffectEvent.fixedResponseTimes["jink"] or 1
|
||||
elseif type(cardEffectEvent.fixedResponseTimes) == "number" then
|
||||
loopTimes = cardEffectEvent.fixedResponseTimes
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, loopTimes do
|
||||
local to = self:getPlayerById(cardEffectEvent.to)
|
||||
local prompt = ""
|
||||
if cardEffectEvent.from then
|
||||
prompt = "#slash-jink:" .. cardEffectEvent.from .. "::" .. 1
|
||||
end
|
||||
|
||||
local use = self:askForUseCard(
|
||||
to,
|
||||
"jink",
|
||||
nil,
|
||||
prompt,
|
||||
true,
|
||||
nil,
|
||||
cardEffectEvent
|
||||
)
|
||||
if use then
|
||||
use.toCard = cardEffectEvent.card
|
||||
use.responseToEvent = cardEffectEvent
|
||||
self:useCard(use)
|
||||
end
|
||||
|
||||
if not cardEffectEvent.isCancellOut then
|
||||
break
|
||||
end
|
||||
|
||||
cardEffectEvent.isCancellOut = i == loopTimes
|
||||
end
|
||||
elseif cardEffectEvent.card.type == Card.TypeTrick and
|
||||
not cardEffectEvent.disresponsive then
|
||||
local players = {}
|
||||
for _, p in ipairs(self.alive_players) do
|
||||
local cards = p:getCardIds(Player.Hand)
|
||||
for _, cid in ipairs(cards) do
|
||||
if Fk:getCardById(cid).name == "nullification" and
|
||||
not table.contains(cardEffectEvent.disresponsiveList or {}, p.id) then
|
||||
table.insert(players, p)
|
||||
break
|
||||
end
|
||||
end
|
||||
if not table.contains(players, p) then
|
||||
for _, s in ipairs(p.player_skills) do
|
||||
if s.pattern and Exppattern:Parse("nullification"):matchExp(s.pattern)
|
||||
and not table.contains(cardEffectEvent.disresponsiveList or {}, p.id) then
|
||||
table.insert(players, p)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, loopTimes do
|
||||
local to = self:getPlayerById(cardEffectEvent.to)
|
||||
local prompt = ""
|
||||
if cardEffectEvent.to then
|
||||
prompt = "#AskForNullification::" .. cardEffectEvent.to .. ":" .. cardEffectEvent.card.name
|
||||
elseif cardEffectEvent.from then
|
||||
prompt = "#AskForNullificationWithoutTo:" .. cardEffectEvent.from .. "::" .. cardEffectEvent.card.name
|
||||
if cardEffectEvent.from then
|
||||
prompt = "#slash-jink:" .. cardEffectEvent.from .. "::" .. 1
|
||||
end
|
||||
local use = self:askForNullification(players, nil, nil, prompt)
|
||||
|
||||
local use = self:askForUseCard(
|
||||
to,
|
||||
"jink",
|
||||
nil,
|
||||
prompt,
|
||||
true,
|
||||
nil,
|
||||
cardEffectEvent
|
||||
)
|
||||
if use then
|
||||
use.toCard = cardEffectEvent.card
|
||||
use.responseToEvent = cardEffectEvent
|
||||
self:useCard(use)
|
||||
end
|
||||
|
||||
if not cardEffectEvent.isCancellOut then
|
||||
break
|
||||
end
|
||||
|
||||
cardEffectEvent.isCancellOut = i == loopTimes
|
||||
end
|
||||
elseif
|
||||
cardEffectEvent.card.type == Card.TypeTrick and
|
||||
not (cardEffectEvent.disresponsive or cardEffectEvent.unoffsetable) and
|
||||
not table.contains(cardEffectEvent.prohibitedCardNames or {}, "nullification")
|
||||
then
|
||||
local players = {}
|
||||
for _, p in ipairs(self.alive_players) do
|
||||
local cards = p:getCardIds(Player.Hand)
|
||||
for _, cid in ipairs(cards) do
|
||||
if
|
||||
Fk:getCardById(cid).name == "nullification" and
|
||||
not (
|
||||
table.contains(cardEffectEvent.disresponsiveList or {}, p.id) or
|
||||
table.contains(cardEffectEvent.unoffsetableList or {}, p.id)
|
||||
)
|
||||
then
|
||||
table.insert(players, p)
|
||||
break
|
||||
end
|
||||
end
|
||||
if not table.contains(players, p) then
|
||||
for _, s in ipairs(p.player_skills) do
|
||||
if
|
||||
s.pattern and
|
||||
Exppattern:Parse("nullification"):matchExp(s.pattern) and
|
||||
not (
|
||||
table.contains(cardEffectEvent.disresponsiveList or {}, p.id) or
|
||||
table.contains(cardEffectEvent.unoffsetableList or {}, p.id)
|
||||
)
|
||||
then
|
||||
table.insert(players, p)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local prompt = ""
|
||||
if cardEffectEvent.to then
|
||||
prompt = "#AskForNullification::" .. cardEffectEvent.to .. ":" .. cardEffectEvent.card.name
|
||||
elseif cardEffectEvent.from then
|
||||
prompt = "#AskForNullificationWithoutTo:" .. cardEffectEvent.from .. "::" .. cardEffectEvent.card.name
|
||||
end
|
||||
local use = self:askForNullification(players, nil, nil, prompt)
|
||||
if use then
|
||||
use.toCard = cardEffectEvent.card
|
||||
use.responseToEvent = cardEffectEvent
|
||||
self:useCard(use)
|
||||
end
|
||||
end
|
||||
|
||||
if event == fk.CardEffecting then
|
||||
if cardEffectEvent.card.skill then
|
||||
execGameEvent(GameEvent.SkillEffect, function ()
|
||||
cardEffectEvent.card.skill:onEffect(self, cardEffectEvent)
|
||||
end)
|
||||
end
|
||||
elseif event == fk.CardEffecting then
|
||||
if cardEffectEvent.card.skill then
|
||||
execGameEvent(GameEvent.SkillEffect, function ()
|
||||
cardEffectEvent.card.skill:onEffect(self, cardEffectEvent)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2687,6 +2762,44 @@ function Room:getCardsFromPileByRule(pattern, num, fromPile)
|
|||
return cardPack
|
||||
end
|
||||
|
||||
---@param flag string|null
|
||||
---@param players ServerPlayer[]|null
|
||||
---@return PlayerId[] @ 可能为空
|
||||
function Room:canMoveCardInBoard(flag, players)
|
||||
if flag then
|
||||
assert(flag == "e" or flag == "j")
|
||||
end
|
||||
|
||||
players = players or self.alive_players
|
||||
|
||||
local targets = {}
|
||||
table.find(players, function(p)
|
||||
local canMoveTo = table.find(players, function(another)
|
||||
return p ~= another and p:canMoveCardsInBoardTo(another, flag)
|
||||
end)
|
||||
|
||||
if canMoveTo then
|
||||
targets = {p.id, canMoveTo.id}
|
||||
end
|
||||
return canMoveTo
|
||||
end)
|
||||
|
||||
return targets
|
||||
end
|
||||
|
||||
function Room:updateQuestSkillState(player, skillName, failed)
|
||||
assert(Fk.skills[skillName].frequency == Skill.Quest)
|
||||
|
||||
self:setPlayerMark(player, MarkEnum.QuestSkillPreName .. skillName, failed and "failed" or "succeed")
|
||||
local updateValue = failed and 2 or 1
|
||||
|
||||
self:doBroadcastNotify("UpdateQuestSkillUI", json.encode{
|
||||
player.id,
|
||||
skillName,
|
||||
updateValue,
|
||||
})
|
||||
end
|
||||
|
||||
function CreateRoom(_room)
|
||||
RoomInstance = Room:new(_room)
|
||||
end
|
||||
|
|
|
@ -324,6 +324,10 @@ function ServerPlayer:getNextAlive()
|
|||
end
|
||||
|
||||
function ServerPlayer:turnOver()
|
||||
if self.room.logic:trigger(fk.BeforeTurnOver, self) then
|
||||
return
|
||||
end
|
||||
|
||||
self.faceup = not self.faceup
|
||||
self.room:broadcastProperty(self, "faceup")
|
||||
|
||||
|
@ -332,6 +336,7 @@ function ServerPlayer:turnOver()
|
|||
from = self.id,
|
||||
arg = self.faceup and "face_up" or "face_down",
|
||||
}
|
||||
|
||||
self.room.logic:trigger(fk.TurnedOver, self)
|
||||
end
|
||||
|
||||
|
@ -593,6 +598,10 @@ end
|
|||
|
||||
---@param chained boolean
|
||||
function ServerPlayer:setChainState(chained)
|
||||
if self.room.logic:trigger(fk.BeforeChainStateChange, self) then
|
||||
return
|
||||
end
|
||||
|
||||
self.chained = chained
|
||||
self.room:broadcastProperty(self, "chained")
|
||||
self.room:sendLog{
|
||||
|
@ -600,6 +609,8 @@ function ServerPlayer:setChainState(chained)
|
|||
from = self.id,
|
||||
arg = self.chained and "chained" or "not-chained"
|
||||
}
|
||||
|
||||
self.room.logic:trigger(fk.ChainStateChanged, self)
|
||||
end
|
||||
|
||||
---@param from ServerPlayer
|
||||
|
|
|
@ -93,8 +93,11 @@ fk.IceDamage = 4
|
|||
---@field public disresponsiveList integer[]|null
|
||||
---@field public unoffsetableList integer[]|null
|
||||
---@field public additionalDamage integer|null
|
||||
---@field public additionalRecover integer|null
|
||||
---@field public customFrom integer|null
|
||||
---@field public cardsResponded Card[]|null
|
||||
---@field public prohibitedCardNames string[]|null
|
||||
---@field public damageDealt table<PlayerId, number>|null
|
||||
|
||||
---@class AimStruct
|
||||
---@field public from integer
|
||||
|
@ -106,6 +109,7 @@ fk.IceDamage = 4
|
|||
---@field public nullifiedTargets integer[]|null
|
||||
---@field public firstTarget boolean
|
||||
---@field public additionalDamage integer|null
|
||||
---@field public additionalRecover integer|null
|
||||
---@field public disresponsive boolean|null
|
||||
---@field public unoffsetableList boolean|null
|
||||
---@field public additionalResponseTimes table<string, integer>|integer|null
|
||||
|
@ -124,6 +128,7 @@ fk.IceDamage = 4
|
|||
---@field public disresponsiveList integer[]|null
|
||||
---@field public unoffsetableList integer[]|null
|
||||
---@field public additionalDamage integer|null
|
||||
---@field public additionalRecover integer|null
|
||||
---@field public customFrom integer|null
|
||||
---@field public cardsResponded Card[]|null
|
||||
---@field public disresponsive boolean|null
|
||||
|
@ -131,6 +136,7 @@ fk.IceDamage = 4
|
|||
---@field public isCancellOut boolean|null
|
||||
---@field public fixedResponseTimes table<string, integer>|integer|null
|
||||
---@field public fixedAddTimesResponsors integer[]
|
||||
---@field public prohibitedCardNames string[]|null
|
||||
|
||||
---@class SkillEffectEvent
|
||||
---@field public from integer
|
||||
|
|
|
@ -18,7 +18,7 @@ local thunderSlashSkill = fk.CreateActiveSkill{
|
|||
from = room:getPlayerById(from),
|
||||
to = room:getPlayerById(to),
|
||||
card = effect.card,
|
||||
damage = 1 + (effect.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.ThunderDamage,
|
||||
skillName = self.name
|
||||
})
|
||||
|
@ -56,7 +56,7 @@ local fireSlashSkill = fk.CreateActiveSkill{
|
|||
from = room:getPlayerById(from),
|
||||
to = room:getPlayerById(to),
|
||||
card = effect.card,
|
||||
damage = 1 + (effect.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.FireDamage,
|
||||
skillName = self.name
|
||||
})
|
||||
|
@ -80,7 +80,7 @@ local analepticSkill = fk.CreateActiveSkill{
|
|||
name = "analeptic_skill",
|
||||
max_turn_use_time = 1,
|
||||
can_use = function(self, player, card)
|
||||
return player:usedCardTimes("analeptic", Player.HistoryTurn) < self:getMaxUseTime(Self, Player.HistoryTurn, card)
|
||||
return player:usedCardTimes("analeptic", Player.HistoryTurn) < self:getMaxUseTime(Self, Player.HistoryTurn, card, Self)
|
||||
end,
|
||||
on_use = function(self, room, use)
|
||||
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
|
||||
|
@ -250,7 +250,7 @@ local fireAttackSkill = fk.CreateActiveSkill{
|
|||
from = from,
|
||||
to = to,
|
||||
card = cardEffectEvent.card,
|
||||
damage = 1 + (cardEffectEvent.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.FireDamage,
|
||||
skillName = self.name
|
||||
})
|
||||
|
@ -276,7 +276,7 @@ local supplyShortageSkill = fk.CreateActiveSkill{
|
|||
local player = Fk:currentRoom():getPlayerById(to_select)
|
||||
if Self ~= player then
|
||||
return not player:hasDelayedTrick("supply_shortage") and
|
||||
Self:distanceTo(player) <= self:getDistanceLimit(Self, card)
|
||||
Self:distanceTo(player) <= self:getDistanceLimit(Self, card, Fk:currentRoom():getPlayerById(to_select))
|
||||
end
|
||||
end
|
||||
return false
|
||||
|
|
|
@ -74,7 +74,27 @@ local maxCardsSkill = fk.CreateMaxCardsSkill{
|
|||
name = "max_cards_skill",
|
||||
global = true,
|
||||
correct_func = function(self, player)
|
||||
return player:getMark("AddMaxCards") + player:getMark("AddMaxCards-turn") - player:getMark("MinusMaxCards") - player:getMark("MinusMaxCards-turn")
|
||||
return
|
||||
player:getMark(MarkEnum.AddMaxCards) +
|
||||
player:getMark(MarkEnum.AddMaxCardsInTurn) -
|
||||
player:getMark(MarkEnum.MinusMaxCards) -
|
||||
player:getMark(MarkEnum.MinusMaxCardsInTurn)
|
||||
end,
|
||||
}
|
||||
|
||||
local choosePlayersToMoveCardInBoardSkill = fk.CreateActiveSkill{
|
||||
name = "choose_players_to_move_card_in_board",
|
||||
target_num = 2,
|
||||
card_filter = function(self, to_select)
|
||||
return false
|
||||
end,
|
||||
target_filter = function(self, to_select, selected, cards)
|
||||
local target = Fk:currentRoom():getPlayerById(to_select)
|
||||
if #selected > 0 then
|
||||
return Fk:currentRoom():getPlayerById(selected[1]):canMoveCardsInBoardTo(target, self.flag)
|
||||
end
|
||||
|
||||
return #target:getCardIds({ Player.Equip, Player.Judge }) > 0
|
||||
end,
|
||||
}
|
||||
|
||||
|
@ -83,4 +103,5 @@ AuxSkills = {
|
|||
chooseCardsSkill,
|
||||
choosePlayersSkill,
|
||||
maxCardsSkill,
|
||||
choosePlayersToMoveCardInBoardSkill,
|
||||
}
|
||||
|
|
|
@ -418,6 +418,7 @@ Fk:loadTranslationTable{
|
|||
["discard_skill"] = "弃牌",
|
||||
["choose_cards_skill"] = "选牌",
|
||||
["choose_players_skill"] = "选择角色",
|
||||
["choose_players_to_move_card_in_board"] = "选择角色",
|
||||
|
||||
["game_rule"] = "弃牌阶段",
|
||||
}
|
||||
|
|
|
@ -1085,9 +1085,7 @@ local lijian = fk.CreateActiveSkill{
|
|||
new_use.from = use.tos[2]
|
||||
new_use.tos = { { use.tos[1] } }
|
||||
new_use.card = duel
|
||||
new_use.unoffsetableList = table.map(room:getAlivePlayers(), function(e)
|
||||
return e.id
|
||||
end)
|
||||
new_use.prohibitedCardNames = { "nullification" }
|
||||
room:useCard(new_use)
|
||||
end,
|
||||
}
|
||||
|
|
|
@ -30,13 +30,16 @@ local slashSkill = fk.CreateActiveSkill{
|
|||
max_phase_use_time = 1,
|
||||
target_num = 1,
|
||||
can_use = function(self, player, card)
|
||||
return player:usedCardTimes("slash", Player.HistoryPhase) < self:getMaxUseTime(Self, Player.HistoryPhase, card)
|
||||
return
|
||||
table.find(Fk:currentRoom().alive_players, function(p)
|
||||
return player:usedCardTimes("slash", Player.HistoryPhase) < self:getMaxUseTime(Self, Player.HistoryPhase, card, p)
|
||||
end)
|
||||
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:getDistanceLimit(Self, card) -- for no distance limit for slash
|
||||
(self:getDistanceLimit(Self, card, Fk:currentRoom():getPlayerById(to_select)) -- for no distance limit for slash
|
||||
+ Self:getAttackRange()
|
||||
>= Self:distanceTo(player))
|
||||
end
|
||||
|
@ -49,7 +52,7 @@ local slashSkill = fk.CreateActiveSkill{
|
|||
from = room:getPlayerById(from),
|
||||
to = room:getPlayerById(to),
|
||||
card = effect.card,
|
||||
damage = 1 + (effect.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.NormalDamage,
|
||||
skillName = self.name
|
||||
})
|
||||
|
@ -224,8 +227,10 @@ local snatchSkill = fk.CreateActiveSkill{
|
|||
target_filter = function(self, to_select, selected, _, card)
|
||||
if #selected == 0 then
|
||||
local player = Fk:currentRoom():getPlayerById(to_select)
|
||||
return Self ~= player and Self:distanceTo(player) <= self:getDistanceLimit(Self, card) -- for no distance limit for snatch
|
||||
and not player:isAllNude()
|
||||
return
|
||||
Self ~= player and
|
||||
Self:distanceTo(player) <= self:getDistanceLimit(Self, card, Fk:currentRoom():getPlayerById(to_select)) and -- for no distance limit for snatch
|
||||
not player:isAllNude()
|
||||
end
|
||||
end,
|
||||
target_num = 1,
|
||||
|
@ -276,10 +281,6 @@ local duelSkill = fk.CreateActiveSkill{
|
|||
local currentResponser = to
|
||||
|
||||
while currentResponser:isAlive() do
|
||||
if effect.disresponsive or table.contains(effect.disresponsiveList or {}, currentResponser.id) then
|
||||
break
|
||||
end
|
||||
|
||||
local loopTimes = 1
|
||||
if effect.fixedResponseTimes then
|
||||
local canFix = currentResponser == to
|
||||
|
@ -298,7 +299,7 @@ local duelSkill = fk.CreateActiveSkill{
|
|||
|
||||
local cardResponded
|
||||
for i = 1, loopTimes do
|
||||
cardResponded = room:askForResponse(currentResponser, 'slash')
|
||||
cardResponded = room:askForResponse(currentResponser, 'slash', nil, nil, false, nil, effect)
|
||||
if cardResponded then
|
||||
room:responseCard({
|
||||
from = currentResponser.id,
|
||||
|
@ -323,7 +324,7 @@ local duelSkill = fk.CreateActiveSkill{
|
|||
from = responsers[currentTurn % 2 + 1],
|
||||
to = currentResponser,
|
||||
card = effect.card,
|
||||
damage = 1 + (effect.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.NormalDamage,
|
||||
skillName = self.name,
|
||||
})
|
||||
|
@ -364,7 +365,7 @@ local collateralSkill = fk.CreateActiveSkill{
|
|||
local to = room:getPlayerById(effect.to)
|
||||
if not to:getEquipment(Card.SubtypeWeapon) then return end
|
||||
local use = room:askForUseCard(to, "slash", nil, nil, nil,
|
||||
{ must_targets = effect.subTargets })
|
||||
{ must_targets = effect.subTargets }, effect)
|
||||
|
||||
if use then
|
||||
room:useCard(use)
|
||||
|
@ -443,10 +444,7 @@ local savageAssaultSkill = fk.CreateActiveSkill{
|
|||
name = "savage_assault_skill",
|
||||
on_use = aoe_on_use,
|
||||
on_effect = function(self, room, effect)
|
||||
local cardResponded = nil
|
||||
if not (effect.disresponsive or table.contains(effect.disresponsiveList or {}, effect.to)) then
|
||||
cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'slash')
|
||||
end
|
||||
local cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'slash', nil, nil, false, nil, effect)
|
||||
|
||||
if cardResponded then
|
||||
room:responseCard({
|
||||
|
@ -459,7 +457,7 @@ local savageAssaultSkill = fk.CreateActiveSkill{
|
|||
from = room:getPlayerById(effect.from),
|
||||
to = room:getPlayerById(effect.to),
|
||||
card = effect.card,
|
||||
damage = 1 + (effect.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.NormalDamage,
|
||||
skillName = self.name,
|
||||
})
|
||||
|
@ -484,10 +482,7 @@ local archeryAttackSkill = fk.CreateActiveSkill{
|
|||
name = "archery_attack_skill",
|
||||
on_use = aoe_on_use,
|
||||
on_effect = function(self, room, effect)
|
||||
local cardResponded = nil
|
||||
if not (effect.disresponsive or table.contains(effect.disresponsiveList or {}, effect.to)) then
|
||||
cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'jink')
|
||||
end
|
||||
local cardResponded = room:askForResponse(room:getPlayerById(effect.to), 'jink', nil, nil, false, nil, effect)
|
||||
|
||||
if cardResponded then
|
||||
room:responseCard({
|
||||
|
@ -500,7 +495,7 @@ local archeryAttackSkill = fk.CreateActiveSkill{
|
|||
from = room:getPlayerById(effect.from),
|
||||
to = room:getPlayerById(effect.to),
|
||||
card = effect.card,
|
||||
damage = 1 + (effect.additionalDamage or 0),
|
||||
damage = 1,
|
||||
damageType = fk.NormalDamage,
|
||||
skillName = self.name,
|
||||
})
|
||||
|
|
|
@ -37,7 +37,7 @@ local cheat = fk.CreateActiveSkill{
|
|||
return
|
||||
end
|
||||
|
||||
local cardName = room:askForChoice(from, allCardNames, "cheat")
|
||||
local cardName = room:askForChoice(from, allCardNames, "cheat", nil, nil, true)
|
||||
local toGain = nil
|
||||
if #allCardMapper[cardName] > 0 then
|
||||
toGain = allCardMapper[cardName][math.random(1, #allCardMapper[cardName])]
|
||||
|
|
Loading…
Reference in New Issue