Dev bugfix (#344)

- 实装了by_user用以检定“使用牌造成伤害”
- 实装Fk.lords以快速查找主公武将
- 添加moveMark以在移动后(前一刻)赋予标记
- 实装-inarea后缀,移动后若不在对应区域会被立即移除
- 为system_enum补全注释
- 内置神将映射
- 修复了小乔转酒杀导致二连击的bug
- 修复了askForCardsChosen烧条后不自动抓取的bug

---------

Co-authored-by: Nyutanislavsky <nyutanislavsky@qq.com>
This commit is contained in:
YoumuKon 2024-04-19 21:35:29 +08:00 committed by GitHub
parent 9d9217da2c
commit a433b1a9ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 197 additions and 133 deletions

View File

@ -332,6 +332,10 @@ function Engine:addGeneral(general)
self.same_generals[tName] = self.same_generals[tName] or { tName }
table.insert(self.same_generals[tName], general.name)
end
if table.find(general.skills, function(s) return s.lordSkill end) then
table.insert(self.lords, general.name)
end
end
--- 加载一系列武将。

View File

@ -11,7 +11,7 @@
---@field public mute boolean @ 决定是否关闭技能配音
---@field public no_indicate boolean @ 决定是否关闭技能指示线
---@field public global boolean @ 决定是否是全局技能
---@field public anim_type string @ 技能类型定义
---@field public anim_type string|AnimationType @ 技能类型定义
---@field public related_skills Skill[] @ 和本技能相关的其他技能,有时候一个技能实际上是通过好几个技能拼接而实现的。
---@field public attached_equip string @ 属于什么装备的技能?
---@field public relate_to_place string @ 主将技/副将技

View File

@ -116,11 +116,12 @@ GameEvent.functions[GameEvent.Damage] = function(self)
local damageStruct = table.unpack(self.data)
local room = self.room
local logic = room.logic
if damageStruct.card and damageStruct.skillName == damageStruct.card.name .. "_skill" and not damageStruct.chain then
if not damageStruct.chain and logic:damageByCardEffect(true) then
local cardEffectData = logic:getCurrentEvent():findParent(GameEvent.CardEffect)
if cardEffectData then
local cardEffectEvent = cardEffectData.data[1]
damageStruct.damage = damageStruct.damage + (cardEffectEvent.additionalDamage or 0)
damageStruct.by_user = true
end
end

View File

@ -10,7 +10,7 @@ GameEvent.functions[GameEvent.MoveCards] = function(self)
assert(info.toArea ~= Card.PlayerSpecial or type(info.specialName) == "string")
assert(type(info.moveReason) == "number")
end
--- @param cardsMoveInfo CardsMoveInfo
for _, cardsMoveInfo in ipairs(args) do
if #cardsMoveInfo.ids > 0 then
infoCheck(cardsMoveInfo)
@ -56,6 +56,7 @@ GameEvent.functions[GameEvent.MoveCards] = function(self)
specialName = cardsMoveInfo.specialName,
specialVisible = cardsMoveInfo.specialVisible,
drawPilePosition = cardsMoveInfo.drawPilePosition,
moveMark = cardsMoveInfo.moveMark,
}
table.insert(cardsMoveStructs, cardsMoveStruct)
@ -71,6 +72,7 @@ GameEvent.functions[GameEvent.MoveCards] = function(self)
specialName = cardsMoveInfo.specialName,
specialVisible = cardsMoveInfo.specialVisible,
drawPilePosition = cardsMoveInfo.drawPilePosition,
moveMark = cardsMoveInfo.moveMark,
}
table.insert(cardsMoveStructs, cardsMoveStruct)
@ -165,13 +167,24 @@ GameEvent.functions[GameEvent.MoveCards] = function(self)
Fk:filterCard(info.cardId, room:getPlayerById(data.to))
local currentCard = Fk:getCardById(info.cardId)
for name, _ in pairs(currentCard.mark) do
for name, value in pairs(currentCard.mark) do
if name:find("-inhand", 1, true) and
realFromArea == Player.Hand and
data.from
then
room:setCardMark(currentCard, name, 0)
end
if name:find("-inarea", 1, true) and
type(value) == "table" and table.contains(value, realFromArea) and not table.contains(value, data.toArea)
then
p(realFromArea)
p(value)
room:setCardMark(currentCard, name, 0)
end
end
if data.moveMark then
local mark = table.clone(data.moveMark) or {"", 0}
room:setCardMark(currentCard, mark[1], mark[2])
end
if
data.toArea == Player.Equip and

