From fa5b9def7bd3a1cf9f8f74d51cc9038a4f87fb72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E5=A6=96=E6=A2=A6=E5=8E=A8?= <12796194+youmuKon-supreme@user.noreply.gitee.com> Date: Thu, 26 Jun 2025 06:18:24 +0800 Subject: [PATCH 1/2] =?UTF-8?q?derived=5Fpiles=E5=92=8C=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E5=AE=A1=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lua/core/skill_skeleton.lua | 86 +++++++++++++++++++++++++++- lua/core/skill_type/usable_skill.lua | 4 +- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/lua/core/skill_skeleton.lua b/lua/core/skill_skeleton.lua index af5f32a..fefab8d 100644 --- a/lua/core/skill_skeleton.lua +++ b/lua/core/skill_skeleton.lua @@ -7,7 +7,7 @@ ---@field public anim_type? string|AnimationType @ 技能类型定义 ---@field public global? boolean @ 决定是否是全局技能 ---@field public dynamic_desc? fun(self: Skill, player: Player, lang: string): string? @ 动态描述函数 ----@field public derived_piles? string|string[] @ 与某效果联系起来的私人牌堆名,失去该效果时将之置入弃牌堆 --- FIXME: 这应该是Skel的属性吧? +---@field public derived_piles? string|string[] @deprecated @ 与某效果联系起来的私人牌堆名,失去该效果时将之置入弃牌堆 --- FIXME: 这应该是Skel的属性吧? ---@field public audio_index? table|integer @ 此技能效果播放的语音序号,可为int或int表 ---@field public extra? table @ 塞进技能里的各种数据 @@ -19,6 +19,11 @@ ---@field public attached_skill_name? string @ 向其他角色分发的技能名(如黄天) ---@field public dynamic_name? fun(self: SkillSkeleton, player: Player, lang?: string): string @ 动态名称函数 ---@field public dynamic_desc? fun(self: SkillSkeleton, player: Player, lang?: string): string? @ 动态描述函数 +---@field public derived_piles? string|string[] @ 与该技能联系起来的私人牌堆名,失去该效果时将之置入弃牌堆 +---@field public max_phase_use_time? integer|fun(self: SkillSkeleton, player: Player): integer? @ 该技能的最大使用次数——阶段 +---@field public max_turn_use_time? integer|fun(self: SkillSkeleton, player: Player): integer? @ 该技能的最大使用次数——回合 +---@field public max_round_use_time? integer|fun(self: SkillSkeleton, player: Player): integer? @ 该技能的最大使用次数——轮次 +---@field public max_game_use_time? integer|fun(self: SkillSkeleton, player: Player): integer? @ 该技能的最大使用次数——本局游戏 ---@field public extra? table @ 塞进技能里的各种数据 ---@class SkillSkeleton : Object, SkillSkeletonSpec @@ -42,6 +47,8 @@ ---@field public onLose fun(self: SkillSkeleton, player: ServerPlayer, is_death: boolean) ---@field public dynamicName fun(self: SkillSkeleton, player: Player, lang?: string): string @ 动态名称函数 ---@field public dynamicDesc fun(self: SkillSkeleton, player: Player, lang?: string): string @ 动态描述函数 +---@field public max_use_time (integer?)[] @ 一个效果的最大可用次数 +---@field public derived_piles? string | string[] @ 与一个技能同在的私有牌堆名,失去时弃置其中的所有牌 ---@field public addTest fun(self: SkillSkeleton, fn: fun(room: Room, me: ServerPlayer)) @ 测试函数 local SkillSkeleton = class("SkillSkeleton") @@ -76,6 +83,13 @@ function SkillSkeleton:initialize(spec) self.dynamicDesc = spec.dynamic_desc self.extra = spec.extra or {} + self.max_use_time = { + spec.max_phase_use_time, + spec.max_turn_use_time, + spec.max_round_use_time, + spec.max_game_use_time, + } + --Notify智慧,当不存在main_skill时,用于创建main_skill。看上去毫无用处 fk.readCommonSpecToSkill(self, spec) end @@ -574,6 +588,14 @@ function SkillSkeleton:onLose(player, is_death) end end local lost_piles = {} + if self.derived_piles then + if type(self.derived_piles) == "string" then + self.derived_piles = {self.derived_piles} + end + for _, pile_name in ipairs(self.derived_piles) do + table.insertTableIfNeed(lost_piles, player:getPile(pile_name)) + end + end for _, effect in ipairs(self.effects) do if effect.derived_piles then if type(effect.derived_piles) == "string" then @@ -637,6 +659,68 @@ function SkillSkeleton:getDynamicDescription(player, lang) return self.dynamicDesc and self:dynamicDesc(player, lang) end +-- 获得技能的最大使用次数 +---@param player Player @ 使用者 +---@param scope integer @ 查询历史范围(默认为回合) +---@param to? Player @ 目标 +---@return number? @ 最大使用次数,nil就是无限 +function SkillSkeleton:getMaxUseTime(player, scope, to) + scope = scope or Player.HistoryTurn + local time = self.max_use_time[scope] + local ret = time + if type(time) == "function" then + ret = time(self, player) + end + if ret == nil then return nil end + local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable + for _, skill in ipairs(status_skills) do + local fix = skill:getFixedNum(player, self, scope, nil, to) + if fix ~= nil then -- 典中典之先到先得 + ret = fix + break + end + local correct = skill:getResidueNum(player, self, scope, nil, to) + if correct == nil then correct = 0 end + ret = ret + correct + end + return ret +end + +-- 获得技能的剩余使用次数 +---@param player Player @ 使用者 +---@param scope integer @ 查询历史范围(默认为回合) +---@param to? Player @ 目标 +---@return number? @ 剩余使用次数,nil就是无限 +function SkillSkeleton:getRemainUseTime(player, scope, to) + if to and to.dead then return nil end -- 一般情况不会对死人使用技能的…… + scope = scope or Player.HistoryTurn + + local limit = self:getMaxUseTime(player, scope, to) + if limit == nil then return nil end + + return math.max(0, limit - player:usedSkillTimes(self.name, scope)) +end + +-- 判断一个角色是否在技能的次数限制内 +---@param player Player @ 使用者 +---@param scope integer @ 查询历史范围(默认为回合) +---@param to? Player @ 目标 +---@return boolean? +function SkillSkeleton:withinTimesLimit(player, scope, to) + if to and to.dead then return false end -- 一般情况不会对死人使用技能的…… + scope = scope or Player.HistoryTurn + + local limit = self:getMaxUseTime(player, scope, to) + if limit == nil then return true end + + local status_skills = Fk:currentRoom().status_skills[TargetModSkill] or Util.DummyTable + for _, skill in ipairs(status_skills) do + if skill:bypassTimesCheck(player, self, scope, nil, to) then return true end + end + + return self:getRemainUseTime(player, scope, to) > 0 +end + ---@param spec SkillSkeletonSpec ---@return SkillSkeleton function fk.CreateSkill(spec) diff --git a/lua/core/skill_type/usable_skill.lua b/lua/core/skill_type/usable_skill.lua index c897cc4..b79eff1 100644 --- a/lua/core/skill_type/usable_skill.lua +++ b/lua/core/skill_type/usable_skill.lua @@ -7,9 +7,9 @@ --]] ---@class UsableSkill : Skill ----@field public max_use_time integer[] +---@field public max_use_time (integer?)[] @ 一个效果的最大可用次数 ---@field public expand_pile? string | integer[] | fun(self: UsableSkill, player: Player): integer[]|string? @ 额外牌堆,牌堆名称或卡牌id表 ----@field public derived_piles? string | string[] +---@field public derived_piles? string | string[] @ 与一个技能同在的私有牌堆名,失去时弃置其中的所有牌 ---@field public times? fun(self: UsableSkill, player: Player): integer local UsableSkill = Skill:subclass("UsableSkill") -- Gitee From 6b36ba233f4bb68ec5f0778f951c8c552598ebf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E5=A6=96=E6=A2=A6=E5=8E=A8?= <12796194+youmuKon-supreme@user.noreply.gitee.com> Date: Thu, 26 Jun 2025 06:37:28 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=B8=BB=E5=8A=A8=E6=8A=80=E7=9A=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=AC=A1=E6=95=B0=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lua/core/skill_type/active.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lua/core/skill_type/active.lua b/lua/core/skill_type/active.lua index 66a5836..8a98ed9 100644 --- a/lua/core/skill_type/active.lua +++ b/lua/core/skill_type/active.lua @@ -31,7 +31,14 @@ end ---@param extra_data? UseExtraData @ 额外数据 ---@return boolean? function ActiveSkill:canUse(player, card, extra_data) - return self:isEffectable(player) and self:withinTimesLimit(player, Player.HistoryPhase, card) + if not self:isEffectable(player) then return false end + if self:getMaxUseTime(player, Player.HistoryPhase, card) ~= nil then + return self:withinTimesLimit(player, Player.HistoryPhase, card) + end + local skel = self:getSkeleton() + if skel then + return skel:withinTimesLimit(player, Player.HistoryPhase) + end end -- 判断一张牌是否可被此技能选中 -- Gitee