Fix bugs (#311)
1、攻击范围状态技类新增基础值修正函数 2、伤害值在一个技能处理后小于1会终止当前事件 3、不向不能使用【无懈可击】的角色询问使用【无懈可击】 4、修正在濒死插结中有人死亡后仍然会向该角色求桃的情况 5、将PreCardUse和PreCardRespond时机移至实体牌移动之前 6、调整改判函数原判定牌置入弃牌堆的原因 6、修正【朱雀羽扇】、【借刀杀人】、【酒】 Co-authored-by: xxyheaven <1433191064@qq.com>
This commit is contained in:
parent
bdd1a68b1c
commit
3b9dd89b10
|
@ -457,16 +457,28 @@ end
|
||||||
|
|
||||||
--- 获取玩家攻击范围。
|
--- 获取玩家攻击范围。
|
||||||
function Player:getAttackRange()
|
function Player:getAttackRange()
|
||||||
local weapon = Fk:getCardById(self:getEquipment(Card.SubtypeWeapon))
|
local baseValue = 1
|
||||||
local baseAttackRange = math.max(weapon and weapon.attack_range or 1, 0)
|
local weapons = self:getEquipments(Card.SubtypeWeapon)
|
||||||
|
if #weapons > 0 then
|
||||||
local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable
|
baseValue = 0
|
||||||
for _, skill in ipairs(status_skills) do
|
for _, id in ipairs(weapons) do
|
||||||
local correct = skill:getCorrect(self)
|
local weapon = Fk:getCardById(id)
|
||||||
baseAttackRange = baseAttackRange + (correct or 0)
|
baseValue = math.max(baseValue, weapon.attack_range or 1)
|
||||||
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
--- 获取角色是否被移除。
|
--- 获取角色是否被移除。
|
||||||
|
|
|
@ -9,6 +9,12 @@ function AttackRangeSkill:getCorrect(from)
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param from Player
|
||||||
|
---@return integer|nil
|
||||||
|
function AttackRangeSkill:getFixed(from)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
function AttackRangeSkill:withinAttackRange(from, to)
|
function AttackRangeSkill:withinAttackRange(from, to)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ end
|
||||||
|
|
||||||
---@param from Player
|
---@param from Player
|
||||||
---@param to Player
|
---@param to Player
|
||||||
---@return integer
|
---@return integer|nil
|
||||||
function DistanceSkill:getFixed(from, to)
|
function DistanceSkill:getFixed(from, to)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -320,19 +320,23 @@ end
|
||||||
|
|
||||||
---@class AttackRangeSpec: StatusSkillSpec
|
---@class AttackRangeSpec: StatusSkillSpec
|
||||||
---@field public correct_func? fun(self: AttackRangeSkill, from: Player, to: Player): number?
|
---@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?
|
---@field public within_func? fun(self: AttackRangeSkill, from: Player, to: Player): boolean?
|
||||||
|
|
||||||
---@param spec AttackRangeSpec
|
---@param spec AttackRangeSpec
|
||||||
---@return AttackRangeSkill
|
---@return AttackRangeSkill
|
||||||
function fk.CreateAttackRangeSkill(spec)
|
function fk.CreateAttackRangeSkill(spec)
|
||||||
assert(type(spec.name) == "string")
|
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)
|
local skill = AttackRangeSkill:new(spec.name)
|
||||||
readStatusSpecToSkill(skill, spec)
|
readStatusSpecToSkill(skill, spec)
|
||||||
if spec.correct_func then
|
if spec.correct_func then
|
||||||
skill.getCorrect = spec.correct_func
|
skill.getCorrect = spec.correct_func
|
||||||
end
|
end
|
||||||
|
if spec.fixed_func then
|
||||||
|
skill.getFixed = spec.fixed_func
|
||||||
|
end
|
||||||
if spec.within_func then
|
if spec.within_func then
|
||||||
skill.withinAttackRange = spec.within_func
|
skill.withinAttackRange = spec.within_func
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,10 +17,12 @@ GameEvent.functions[GameEvent.Dying] = function(self)
|
||||||
-- room.logic:trigger(fk.Dying, dyingPlayer, dyingStruct)
|
-- room.logic:trigger(fk.Dying, dyingPlayer, dyingStruct)
|
||||||
local savers = room:getAlivePlayers()
|
local savers = room:getAlivePlayers()
|
||||||
for _, p in ipairs(savers) do
|
for _, p in ipairs(savers) do
|
||||||
|
if not p.dead then
|
||||||
if dyingPlayer.hp > 0 or dyingPlayer.dead or logic:trigger(fk.AskForPeaches, p, dyingStruct) then
|
if dyingPlayer.hp > 0 or dyingPlayer.dead or logic:trigger(fk.AskForPeaches, p, dyingStruct) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
logic:trigger(fk.AskForPeachesDone, dyingPlayer, dyingStruct)
|
logic:trigger(fk.AskForPeachesDone, dyingPlayer, dyingStruct)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -170,6 +170,10 @@ GameEvent.functions[GameEvent.UseCard] = function(self)
|
||||||
|
|
||||||
local _card = sendCardEmotionAndLog(room, cardUseEvent)
|
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)
|
room:moveCardTo(cardUseEvent.card, Card.Processing, nil, fk.ReasonUse)
|
||||||
|
|
||||||
local card = cardUseEvent.card
|
local card = cardUseEvent.card
|
||||||
|
@ -196,10 +200,6 @@ GameEvent.functions[GameEvent.UseCard] = function(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if logic:trigger(fk.PreCardUse, room:getPlayerById(cardUseEvent.from), cardUseEvent) then
|
|
||||||
logic:breakEvent()
|
|
||||||
end
|
|
||||||
|
|
||||||
if not cardUseEvent.extraUse then
|
if not cardUseEvent.extraUse then
|
||||||
room:getPlayerById(cardUseEvent.from):addCardUseHistory(cardUseEvent.card.trueName, 1)
|
room:getPlayerById(cardUseEvent.from):addCardUseHistory(cardUseEvent.card.trueName, 1)
|
||||||
end
|
end
|
||||||
|
@ -270,6 +270,10 @@ GameEvent.functions[GameEvent.RespondCard] = function(self)
|
||||||
|
|
||||||
playCardEmotionAndSound(room, room:getPlayerById(from), card)
|
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)
|
room:moveCardTo(card, Card.Processing, nil, fk.ReasonResonpse)
|
||||||
if #cardIds > 0 then
|
if #cardIds > 0 then
|
||||||
room:sendFootnote(cardIds, {
|
room:sendFootnote(cardIds, {
|
||||||
|
@ -281,10 +285,6 @@ GameEvent.functions[GameEvent.RespondCard] = function(self)
|
||||||
end
|
end
|
||||||
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)
|
logic:trigger(fk.CardResponding, room:getPlayerById(cardResponseEvent.from), cardResponseEvent)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -395,7 +395,9 @@ function GameLogic:trigger(event, target, data, refresh_only)
|
||||||
skill_names = table.map(table.filter(skills, filter_func), Util.NameMapper)
|
skill_names = table.map(table.filter(skills, filter_func), Util.NameMapper)
|
||||||
|
|
||||||
broken = broken or (event == fk.AskForPeaches
|
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
|
if broken then break end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2760,7 +2760,9 @@ function Room:handleCardEffect(event, cardEffectEvent)
|
||||||
then
|
then
|
||||||
local players = {}
|
local players = {}
|
||||||
Fk.currentResponsePattern = "nullification"
|
Fk.currentResponsePattern = "nullification"
|
||||||
|
local cardCloned = Fk:cloneCard("nullification")
|
||||||
for _, p in ipairs(self.alive_players) do
|
for _, p in ipairs(self.alive_players) do
|
||||||
|
if not p:prohibitUse(cardCloned) then
|
||||||
local cards = p:getHandlyIds()
|
local cards = p:getHandlyIds()
|
||||||
for _, cid in ipairs(cards) do
|
for _, cid in ipairs(cards) do
|
||||||
if
|
if
|
||||||
|
@ -2792,6 +2794,7 @@ function Room:handleCardEffect(event, cardEffectEvent)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local prompt = ""
|
local prompt = ""
|
||||||
if cardEffectEvent.to then
|
if cardEffectEvent.to then
|
||||||
|
@ -3176,12 +3179,6 @@ function Room:retrial(card, player, judge, skillName, exchange)
|
||||||
local rebyre = judge.retrial_by_response
|
local rebyre = judge.retrial_by_response
|
||||||
judge.retrial_by_response = player
|
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{
|
self:sendLog{
|
||||||
type = "#ChangedJudge",
|
type = "#ChangedJudge",
|
||||||
from = player.id,
|
from = player.id,
|
||||||
|
@ -3190,8 +3187,18 @@ function Room:retrial(card, player, judge, skillName, exchange)
|
||||||
arg = skillName,
|
arg = skillName,
|
||||||
}
|
}
|
||||||
|
|
||||||
self:moveCards(move2)
|
|
||||||
Fk:filterCard(judge.card.id, judge.who, judge)
|
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
|
end
|
||||||
|
|
||||||
--- 弃置一名角色的牌。
|
--- 弃置一名角色的牌。
|
||||||
|
|
|
@ -146,7 +146,7 @@ local analepticEffect = fk.CreateTriggerSkill{
|
||||||
name = "analeptic_effect",
|
name = "analeptic_effect",
|
||||||
global = true,
|
global = true,
|
||||||
priority = 0, -- game rule
|
priority = 0, -- game rule
|
||||||
events = { fk.PreCardUse, fk.EventPhaseStart },
|
events = { fk.PreCardUse, fk.AfterTurnEnd },
|
||||||
can_trigger = function(_, event, target, player, data)
|
can_trigger = function(_, event, target, player, data)
|
||||||
if target ~= player then
|
if target ~= player then
|
||||||
return false
|
return false
|
||||||
|
@ -155,7 +155,7 @@ local analepticEffect = fk.CreateTriggerSkill{
|
||||||
if event == fk.PreCardUse then
|
if event == fk.PreCardUse then
|
||||||
return data.card.trueName == "slash" and player.drank > 0
|
return data.card.trueName == "slash" and player.drank > 0
|
||||||
else
|
else
|
||||||
return target.phase == Player.NotActive
|
return true
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_trigger = function(_, event, _, player, data)
|
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"
|
return target == player and player:hasSkill(self) and data.card.name == "slash"
|
||||||
end,
|
end,
|
||||||
on_use = function(_, _, _, _, data)
|
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.skillName = "fan"
|
||||||
card:addSubcard(data.card)
|
|
||||||
data.card = card
|
data.card = card
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
@ -522,7 +529,7 @@ Fk:loadTranslationTable{
|
||||||
["#guding_blade_skill"] = "古锭刀",
|
["#guding_blade_skill"] = "古锭刀",
|
||||||
|
|
||||||
["fan"] = "朱雀羽扇",
|
["fan"] = "朱雀羽扇",
|
||||||
[":fan"] = "装备牌·武器<br /><b>攻击范围</b>:4<br /><b>武器技能</b>:你可以将一张普通【杀】当火【杀】使用。",
|
[":fan"] = "装备牌·武器<br /><b>攻击范围</b>:4<br /><b>武器技能</b>:当你声明使用普【杀】后,你可以将此【杀】改为火【杀】。",
|
||||||
["#fan_skill"] = "朱雀羽扇",
|
["#fan_skill"] = "朱雀羽扇",
|
||||||
|
|
||||||
["vine"] = "藤甲",
|
["vine"] = "藤甲",
|
||||||
|
|
|
@ -39,7 +39,7 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
switch(event, {
|
switch(event, {
|
||||||
[fk.AskForPeaches] = function()
|
[fk.AskForPeaches] = function()
|
||||||
local dyingPlayer = room:getPlayerById(data.who)
|
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 cardNames = {"peach"}
|
||||||
local prompt = "#AskForPeaches:" .. dyingPlayer.id .. "::" .. tostring(1 - dyingPlayer.hp)
|
local prompt = "#AskForPeaches:" .. dyingPlayer.id .. "::" .. tostring(1 - dyingPlayer.hp)
|
||||||
if player == dyingPlayer then
|
if player == dyingPlayer then
|
||||||
|
|
|
@ -352,18 +352,22 @@ local collateralSkill = fk.CreateActiveSkill{
|
||||||
prompt = "#collateral_skill",
|
prompt = "#collateral_skill",
|
||||||
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
|
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
|
||||||
local player = Fk:currentRoom():getPlayerById(to_select)
|
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,
|
end,
|
||||||
target_filter = function(self, to_select, selected, _, card)
|
target_filter = function(self, to_select, selected, _, card)
|
||||||
if #selected >= (self:getMaxTargetNum(Self, card) - 1) * 2 then
|
if #selected >= (self:getMaxTargetNum(Self, card) - 1) * 2 then
|
||||||
return false--修改借刀的目标选择
|
return false--修改借刀的目标选择
|
||||||
elseif #selected % 2 == 0 then
|
elseif #selected % 2 == 0 then
|
||||||
return self:modTargetFilter(to_select, selected, Self.id, card)
|
return self:modTargetFilter(to_select, {}, Self.id, card)
|
||||||
else
|
else
|
||||||
local player = Fk:currentRoom():getPlayerById(to_select)
|
return self:modTargetFilter(selected[#selected], {}, Self.id, card)
|
||||||
local from = Fk:currentRoom():getPlayerById(selected[#selected])
|
and self:modTargetFilter(to_select, {selected[#selected]}, Self.id, card)
|
||||||
return self:modTargetFilter(selected[#selected], selected, Self.id, card)
|
|
||||||
and from:inMyAttackRange(player) and not from:isProhibited(player, Fk:cloneCard("slash"))
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
target_num = 2,
|
target_num = 2,
|
||||||
|
@ -382,17 +386,26 @@ local collateralSkill = fk.CreateActiveSkill{
|
||||||
end,
|
end,
|
||||||
on_effect = function(self, room, effect)
|
on_effect = function(self, room, effect)
|
||||||
local to = room:getPlayerById(effect.to)
|
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]
|
local prompt = "#collateral-slash:"..effect.from..":"..effect.subTargets[1]
|
||||||
if #effect.subTargets > 1 then
|
if #effect.subTargets > 1 then
|
||||||
prompt = nil
|
prompt = nil
|
||||||
end
|
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
|
if use then
|
||||||
use.extraUse = true
|
use.extraUse = true
|
||||||
room:useCard(use)
|
room:useCard(use)
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue