查看: 31|回复: 7

[Lua] 五行怪物随机词缀模块化

[复制链接]

38

主题

24

回帖

1199

积分

金牌会员

积分
1199
发表于 4 天前 | 显示全部楼层 |阅读模式
本帖最后由 牛头 于 2026-7-16 19:51 编辑

AffixConfig.lua 全局词缀配置
AffixConfig = {}

-- ========== 全局总开关 ==========
AffixConfig.Switch = {
    OpenMonsterRandomAffix = true, -- 是否开启怪物出生随机词缀
}

-- ========== 五行词缀组ID(和AffixGroup.xls GroupID对应) ==========
AffixConfig.GroupId = {
    Metal  = 1, -- 金系怪物词缀组
    Wood   = 2, -- 木系怪物词缀组
    Water  = 3, -- 水系怪物词缀组
    Fire   = 4, -- 火系怪物词缀组
    Earth  = 5  -- 土系怪物词缀组
}

-- ========== 五行独立词缀池 {词缀ID, 权重} 权重越高越容易刷出 ==========
-- 金系:物攻、暴击、金币加成类词缀
AffixConfig.AffixPool_Metal = {
    {AffixId = 1001, Weight = 80}, -- 锋利
    {AffixId = 1002, Weight = 60}, -- 狂击
    {AffixId = 1003, Weight = 40}, -- 破甲
    {AffixId = 1004, Weight = 20}, -- 碎魂(稀有)
}
-- 木系:回血、持续毒、生命上限词缀
AffixConfig.AffixPool_Wood = {
    {AffixId = 2001, Weight = 80}, -- 生机
    {AffixId = 2002, Weight = 60}, -- 毒雾
    {AffixId = 2003, Weight = 40}, -- 厚皮
    {AffixId = 2004, Weight = 20}, -- 万木归宗(稀有)
}
-- 水系:减速、冰冻、魔法减伤词缀
AffixConfig.AffixPool_Water = {
    {AffixId = 3001, Weight = 80}, -- 冰甲
    {AffixId = 3002, Weight = 60}, -- 迟缓
    {AffixId = 3003, Weight = 40}, -- 魔力屏障
    {AffixId = 3004, Weight = 20}, -- 冰封大地(稀有)
}
-- 火系:灼烧、暴击伤害、爆率加成词缀
AffixConfig.AffixPool_Fire = {
    {AffixId = 4001, Weight = 80}, -- 灼烧
    {AffixId = 4002, Weight = 60}, -- 烈焰
    {AffixId = 4003, Weight = 40}, -- 熔甲
    {AffixId = 4004, Weight = 20}, -- 焚天(稀有)
}
-- 土系:防御、反伤、血量加成词缀
AffixConfig.AffixPool_Earth = {
    {AffixId = 5001, Weight = 80}, -- 石肤
    {AffixId = 5002, Weight = 60}, -- 反震
    {AffixId = 5003, Weight = 40}, -- 巨体
    {AffixId = 5004, Weight = 20}, -- 不动如山(稀有)
}

-- ========== 怪物绑定配置:怪物ID、所属五行分组、0~5条词缀生成权重 ==========
-- 格式 {MonsterId=怪物ID, GroupType=五行分组标识, Weight={无词缀,1条,2条,3条,4条,5条}}
AffixConfig.MonsterBindList = {
    -- 金系怪物示例
    {MonsterId=1001, GroupType="Metal", Weight={50,30,15,4,1,0}},
    {MonsterId=1002, GroupType="Metal", Weight={30,35,20,10,4,1}},
    -- 木系怪物示例
    {MonsterId=2001, GroupType="Wood", Weight={40,32,18,7,2,1}},
    -- 水系怪物示例
    {MonsterId=3001, GroupType="Water", Weight={45,30,16,6,2,1}},
    -- 火系BOSS(高概率多词缀)
    {MonsterId=4001, GroupType="Fire", Weight={0,10,25,30,25,10}},
    -- 土系小怪
    {MonsterId=5001, GroupType="Earth", Weight={60,28,10,2,0,0}},
}

-- 根据分组标识获取对应词缀池
function AffixConfig:GetPoolByGroup(groupType)
    local poolMap = {
        Metal = self.AffixPool_Metal,
        Wood  = self.AffixPool_Wood,
        Water = self.AffixPool_Water,
        Fire  = self.AffixPool_Fire,
        Earth = self.AffixPool_Earth
    }
    return poolMap[groupType] or nil
end

return AffixConfig
MonsterAffixCore.lua 词缀工具核心库
local Config = require("AffixConfig")
MonsterAffixCore = {}

-- 1. 根据权重数组随机生成词缀数量(返回0~5)
-- weightArr = {Affix0Weight, Affix1Weight, Affix2Weight, Affix3Weight, Affix4Weight, Affix5Weight}
function MonsterAffixCore.RandomAffixCount(weightArr)
    local totalWeight = 0
    for _, w in ipairs(weightArr) do
        totalWeight = totalWeight + w
    end
    if totalWeight <= 0 then return 0 end

    local randVal = math.random(1, totalWeight)
    local curSum = 0
    for count = 0, 5 do
        curSum = curSum + weightArr[count+1]
        if randVal <= curSum then
            return count
        end
    end
    return 0
end

