From 3b9dd89b10d74cde631c05495fd6f2e417e07d86 Mon Sep 17 00:00:00 2001 From: notify Date: Mon, 29 Jan 2024 10:19:10 +0800 Subject: [PATCH] Fix bugs (#311) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、攻击范围状态技类新增基础值修正函数 2、伤害值在一个技能处理后小于1会终止当前事件 3、不向不能使用【无懈可击】的角色询问使用【无懈可击】 4、修正在濒死插结中有人死亡后仍然会向该角色求桃的情况 5、将PreCardUse和PreCardRespond时机移至实体牌移动之前 6、调整改判函数原判定牌置入弃牌堆的原因 6、修正【朱雀羽扇】、【借刀杀人】、【酒】 Co-authored-by: xxyheaven <1433191064@qq.com> --- lua/core/player.lua | 28 +++++++++---- lua/core/skill_type/attack_range.lua | 6 +++ lua/core/skill_type/distance.lua | 2 +- lua/fk_ex.lua | 6 ++- lua/server/events/death.lua | 6 ++- lua/server/events/usecard.lua | 16 ++++---- lua/server/gamelogic.lua | 4 +- lua/server/room.lua | 59 ++++++++++++++++------------ packages/maneuvering/init.lua | 17 +++++--- packages/standard/game_rule.lua | 2 +- packages/standard_cards/init.lua | 31 ++++++++++----- 11 files changed, 115 insertions(+), 62 deletions(-) diff --git a/lua/core/player.lua b/lua/core/player.lua index e54dcfef..8a9fe445 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -457,16 +457,28 @@ end --- 获取玩家攻击范围。 function Player:getAttackRange() - local weapon = Fk:getCardById(self:getEquipment(Card.SubtypeWeapon)) - local baseAttackRange = math.max(weapon and weapon.attack_range or 1, 0) - - local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable - for _, skill in ipairs(status_skills) do - local correct = skill:getCorrect(self) - baseAttackRange = baseAttackRange + (correct or 0) + local baseValue = 1 + local weapons = self:getEquipments(Card.SubtypeWeapon) + if #weapons > 0 then + baseValue = 0 + for _, id in ipairs(weapons) do + local weapon = Fk:getCardById(id) + baseValue = math.max(baseValue, weapon.attack_range or 1) + end end - return math.max(baseAttackRange, 0) + local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable + local max_fixed, correct = nil, 0 + for _, skill in ipairs(status_skills) do + local f = skill:getFixed(self) + if f ~= nil then + max_fixed = max_fixed and math.max(max_fixed, f) or f + end + local c = skill:getCorrect(self) + correct = correct + (c or 0) + end + + return math.max(math.max(baseValue, (max_fixed or 0)) + correct, 0) end --- 获取角色是否被移除。 diff --git a/lua/core/skill_type/attack_range.lua b/lua/core/skill_type/attack_range.lua index 6a646532..aa48de04 100644 --- a/lua/core/skill_type/attack_range.lua +++ b/lua/core/skill_type/attack_range.lua @@ -9,6 +9,12 @@ function AttackRangeSkill:getCorrect(from) return 0 end +---@param from Player +---@return integer|nil +function AttackRangeSkill:getFixed(from) + return nil +end + function AttackRangeSkill:withinAttackRange(from, to) return false end diff --git a/lua/core/skill_type/distance.lua b/lua/core/skill_type/distance.lua index 681dfc01..b0d6db42 100644 --- a/lua/core/skill_type/distance.lua +++ b/lua/core/skill_type/distance.lua @@ -12,7 +12,7 @@ end ---@param from Player ---@param to Player ----@return integer +---@return integer|nil function DistanceSkill:getFixed(from, to) return nil end diff --git a/lua/fk_ex.lua b/lua/fk_ex.lua index 1cf0d062..f0a9eb0e 100644 --- a/lua/fk_ex.lua +++ b/lua/fk_ex.lua @@ -320,19 +320,23 @@ end ---@class AttackRangeSpec: StatusSkillSpec ---@field public correct_func? fun(self: AttackRangeSkill, from: Player, to: Player): number? +---@field public fixed_func? fun(self: AttackRangeSkill, player: Player): number? ---@field public within_func? fun(self: AttackRangeSkill, from: Player, to: Player): boolean? ---@param spec AttackRangeSpec ---@return AttackRangeSkill function fk.CreateAttackRangeSkill(spec) assert(type(spec.name) == "string") - assert(type(spec.correct_func) == "function" or type(spec.within_func) == "function") + assert(type(spec.correct_func) == "function" or type(spec.fixed_func) == "function" or type(spec.within_func) == "function") local skill = AttackRangeSkill:new(spec.name) readStatusSpecToSkill(skill, spec) if spec.correct_func then skill.getCorrect = spec.correct_func end + if spec.fixed_func then + skill.getFixed = spec.fixed_func + end if spec.within_func then skill.withinAttackRange = spec.within_func end diff --git a/lua/server/events/death.lua b/lua/server/events/death.lua index 67652760..884b775b 100644 --- a/lua/server/events/death.lua +++ b/lua/server/events/death.lua @@ -17,8 +17,10 @@ GameEvent.functions[GameEvent.Dying] = function(self) -- room.logic:trigger(fk.Dying, dyingPlayer, dyingStruct) local savers = room:getAlivePlayers() for _, p in ipairs(savers) do - if dyingPlayer.hp > 0 or dyingPlayer.dead or logic:trigger(fk.AskForPeaches, p, dyingStruct) then - break + if not p.dead then + if dyingPlayer.hp > 0 or dyingPlayer.dead or logic:trigger(fk.AskForPeaches, p, dyingStruct) then + break + end end end logic:trigger(fk.AskForPeachesDone, dyingPlayer, dyingStruct) diff --git a/lua/server/events/usecard.lua b/lua/server/events/usecard.lua index b540c3bf..e0300b92 100644 --- a/lua/server/events/usecard.lua +++ b/lua/server/events/usecard.lua @@ -170,6 +170,10 @@ GameEvent.functions[GameEvent.UseCard] = function(self) local _card = sendCardEmotionAndLog(room, cardUseEvent) + if logic:trigger(fk.PreCardUse, room:getPlayerById(cardUseEvent.from), cardUseEvent) then + logic:breakEvent() + end + room:moveCardTo(cardUseEvent.card, Card.Processing, nil, fk.ReasonUse) local card = cardUseEvent.card @@ -196,10 +200,6 @@ GameEvent.functions[GameEvent.UseCard] = function(self) end end - if logic:trigger(fk.PreCardUse, room:getPlayerById(cardUseEvent.from), cardUseEvent) then - logic:breakEvent() - end - if not cardUseEvent.extraUse then room:getPlayerById(cardUseEvent.from):addCardUseHistory(cardUseEvent.card.trueName, 1) end @@ -270,6 +270,10 @@ GameEvent.functions[GameEvent.RespondCard] = function(self) playCardEmotionAndSound(room, room:getPlayerById(from), card) + if logic:trigger(fk.PreCardRespond, room:getPlayerById(cardResponseEvent.from), cardResponseEvent) then + logic:breakEvent() + end + room:moveCardTo(card, Card.Processing, nil, fk.ReasonResonpse) if #cardIds > 0 then room:sendFootnote(cardIds, { @@ -281,10 +285,6 @@ GameEvent.functions[GameEvent.RespondCard] = function(self) end end - if logic:trigger(fk.PreCardRespond, room:getPlayerById(cardResponseEvent.from), cardResponseEvent) then - logic:breakEvent() - end - logic:trigger(fk.CardResponding, room:getPlayerById(cardResponseEvent.from), cardResponseEvent) end diff --git a/lua/server/gamelogic.lua b/lua/server/gamelogic.lua index ed174f29..e1c72130 100644 --- a/lua/server/gamelogic.lua +++ b/lua/server/gamelogic.lua @@ -395,7 +395,9 @@ function GameLogic:trigger(event, target, data, refresh_only) skill_names = table.map(table.filter(skills, filter_func), Util.NameMapper) broken = broken or (event == fk.AskForPeaches - and room:getPlayerById(data.who).hp > 0) or cur_event.killed + and room:getPlayerById(data.who).hp > 0) or + (table.contains({fk.PreDamage, fk.DamageCaused, fk.DamageInflicted}, event) and data.damage < 1) or + cur_event.killed if broken then break end end diff --git a/lua/server/room.lua b/lua/server/room.lua index 571859ec..f28fd8f7 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -2760,27 +2760,13 @@ function Room:handleCardEffect(event, cardEffectEvent) then local players = {} Fk.currentResponsePattern = "nullification" + local cardCloned = Fk:cloneCard("nullification") for _, p in ipairs(self.alive_players) do - local cards = p:getHandlyIds() - for _, cid in ipairs(cards) do - if - Fk:getCardById(cid).trueName == "nullification" and - not ( - table.contains(cardEffectEvent.disresponsiveList or Util.DummyTable, p.id) or - table.contains(cardEffectEvent.unoffsetableList or Util.DummyTable, p.id) - ) - then - table.insert(players, p) - break - end - end - if not table.contains(players, p) then - Self = p -- for enabledAtResponse - for _, s in ipairs(table.connect(p.player_skills, p._fake_skills)) do + if not p:prohibitUse(cardCloned) then + local cards = p:getHandlyIds() + for _, cid in ipairs(cards) do if - s.pattern and - Exppattern:Parse("nullification"):matchExp(s.pattern) and - not (s.enabledAtResponse and not s:enabledAtResponse(p)) and + Fk:getCardById(cid).trueName == "nullification" and not ( table.contains(cardEffectEvent.disresponsiveList or Util.DummyTable, p.id) or table.contains(cardEffectEvent.unoffsetableList or Util.DummyTable, p.id) @@ -2790,6 +2776,23 @@ function Room:handleCardEffect(event, cardEffectEvent) break end end + if not table.contains(players, p) then + Self = p -- for enabledAtResponse + for _, s in ipairs(table.connect(p.player_skills, p._fake_skills)) do + if + s.pattern and + Exppattern:Parse("nullification"):matchExp(s.pattern) and + not (s.enabledAtResponse and not s:enabledAtResponse(p)) and + not ( + table.contains(cardEffectEvent.disresponsiveList or Util.DummyTable, p.id) or + table.contains(cardEffectEvent.unoffsetableList or Util.DummyTable, p.id) + ) + then + table.insert(players, p) + break + end + end + end end end @@ -3176,12 +3179,6 @@ function Room:retrial(card, player, judge, skillName, exchange) local rebyre = judge.retrial_by_response judge.retrial_by_response = player - local move2 = {} ---@type CardsMoveInfo - move2.ids = { oldJudge:getEffectiveId() } - move2.toArea = exchange and Card.PlayerHand or Card.DiscardPile - move2.moveReason = fk.ReasonJustMove - move2.to = exchange and player.id or nil - self:sendLog{ type = "#ChangedJudge", from = player.id, @@ -3190,8 +3187,18 @@ function Room:retrial(card, player, judge, skillName, exchange) arg = skillName, } - self:moveCards(move2) Fk:filterCard(judge.card.id, judge.who, judge) + + exchange = exchange and not player.dead + + local move2 = {} ---@type CardsMoveInfo + move2.ids = { oldJudge:getEffectiveId() } + move2.toArea = exchange and Card.PlayerHand or Card.DiscardPile + move2.moveReason = exchange and fk.ReasonJustMove or fk.ReasonJudge + move2.to = exchange and player.id or nil + move2.skillName = skillName + + self:moveCards(move2) end --- 弃置一名角色的牌。 diff --git a/packages/maneuvering/init.lua b/packages/maneuvering/init.lua index cdcf2f20..0283fcdc 100644 --- a/packages/maneuvering/init.lua +++ b/packages/maneuvering/init.lua @@ -146,7 +146,7 @@ local analepticEffect = fk.CreateTriggerSkill{ name = "analeptic_effect", global = true, priority = 0, -- game rule - events = { fk.PreCardUse, fk.EventPhaseStart }, + events = { fk.PreCardUse, fk.AfterTurnEnd }, can_trigger = function(_, event, target, player, data) if target ~= player then return false @@ -155,7 +155,7 @@ local analepticEffect = fk.CreateTriggerSkill{ if event == fk.PreCardUse then return data.card.trueName == "slash" and player.drank > 0 else - return target.phase == Player.NotActive + return true end end, on_trigger = function(_, event, _, player, data) @@ -360,9 +360,16 @@ local fanSkill = fk.CreateTriggerSkill{ return target == player and player:hasSkill(self) and data.card.name == "slash" end, on_use = function(_, _, _, _, data) - local card = Fk:cloneCard("fire__slash") + local card = Fk:cloneCard("fire__slash", data.card.suit, data.card.number) + for k, v in pairs(data.card) do + if card[k] == nil then + card[k] = v + end + end + if not data.card:isVirtual() then + card.id = data.card.id + end card.skillName = "fan" - card:addSubcard(data.card) data.card = card end, } @@ -522,7 +529,7 @@ Fk:loadTranslationTable{ ["#guding_blade_skill"] = "古锭刀", ["fan"] = "朱雀羽扇", - [":fan"] = "装备牌·武器
攻击范围:4
武器技能:你可以将一张普通【杀】当火【杀】使用。", + [":fan"] = "装备牌·武器
攻击范围:4
武器技能:当你声明使用普【杀】后,你可以将此【杀】改为火【杀】。", ["#fan_skill"] = "朱雀羽扇", ["vine"] = "藤甲", diff --git a/packages/standard/game_rule.lua b/packages/standard/game_rule.lua index 3cc23b40..e893d2b4 100644 --- a/packages/standard/game_rule.lua +++ b/packages/standard/game_rule.lua @@ -39,7 +39,7 @@ GameRule = fk.CreateTriggerSkill{ switch(event, { [fk.AskForPeaches] = function() local dyingPlayer = room:getPlayerById(data.who) - while dyingPlayer.hp < 1 do + while not (player.dead or dyingPlayer.dead) and dyingPlayer.hp < 1 do local cardNames = {"peach"} local prompt = "#AskForPeaches:" .. dyingPlayer.id .. "::" .. tostring(1 - dyingPlayer.hp) if player == dyingPlayer then diff --git a/packages/standard_cards/init.lua b/packages/standard_cards/init.lua index abfacd02..8038ae1a 100644 --- a/packages/standard_cards/init.lua +++ b/packages/standard_cards/init.lua @@ -352,18 +352,22 @@ local collateralSkill = fk.CreateActiveSkill{ prompt = "#collateral_skill", mod_target_filter = function(self, to_select, selected, user, card, distance_limited) local player = Fk:currentRoom():getPlayerById(to_select) - return user ~= to_select and player:getEquipment(Card.SubtypeWeapon) + if #selected == 0 then + return user ~= to_select and player:getEquipment(Card.SubtypeWeapon) and not player:prohibitUse(Fk:cloneCard("slash")) + elseif #selected == 1 then + local target = Fk:currentRoom():getPlayerById(to_select) + local from = Fk:currentRoom():getPlayerById(selected[1]) + return from:inMyAttackRange(target) and not from:isProhibited(player, Fk:cloneCard("slash")) + end end, target_filter = function(self, to_select, selected, _, card) if #selected >= (self:getMaxTargetNum(Self, card) - 1) * 2 then return false--修改借刀的目标选择 elseif #selected % 2 == 0 then - return self:modTargetFilter(to_select, selected, Self.id, card) + return self:modTargetFilter(to_select, {}, Self.id, card) else - local player = Fk:currentRoom():getPlayerById(to_select) - local from = Fk:currentRoom():getPlayerById(selected[#selected]) - return self:modTargetFilter(selected[#selected], selected, Self.id, card) - and from:inMyAttackRange(player) and not from:isProhibited(player, Fk:cloneCard("slash")) + return self:modTargetFilter(selected[#selected], {}, Self.id, card) + and self:modTargetFilter(to_select, {selected[#selected]}, Self.id, card) end end, target_num = 2, @@ -382,17 +386,26 @@ local collateralSkill = fk.CreateActiveSkill{ end, on_effect = function(self, room, effect) local to = room:getPlayerById(effect.to) - if to.dead or not to:getEquipment(Card.SubtypeWeapon) then return end + if to.dead then return end local prompt = "#collateral-slash:"..effect.from..":"..effect.subTargets[1] if #effect.subTargets > 1 then prompt = nil end - local use = room:askForUseCard(to, "slash", nil, prompt, nil, { must_targets = effect.subTargets }, effect) + local extra_data = { + must_targets = effect.subTargets, + bypass_times = true, + } + local use = room:askForUseCard(to, "slash", nil, prompt, nil, extra_data, effect) if use then use.extraUse = true room:useCard(use) else - room:moveCardTo(to:getEquipment(Card.SubtypeWeapon), Card.PlayerHand, room:getPlayerById(effect.from), fk.ReasonGive, "collateral", nil, true, to.id) + local from = room:getPlayerById(effect.from) + if from.dead then return end + local weapons = to:getEquipments(Card.SubtypeWeapon) + if #weapons > 0 then + room:moveCardTo(weapons, Card.PlayerHand, from, fk.ReasonGive, "collateral", nil, true, to.id) + end end end }