View File

@ -52,5 +52,7 @@ MarkEnum.TempMarkSuffix = { "-phase", "-turn", "-round" }
---round轮次结束后
---
---inhand离开手牌区后
---
---inarea离开标记值指定的特定区域后
MarkEnum.CardTempMarkSuffix = { "-phase", "-turn", "-round",
"-inhand" }
"-inhand", "-inarea" }

View File

@ -265,7 +265,11 @@ end
---@param cardId integer | Card @ 要获得区域的那张牌可以是Card或者一个id
---@return CardArea @ 这张牌的区域
function Room:getCardArea(cardId)
local cardIds = table.map(Card:getIdList(cardId), function(cid) return self.card_place[cid] or Card.Unknown end)
local cardIds = {}
for _, cid in ipairs(Card:getIdList(cardId)) do
local place = self.card_place[cid] or Card.Unknown
table.insertIfNeed(cardIds, place)
end
return #cardIds == 1 and cardIds[1] or Card.Unknown
end
@ -3131,7 +3135,7 @@ function Room:drawCards(player, num, skillName, fromPlace)
fromPlace = fromPlace,
}
if self.logic:trigger(fk.BeforeDrawCard, player, drawData) then
self.logic:breakEvent(false)
return {}
end
num = drawData.num
@ -3876,7 +3880,7 @@ end
--- 刷新使命技状态
---@param player ServerPlayer
---@param skillName Suit
---@param skillName string
---@param failed? boolean
function Room:updateQuestSkillState(player, skillName, failed)
assert(Fk.skills[skillName].frequency == Skill.Quest)

View File