-- 2. 从指定词缀池随机抽取N个不重复词缀ID
-- pool:五行词缀池数组 | needCount:需要抽取几条
function MonsterAffixCore.RandomUniqueAffix(pool, needCount)
    local result = {}
    local tempPool = {}
    -- 复制临时池,防止修改原配置
    for _, item in ipairs(pool) do
        table.insert(tempPool, {AffixId = item.AffixId, Weight = item.Weight})
    end

    if needCount <= 0 or #tempPool == 0 then
        return result
    end

    for i = 1, needCount do
        -- 剩余池总权重
        local totalW = 0
        for _, p in ipairs(tempPool) do
            totalW = totalW + p.Weight
        end
        if totalW <= 0 then break end

        local rand = math.random(1, totalW)
        local sum = 0
        local pickIdx = -1
        for idx, p in ipairs(tempPool) do
            sum = sum + p.Weight
            if rand <= sum then
                pickIdx = idx
                break
            end
        end

        if pickIdx ~= -1 then
            -- 存入结果并从临时池移除(保证不重复)
            table.insert(result, tempPool[pickIdx].AffixId)
            table.remove(tempPool, pickIdx)
        end
    end
    return result
end

-- 3. 给怪物批量挂载词缀(自动先清空原有词缀)
function MonsterAffixCore.BatchAddMonsterAffix(monsterObj, affixIdList)
    ClearAffix(monsterObj) -- 清空旧词缀,避免叠加
    for _, aid in ipairs(affixIdList) do
        AddAffix(monsterObj, aid)
    end
end

-- 4. 工具:检测怪物是否拥有指定词缀
function MonsterAffixCore.HasAffix(monsterObj, affixId)
    return CheckAffix(monsterObj, affixId)
end

-- 5. 工具:移除怪物单个指定词缀
function MonsterAffixCore.RemoveSingleAffix(monsterObj, affixId)
    DelAffix(monsterObj, affixId)
end

return MonsterAffixCore
MonsterAffixSpawn.lua 怪物出生词缀生成业务逻辑
local Config = require("AffixConfig")
local Core = require("MonsterAffixCore")
MonsterAffixSpawn = {}

-- 怪物创建出生事件入口(引擎 OnMonsterCreate 回调)
function MonsterAffixSpawn.OnMonsterBorn(monster)
    -- 全局开关关闭直接退出
    if not Config.Switch.OpenMonsterRandomAffix then
        return
    end

    local monsterId = monster:GetMonsterID()
    local monsterBind = nil

    -- 匹配当前怪物对应的五行配置
    for _, bindCfg in ipairs(Config.MonsterBindList) do
        if bindCfg.MonsterId == monsterId then
            monsterBind = bindCfg
            break
        end
    end
    -- 未配置的怪物不生成词缀
    if not monsterBind then
        return
    end

    -- 1. 随机本次要生成几条词缀(0~5)
    local needNum = Core.RandomAffixCount(monsterBind.Weight)
    if needNum <= 0 then
        ClearAffix(monster) -- 无词缀直接清空
        return
    end

    -- 2. 获取对应五行词缀池
    local affixPool = Config:GetPoolByGroup(monsterBind.GroupType)
    if not affixPool or #affixPool == 0 then
        return
    end

    -- 3. 随机N个不重复词缀
    local affixIdList = Core.RandomUniqueAffix(affixPool, needNum)
    -- 4. 批量挂载到怪物身上
    Core.BatchAddMonsterAffix(monster, affixIdList)
end

return MonsterAffixSpawn
Main.lua 引擎主加载与事件注册入口
-- 加载模块化依赖
AffixConfig = require("AffixConfig")
MonsterAffixCore = require("MonsterAffixCore")
MonsterAffixSpawn = require("MonsterAffixSpawn")

-- VV引擎注册【怪物创建出生事件】
RegisterMonsterCreateEvent(MonsterAffixSpawn.OnMonsterBorn)

print("【五行怪物随机词缀模块化脚本】加载完成!")

11

主题

66

回帖

7354

积分

论坛元老

积分
7354
发表于 3 天前 | 显示全部楼层
看上去不错的样子

2

主题

16

回帖

468

积分

中级会员

积分
468
发表于 前天 18:46 | 显示全部楼层
学习一下

21

主题

97

回帖

1305

积分

金牌会员

积分
1305
发表于 前天 21:52 | 显示全部楼层
不封挂封挂和任何

38

主题

24

回帖

1199

积分

金牌会员

积分
1199
楼主 发表于 前天 22:56 | 显示全部楼层
goodsnowv 发表于 2026-7-17 18:50
看上去不错的样子

可以试试哦··

0

主题

6

回帖

97

积分

注册会员

积分
97
发表于 昨天 22:41 | 显示全部楼层
引擎还不能下载,怎么测试?

38

主题

24

回帖

1199

积分

金牌会员

积分
1199
楼主 发表于 昨天 22:53 | 显示全部楼层
hi8 发表于 2026-7-19 22:41
引擎还不能下载,怎么测试?

所以加油啊····500贡献了申请内测

0

主题

6

回帖

97

积分

注册会员

积分
97
发表于 半小时前 | 显示全部楼层
牛头 发表于 2026-7-19 22:53
所以加油啊····500贡献了申请内测

早得很,刷帖子又怕封号!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表