diff --git a/lua/core/engine.lua b/lua/core/engine.lua index 6a09076a..facaff84 100644 --- a/lua/core/engine.lua +++ b/lua/core/engine.lua @@ -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 --- 加载一系列武将。 diff --git a/lua/core/skill.lua b/lua/core/skill.lua index f2e21ebf..3cc1b9e8 100644 --- a/lua/core/skill.lua +++ b/lua/core/skill.lua @@ -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 @ 主将技/副将技 diff --git a/lua/server/events/hp.lua b/lua/server/events/hp.lua index e62f786a..ee316db2 100644 --- a/lua/server/events/hp.lua +++ b/lua/server/events/hp.lua @@ -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 diff --git a/lua/server/events/movecard.lua b/lua/server/events/movecard.lua index 69e7b48b..7f03cd2d 100644 --- a/lua/server/events/movecard.lua +++ b/lua/server/events/movecard.lua @@ -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 diff --git a/lua/server/mark_enum.lua b/lua/server/mark_enum.lua index f13cb258..0c8f4ad8 100644 --- a/lua/server/mark_enum.lua +++ b/lua/server/mark_enum.lua @@ -52,5 +52,7 @@ MarkEnum.TempMarkSuffix = { "-phase", "-turn", "-round" } ---round:轮次结束后 --- ---inhand:离开手牌区后 +--- +---inarea:离开标记值指定的特定区域后 MarkEnum.CardTempMarkSuffix = { "-phase", "-turn", "-round", - "-inhand" } + "-inhand", "-inarea" } diff --git a/lua/server/room.lua b/lua/server/room.lua index f0f5825d..15ff53bf 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -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) diff --git a/lua/server/system_enum.lua b/lua/server/system_enum.lua index 381c9751..7e764065 100644 --- a/lua/server/system_enum.lua +++ b/lua/server/system_enum.lua @@ -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 ----@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 @ 此牌造成的伤害 +---@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|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|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|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|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 ----@field public reason string +---@field public from ServerPlayer @ 拼点发起者 +---@field public tos ServerPlayer[] @ 拼点目标 +---@field public fromCard Card @ 拼点发起者拼点牌 +---@field public results table @ 结果 +---@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" diff --git a/packages/maneuvering/init.lua b/packages/maneuvering/init.lua index fa84147d..336f0ffa 100644 --- a/packages/maneuvering/init.lua +++ b/packages/maneuvering/init.lua @@ -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) diff --git a/packages/standard/aux_poxi.lua b/packages/standard/aux_poxi.lua index f1918022..a6243069 100644 --- a/packages/standard/aux_poxi.lua +++ b/packages/standard/aux_poxi.lua @@ -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 } diff --git a/packages/standard/init.lua b/packages/standard/init.lua index 3f0327a8..cc20fca1 100644 --- a/packages/standard/init.lua +++ b/packages/standard/init.lua @@ -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