@ -2,41 +2,48 @@
---@alias PlayerId integer
--- CardsMoveInfo 一组牌的移动信息
---@class CardsMoveInfo
---@field public ids integer[]
---@field public from? integer
---@field public to? integer
---@field public toArea? CardArea
---@field public moveReason? CardMoveReason
---@field public proposer? integer
---@field public skillName? string
---@field public moveVisible? boolean
---@field public specialName? string
---@field public specialVisible? boolean
---@field public ids integer[] @ 移动卡牌ID数组
---@field public from? integer @ 移动来源玩家ID
---@field public to? integer @ 移动终点玩家ID
---@field public toArea? CardArea @ 移动终点区域
---@field public moveReason? CardMoveReason @ 移动原因
---@field public proposer? integer @ 移动执行者
---@field public skillName? string @ 移动技能名
---@field public moveVisible? boolean @ 控制移动是否可见
---@field public specialName? string @ 若终点区域为PlayerSpecial则存至对应私人牌堆内
---@field public specialVisible? boolean @ 控制上述创建私人牌堆后是否令其可见
---@field public drawPilePosition? integer @ 移至牌堆的索引位置,值为-1代表置入牌堆底或者牌堆牌数+1也为牌堆底
---@field public moveMark? table @ 移动后自动赋予标记,格式:{标记名(支持-inarea后缀移出值代表区域后清除), 值}
--- MoveInfo 一张牌的来源信息
---@class MoveInfo
---@field public cardId integer
---@field public fromArea CardArea
---@field public fromSpecialName? string
--- CardsMoveStruct 一次完整移动
---@class CardsMoveStruct
---@field public moveInfo MoveInfo[]
---@field public from? integer
---@field public to? integer
---@field public toArea CardArea
---@field public moveReason CardMoveReason
---@field public proposer? integer
---@field public skillName? string
---@field public moveVisible? boolean
---@field public specialName? string
---@field public specialVisible? boolean
---@field public moveInfo MoveInfo[] @ 移动信息
---@field public from? integer @ 移动来源玩家ID
---@field public to? integer @ 移动终点玩家ID
---@field public toArea CardArea @ 移动终点区域
---@field public moveReason CardMoveReason @ 移动原因
---@field public proposer? integer @ 移动执行者
---@field public skillName? string @ 移动技能名
---@field public moveVisible? boolean @ 控制移动是否可见
---@field public specialName? string @ 若终点区域为PlayerSpecial则存至对应私人牌堆内
---@field public specialVisible? boolean @ 控制上述创建私人牌堆后是否令其可见
---@field public drawPilePosition? integer @ 移至牌堆的索引位置,值为-1代表置入牌堆底或者牌堆牌数+1也为牌堆底
---@field public moveMark? table @ 移动后自动赋予标记,格式:{标记名(支持-inarea后缀移出值代表区域后清除), 值}
--- PindianResult 拼点结果
---@class PindianResult
---@field public toCard Card
---@field public winner? ServerPlayer
---@field public toCard Card @ 被拼点者所使用的牌
---@field public winner? ServerPlayer @ 赢家,可能不存在
--- 描述和一次体力变化有关的数据
--- HpChangedData 描述和一次体力变化有关的数据
---@class HpChangedData
---@field public num integer @ 体力变化量,可能是正数或者负数
---@field public shield_lost integer|nil
@ -45,15 +52,16 @@
---@field public damageEvent? DamageStruct @ 引起这次体力变化的伤害数据
---@field public preventDying? boolean @ 是否阻止本次体力变更流程引发濒死流程
--- 描述跟失去体力有关的数据
--- HpLostData 描述跟失去体力有关的数据
---@class HpLostData
---@field public num integer @ 失去体力的数值
---@field public skillName string @ 导致这次失去的技能名
--- 描述跟体力上限变化有关的数据
--- MaxHpChangedData 描述跟体力上限变化有关的数据
---@class MaxHpChangedData
---@field public num integer @ 体力上限变化量,可能是正数或者负数
--- DamageType 伤害的属性
---@alias DamageType integer
fk.NormalDamage = 1
@ -61,7 +69,7 @@ fk.ThunderDamage = 2
fk.FireDamage = 3
fk.IceDamage = 4
--- DamageStruct 用来描述和伤害事件有关的数据。
--- DamageStruct 描述和伤害事件有关的数据。
---@class DamageStruct
---@field public from? ServerPlayer @ 伤害来源
---@field public to ServerPlayer @ 伤害目标
@ -73,7 +81,7 @@ fk.IceDamage = 4
---@field public beginnerOfTheDamage? boolean @ 是否是本次铁索传导的起点
---@field public by_user? boolean @ 是否由卡牌直接生效造成的伤害
--- 用来描述和回复体力有关的数据。
--- RecoverStruct 描述和回复体力有关的数据。
---@class RecoverStruct
---@field public who ServerPlayer @ 回复体力的角色
---@field public num integer @ 回复值
@ -81,14 +89,16 @@ fk.IceDamage = 4
---@field public skillName? string @ 因何种技能而回复
---@field public card? Card @ 造成此次回复的卡牌
--- DyingStruct 描述和濒死事件有关的数据
---@class DyingStruct
---@field public who integer
---@field public damage DamageStruct
---@field public ignoreDeath? boolean
---@field public who integer @ 濒死角色
---@field public damage DamageStruct @ 造成此次濒死的伤害数据
---@field public ignoreDeath? boolean @ 是否不进行死亡结算
--- DeathStruct 描述和死亡事件有关的数据
---@class DeathStruct
---@field public who integer
---@field public damage DamageStruct
---@field public who integer @ 死亡角色
---@field public damage DamageStruct @ 造成此次死亡的伤害数据
--- askForUseCard中的extra_data
---@class UseExtraData
@ -99,103 +109,118 @@ fk.IceDamage = 4
---@field public bypass_times? boolean @ 无次数限制?
---@field public playing? boolean @ (AI专用) 出牌阶段?
--- CardUseStruct 使用卡牌的数据
---@class CardUseStruct
---@field public from integer
---@field public tos TargetGroup
---@field public card Card
---@field public toCard? Card
---@field public responseToEvent? CardUseStruct
---@field public nullifiedTargets? integer[]
---@field public extraUse? boolean
---@field public disresponsiveList? integer[]
---@field public unoffsetableList? integer[]
---@field public additionalDamage? integer
---@field public additionalRecover? integer
---@field public customFrom? integer
---@field public cardsResponded? Card[]
---@field public prohibitedCardNames? string[]
---@field public damageDealt? table<PlayerId, number>
---@field public additionalEffect? integer
---@field public noIndicate? boolean
---@field public from integer @ 使用者
---@field public tos TargetGroup @ 角色目标组
---@field public card Card @ 卡牌本牌
---@field public toCard? Card @ 卡牌目标
---@field public responseToEvent? CardUseStruct @ 响应事件目标
---@field public nullifiedTargets? integer[] @ 对这些角色无效
---@field public extraUse? boolean @ 是否不计入次数
---@field public disresponsiveList? integer[] @ 这些角色不可响应此牌
---@field public unoffsetableList? integer[] @ 这些角色不可抵消此牌
---@field public additionalDamage? integer @ 额外伤害值(如酒之于杀)
---@field public additionalRecover? integer @ 额外回复值
---@field public extra_data? any @ 额外数据(如目标过滤等)
---@field public customFrom? integer @ 新使用者
---@field public cardsResponded? Card[] @ 响应此牌的牌
---@field public prohibitedCardNames? string[] @ 这些牌名的牌不可响应此牌
---@field public damageDealt? table<PlayerId, number> @ 此牌造成的伤害
---@field public additionalEffect? integer @ 额外结算次数
---@field public noIndicate? boolean @ 隐藏指示线
--- AimStruct 处理使用牌目标的数据
---@class AimStruct
---@field public from integer
---@field public card Card
---@field public tos AimGroup
---@field public to integer
---@field public subTargets? integer[]
---@field public targetGroup? TargetGroup
---@field public nullifiedTargets? integer[]
---@field public firstTarget boolean
---@field public additionalDamage? integer
---@field public additionalRecover? integer
---@field public disresponsive? boolean
---@field public unoffsetableList? boolean
---@field public additionalResponseTimes? table<string, integer>|integer
---@field public fixedAddTimesResponsors? integer[]
---@field public additionalEffect? integer
---@field public from integer @ 使用者
---@field public card Card @ 卡牌本牌
---@field public tos AimGroup @ 总角色目标
---@field public to integer @ 当前角色目标
---@field public subTargets? integer[] @ 子目标(借刀!)
---@field public targetGroup? TargetGroup @ 目标组
---@field public nullifiedTargets? integer[] @ 对这些角色无效
---@field public firstTarget boolean @ 是否是第一个目标
---@field public additionalDamage? integer @ 额外伤害值(如酒之于杀)
---@field public additionalRecover? integer @ 额外回复值
---@field public disresponsive? boolean @ 是否不可响应
---@field public unoffsetable? boolean @ 是否不可抵消
---@field public fixedResponseTimes? table<string, integer>|integer @ 额外响应请求
---@field public fixedAddTimesResponsors? integer[] @ 额外响应请求次数
---@field public additionalEffect? integer @额外结算次数
--- CardUseStruct 卡牌效果的数据
---@class CardEffectEvent
---@field public from? integer
---@field public to integer
---@field public subTargets? integer[]
---@field public tos TargetGroup
---@field public card Card
---@field public toCard? Card
---@field public responseToEvent? CardEffectEvent
---@field public nullifiedTargets? integer[]
---@field public extraUse? boolean
---@field public disresponsiveList? integer[]
---@field public unoffsetableList? integer[]
---@field public additionalDamage? integer
---@field public additionalRecover? integer
---@field public customFrom? integer
---@field public cardsResponded? Card[]
---@field public disresponsive? boolean
---@field public unoffsetable? boolean
---@field public isCancellOut? boolean
---@field public fixedResponseTimes? table<string, integer>|integer
---@field public fixedAddTimesResponsors? integer[]
---@field public prohibitedCardNames? string[]
---@field public from? integer @ 使用者
---@field public to integer @ 角色目标
---@field public subTargets? integer[] @ 子目标(借刀!)
---@field public tos TargetGroup @ 目标组
---@field public card Card @ 卡牌本牌
---@field public toCard? Card @ 卡牌目标
---@field public responseToEvent? CardEffectEvent @ 响应事件目标
---@field public nullifiedTargets? integer[] @ 对这些角色无效
---@field public extraUse? boolean @ 是否不计入次数
---@field public disresponsiveList? integer[] @ 这些角色不可响应此牌
---@field public unoffsetableList? integer[] @ 这些角色不可抵消此牌
---@field public additionalDamage? integer @ 额外伤害值(如酒之于杀)
---@field public additionalRecover? integer @ 额外回复值
---@field public extra_data? any @ 额外数据(如目标过滤等)
---@field public customFrom? integer @ 新使用者
---@field public cardsResponded? Card[] @ 响应此牌的牌
---@field public disresponsive? boolean @ 是否不可响应
---@field public unoffsetable? boolean @ 是否不可抵消
---@field public isCancellOut? boolean @ 是否被抵消
---@field public fixedResponseTimes? table<string, integer>|integer @ 额外响应请求
---@field public fixedAddTimesResponsors? integer[] @ 额外响应请求次数
---@field public prohibitedCardNames? string[] @ 这些牌名的牌不可响应此牌
--- SkillEffectEvent 技能效果的数据
---@class SkillEffectEvent
---@field public from integer
---@field public tos integer[]
---@field public cards integer[]
---@field public from integer @ 使用者
---@field public tos integer[] @ 角色目标
---@field public cards integer[] @ 选择卡牌
--- JudgeStruct 判定的数据
---@class JudgeStruct
---@field public who ServerPlayer
---@field public card Card
---@field public reason string
---@field public pattern string
---@field public skipDrop? boolean
---@field public who ServerPlayer @ 判定者
---@field public card Card @ 当前判定牌
---@field public reason string @ 判定原因
---@field public pattern string @ 钩叉条件
---@field public skipDrop? boolean @ 是否不进入弃牌堆
--- CardResponseEvent 卡牌响应的数据
---@class CardResponseEvent
---@field public from integer
---@field public card Card
---@field public responseToEvent? CardEffectEvent
---@field public skipDrop? boolean
---@field public customFrom? integer
---@field public from integer @ 响应者
---@field public card Card @ 卡牌本牌
---@field public responseToEvent? CardEffectEvent @ 响应事件目标
---@field public skipDrop? boolean @ 是否不进入弃牌堆
---@field public customFrom? integer @ 新响应者
--- AskForCardUse 询问使用卡牌的数据
---@class AskForCardUse
---@field public user ServerPlayer
---@field public cardName string
---@field public pattern string
---@field public result CardUseStruct
---@field public user ServerPlayer @ 使用者
---@field public cardName string @ 烧条信息
---@field public pattern string @ 可用牌过滤
---@field public eventData CardEffectEvent @ 事件数据
---@field public extraData UseExtraData @ 额外数据
---@field public result? CardUseStruct @ 使用结果
--- AskForCardResponse 询问响应卡牌的数据
---@class AskForCardResponse
---@field public user ServerPlayer
---@field public cardName string
---@field public pattern string
---@field public result Card
---@field public user ServerPlayer @ 响应者
---@field public cardName string @ 烧条信息
---@field public pattern string @ 可用牌过滤
---@field public extraData UseExtraData @ 额外数据
---@field public result? Card
--- PindianStruct 拼点的数据
---@class PindianStruct
---@field public from ServerPlayer
---@field public tos ServerPlayer[]
---@field public fromCard Card
---@field public results table<integer, PindianResult>
---@field public reason string
---@field public from ServerPlayer @ 拼点发起者
---@field public tos ServerPlayer[] @ 拼点目标
---@field public fromCard Card @ 拼点发起者拼点牌
---@field public results table<integer, PindianResult> @ 结果
---@field public reason string @ 拼点原因
--- LogMessage 战报信息
---@class LogMessage
---@field public type string @ log主体
---@field public from? integer @ 要替换%from的玩家的id
@ -206,16 +231,19 @@ fk.IceDamage = 4
---@field public arg3? any @ 要替换%arg3的内容
---@field public toast? boolean @ 是否顺手把消息发送一条相同的toast
--- SkillUseStruct 使用技能的数据
---@class SkillUseStruct
---@field public skill Skill
---@field public willUse boolean
--- DrawCardStruct 摸牌的数据
---@class DrawCardStruct
---@field public who ServerPlayer
---@field public num number
---@field public skillName string
---@field public fromPlace "top"|"bottom"
---@field public who ServerPlayer @ 摸牌者
---@field public num number @ 摸牌数
---@field public skillName string @ 技能名
---@field public fromPlace "top"|"bottom" @ 摸牌的位置
--- 移动理由
---@alias CardMoveReason integer
fk.ReasonJustMove = 1
fk.ReasonDraw = 2
@ -229,3 +257,6 @@ fk.ReasonUse = 9
fk.ReasonResonpse = 10
fk.ReasonJudge = 11
fk.ReasonRecast = 12
--- 内置动画类型理论上你可以自定义一个自己的动画类型big会播放一段限定技动画
---@alias AnimationType "special" | "drawcard" | "control" | "offensive" | "support" | "defensive" | "negative" | "masochism" | "switch" | "big"

View File

@ -335,14 +335,8 @@ local gudingSkill = fk.CreateTriggerSkill{
can_trigger = function(self, _, target, player, data)
local logic = player.room.logic
if target == player and player:hasSkill(self) and
data.to:isKongcheng() and data.card and data.card.trueName == "slash" and not data.chain then
local event = logic:getCurrentEvent()
if event == nil then return false end
event = event.parent
if event == nil or event.event ~= GameEvent.SkillEffect then return false end
event = event.parent
if event == nil or event.event ~= GameEvent.CardEffect then return false end
return data.card == event.data[1].card and data.from.id == event.data[1].from
data.to:isKongcheng() and data.card and data.card.trueName == "slash" then
return data.by_user
end
end,
on_use = function(_, _, _, _, data)

View File

@ -19,4 +19,17 @@ Fk:addPoxiMethod{
return ret .. ":" ..extra_data.to
end
end,
default_choice = function(data, extra_data)
local ret = {}
for _, pile in ipairs(data) do
local cards = pile[2]
local lim = extra_data.min - #ret
if #cards > lim then
table.insertTable(ret, table.random(cards, lim))
break
end
table.insertTable(ret, cards)
end
return ret
end
}

View File

@ -6,6 +6,8 @@ dofile "packages/standard/game_rule.lua"
dofile "packages/standard/aux_skills.lua"
dofile "packages/standard/aux_poxi.lua"
Fk:appendKingdomMap("god", {"wei", "shu", "wu", "qun"})
local jianxiong = fk.CreateTriggerSkill{
name = "jianxiong",
anim_type = "masochism",
@ -202,7 +204,7 @@ local luoyi_trigger = fk.CreateTriggerSkill{
events = {fk.DamageCaused},
can_trigger = function(self, event, target, player, data)
return target == player and player:usedSkillTimes("luoyi", Player.HistoryTurn) > 0 and
not data.chain and data.card and (data.card.trueName == "slash" or data.card.name == "duel")
data.card and (data.card.trueName == "slash" or data.card.name == "duel") and data.by_user
end,
on_cost = Util.TrueFunc,
on_use = function(self, event, target, player, data)
@ -1131,7 +1133,7 @@ local role_getlogic = function()
end
lord_num = math.min(a1 - a2, lord_num)
local generals = table.connect(room:findGenerals(function(g)
return table.find(Fk.generals[g].skills, function(s) return s.lordSkill end)
return table.contains(Fk.lords, g)
end, lord_num), room:getNGenerals(generalNum))
lord_generals = room:askForGeneral(lord, generals, n)
local lord_general, deputy