找回密码
 点一下
查看: 5708|回复: 26

随机物品系统

[复制链接]
发表于 2009-10-19 16:41:11 | 显示全部楼层 |阅读模式
系统功能:
  • 自定义每个的随机等级
  • 对每个物品设置在相同随机等级中的概率
  • 多等级随机物品系统可以在多个任意定义的等级内随机物品
  • 多等级随机时,可以设置每个等级出现的概率
  • 注册物品时不需要按等级排序,只要将所有的物品类型、等级、在等级内出现的概率放到对应的三个数组系统即可
  • 可禁用物品版的支持禁用某个物品类型出现在随机中
系统说明:
     使用方法,先(所有数据注册完成后的任意时间)执行RandomItemSystemInitialize,然后通过函数GetRandomItemType获得随机到的物品类型。
     多等级物品的等级使用二进制方法记录,通过参数Key的二进制值的每位的值(0、1)来决定是否使用某个等级。你可以使用MakeLevelKey来添加等级、或者直接自己计算出结果添加到参数里。详细内容参考演示使用。
     如果不需要在多个等级中随机,只会在全部物品或某一等级的物品中随机,请使用单等级版本。运算效率会更高。
     多等级版本暂时最多支持定义30个等级(没有保护,请使用者自行注意)因为一个整数的数据量有限,如果需要更多等级,请自行修改代码
     关于参数的设置请参考演示或函数中的注释,特殊说明一下注释中最后的(自定数据)(结果数据)(间接数据)这三个类别。自定数据就是自己设置值的数据,间接数据是根据自定数据得到的值,比如数组使用的大小,结果数据是放置计算结果的数据,请勿修改。
     两个系统最终的返回值都是物品类型(integer)
    禁用物品版增加了禁用某个物品出现在随机中的功能,禁用物品请用AddBanItem添加物品类型(integer),去除禁用物品请使用RemoveBanItem,参数也是物品类型。删除错误的类型无效。具体使用方法请看演示

单等级版代码:
[jass]globals
integer array udg_ItemTypeArray//物品类型记录数组(不必按等级排列)(自定数据)
integer array udg_ItemAppearRate//对应每个物品类型物品在其等级所有物品中的出现概率(自动计算)(自定数据)  
integer array udg_ItemLevel//对应每个物品类型的等级
integer array udg_ItemLevelRate//所有等级中每个等级出现的概率(自动计算)(自定数据)
integer array udg_ItemRateNumInLevel//每个等级的物品的概率总和(对应等级排列)(结果数据)                     
integer array udg_ItemIndexInLevel//每个等级的物品在udg_ItemTypeArray中的第一个的序号位置(对应等级排列,为0~udg_ItemLevelNum -1)(结果数据)
integer udg_ItemTypeNum//物品类型总数(间接数据)
integer udg_ItemLevelNum//物品等级总数,物品等级从0级开始,依次递增到udg_ItemLevelNum - 1级,共udg_ItemLevelNum个等级 (间接数据)
integer udg_ItemLevelRateNum//物品等级总概率(结果数据)
endglobals
function RandomItemSystemInitialize takes nothing returns nothing//随机物品系统初始化
    local integer array TempItemTypeArray
    local integer array TempItemAppearRate
    local integer array TempItemLevel
    local integer array TempItemNum
    local integer TempInteger
    local integer i = 0
    set udg_ItemLevelRateNum = 0
    set udg_ItemIndexInLevel[0] = 0
    loop//对于等级概率求和以及部分数据初始值设置
        set udg_ItemLevelRateNum = udg_ItemLevelRateNum + udg_ItemLevelRate
        set udg_ItemRateNumInLevel = 0
        set udg_ItemIndexInLevel = 0
        set TempItemNum = 0
        set i = i + 1
        exitwhen i >= udg_ItemLevelNum
    endloop
    set i = 0
    loop//记录临时数据以及等级内概率求和
        set TempItemTypeArray = udg_ItemTypeArray
        set TempItemAppearRate = udg_ItemAppearRate
        set TempItemLevel = udg_ItemLevel
        set udg_ItemIndexInLevel[udg_ItemLevel + 1] = udg_ItemIndexInLevel[udg_ItemLevel + 1] + 1
        set udg_ItemRateNumInLevel[udg_ItemLevel] = udg_ItemRateNumInLevel[udg_ItemLevel] + udg_ItemAppearRate
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum
    endloop
    set i = 1
    loop//对于等级概率分配以及每个等级初始位置分配
        set udg_ItemLevelRate = udg_ItemLevelRate  + udg_ItemLevelRate[i - 1]   
        set udg_ItemIndexInLevel = udg_ItemIndexInLevel + udg_ItemIndexInLevel[i - 1]
        set i = i + 1
        exitwhen i >= udg_ItemLevelNum
    endloop
    set i= 0
    loop//对于物品类型数据排序
        set TempInteger = udg_ItemIndexInLevel[TempItemLevel] + TempItemNum[TempItemLevel]
        set udg_ItemTypeArray[TempInteger] = TempItemTypeArray
        set udg_ItemAppearRate[TempInteger] = TempItemAppearRate
        set udg_ItemLevel[TempInteger] = TempItemLevel
        set TempItemNum[TempItemLevel] = TempItemNum[TempItemLevel] + 1
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum
    endloop      
    set i = 1
    set TempInteger = 1
    loop//分配每个等级内的概率
        if i != udg_ItemIndexInLevel [TempInteger] then
            set udg_ItemAppearRate = udg_ItemAppearRate + udg_ItemAppearRate[i - 1]
        else
            set TempInteger = TempInteger + 1
        endif
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum  
    endloop                  
endfunction
function GetRandomItemType takes integer Level returns integer//获得一个给定等级的随机物品当物品等级为-1时为在所有是物品中随机获得
    local integer RandomRate
    local integer i = 0
    if Level == -1 then
        set RandomRate = GetRandomInt(1,udg_ItemLevelRateNum)
        loop
            if udg_ItemLevelRate >= RandomRate then
                set Level = i
                exitwhen true
            endif  
            set i = i + 1
        endloop
    endif
    set RandomRate = GetRandomInt(1,udg_ItemRateNumInLevel[Level])
    set i = 0
    loop
        if udg_ItemAppearRate[udg_ItemIndexInLevel[Level] + i] >= RandomRate then
            return udg_ItemTypeArray[udg_ItemIndexInLevel[Level] + i]
        endif
        set i = i + 1
    endloop
    return udg_ItemTypeArray[0]
endfunction [/jass]
多等级版代码:
[jass]globals
integer array udg_ItemTypeArray//物品类型记录数组(不必按等级排列)(自定数据)
integer array udg_ItemAppearRate//对应每个物品类型物品在其等级所有物品中的出现概率(自动计算)(自定数据)  
integer array udg_ItemLevel//对应每个物品类型的等级
integer array udg_ItemLevelRate//所有等级中每个等级出现的概率(自动计算)(自定数据)  
integer array udg_ItemRateNumInLevel//每个等级的物品的概率总和(对应等级排列)(结果数据)                     
integer array udg_ItemIndexInLevel//每个等级的物品在udg_ItemTypeArray中的第一个的序号位置(对应等级排列,为0~udg_ItemLevelNum -1)(结果数据)
integer udg_ItemTypeNum//物品类型总数(间接数据)
integer udg_ItemLevelNum//物品等级总数,物品等级从0级开始,依次递增到udg_ItemLevelNum - 1级,共udg_ItemLevelNum个等级 (间接数据)
endglobals
function RandomItemSystemInitialize takes nothing returns nothing//随机物品系统初始化
    local integer array TempItemTypeArray
    local integer array TempItemAppearRate
    local integer array TempItemLevel
    local integer array TempItemNum
    local integer TempInteger
    local integer i = 0
    set udg_ItemIndexInLevel[0] = 0
    loop//对于部分数据初始值设置
        set udg_ItemRateNumInLevel = 0
        set udg_ItemIndexInLevel = 0
        set TempItemNum = 0
        set i = i + 1
        exitwhen i >= udg_ItemLevelNum
    endloop
    set i = 0
    loop//记录临时数据以及等级内概率求和
        set TempItemTypeArray = udg_ItemTypeArray
        set TempItemAppearRate = udg_ItemAppearRate
        set TempItemLevel = udg_ItemLevel
        set udg_ItemIndexInLevel[udg_ItemLevel + 1] = udg_ItemIndexInLevel[udg_ItemLevel + 1] + 1
        set udg_ItemRateNumInLevel[udg_ItemLevel] = udg_ItemRateNumInLevel[udg_ItemLevel] + udg_ItemAppearRate
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum
    endloop
    set i = 1
    loop//对于每个等级初始位置分配
        set udg_ItemIndexInLevel = udg_ItemIndexInLevel + udg_ItemIndexInLevel[i - 1]
        set i = i + 1
        exitwhen i >= udg_ItemLevelNum
    endloop
    set i= 0
    loop//对于物品类型数据排序
        set TempInteger = udg_ItemIndexInLevel[TempItemLevel] + TempItemNum[TempItemLevel]
        set udg_ItemTypeArray[TempInteger] = TempItemTypeArray
        set udg_ItemAppearRate[TempInteger] = TempItemAppearRate
        set udg_ItemLevel[TempInteger] = TempItemLevel
        set TempItemNum[TempItemLevel] = TempItemNum[TempItemLevel] + 1
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum
    endloop      
    set i = 1
    set TempInteger = 1
    loop//分配每个等级内的概率
        if i != udg_ItemIndexInLevel [TempInteger] then
            set udg_ItemAppearRate = udg_ItemAppearRate + udg_ItemAppearRate[i - 1]
        else
            set TempInteger = TempInteger + 1
        endif
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum  
    endloop                  
endfunction
function MakeLevelKey takes integer Level,integer Key returns integer//将Level加入到Key中,注意不要重复添加,最大等级30
    local integer i = 0
    local integer TempKey = 1
    loop   
        exitwhen i == Level            
        set TempKey = TempKey * 2
        set i = i + 1
    endloop
    return Key + TempKey
endfunction
function GetRandomItemType takes integer Key returns integer//获得一个给定Key的随机物品
    local integer RandomRate
    local integer i = -1
    local integer j = 0
    local integer Level = 0
    local integer TempAllLevelRate = 0
    local integer array TempLevelRate
    local integer array TempLevel   
    loop//获取记录有效的Level
        if Key != Key / 2 * 2 then   
            set i = i + 1
            set TempLevelRate = udg_ItemLevelRate[j]
            set TempAllLevelRate = TempAllLevelRate + udg_ItemLevelRate[j]
            set TempLevel = j
        endif
        set Key = Key / 2  
        exitwhen Key == 0  
        set j = j + 1
    endloop
    set j = 1
    loop//分配概率               
        exitwhen j > i
        set TempLevelRate[j] = TempLevelRate[j] + TempLevelRate[j - 1]
        set j = j + 1
    endloop
    set RandomRate = GetRandomInt(1,TempAllLevelRate)
    set j = 0
    loop
        if TempLevelRate[j] >= RandomRate then
            set Level = TempLevel[j]   
            exitwhen true
        endif
        set j = j + 1        
    endloop
    set j = 0     
    set RandomRate = GetRandomInt(1,udg_ItemRateNumInLevel[Level])
    loop
        if udg_ItemAppearRate[udg_ItemIndexInLevel[Level] + j] >= RandomRate then
            return udg_ItemTypeArray[udg_ItemIndexInLevel[Level] + j]
        endif
        set j = j + 1
    endloop
    return udg_ItemTypeArray[0]
endfunction
[/jass]

多等级禁用物品版
[jass]globals
integer array udg_ItemTypeArray//物品类型记录数组(不必按等级排列)(自定数据)
integer array udg_ItemAppearRate//对应每个物品类型物品在其等级所有物品中的出现概率(自动计算)(自定数据)  
integer array udg_ItemLevel//对应每个物品类型的等级
integer array udg_ItemLevelRate//所有等级中每个等级出现的概率(自动计算)(自定数据)                    
integer array udg_ItemIndexInLevel//每个等级的物品在udg_ItemTypeArray中的第一个的序号位置(对应等级排列,为0~udg_ItemLevelNum -1)(结果数据)
integer array udg_BanItemType//禁止的物品的类型数组,在调用函数GetRandomItemType后自动清空。如果需禁用某个物品,那么请放入此数组中(结果数据)
integer udg_ItemTypeNum//物品类型总数(间接数据)
integer udg_ItemLevelNum//物品等级总数,物品等级从0级开始,依次递增到udg_ItemLevelNum - 1级,共udg_ItemLevelNum个等级 (间接数据)
endglobals
function RandomItemSystemInitialize takes nothing returns nothing//随机物品系统初始化
    local integer array TempItemTypeArray
    local integer array TempItemAppearRate
    local integer array TempItemLevel
    local integer array TempItemNum
    local integer TempInteger
    local integer i = 0
    set udg_ItemIndexInLevel[0] = 0
    loop//对于部分数据初始值设置
        set udg_ItemIndexInLevel = 0
        set TempItemNum = 0
        set i = i + 1
        exitwhen i >= udg_ItemLevelNum
    endloop
    set i = 0
    loop//记录临时数据以及等级内概率求和
        set TempItemTypeArray = udg_ItemTypeArray
        set TempItemAppearRate = udg_ItemAppearRate
        set TempItemLevel = udg_ItemLevel
        set udg_ItemIndexInLevel[udg_ItemLevel + 1] = udg_ItemIndexInLevel[udg_ItemLevel + 1] + 1
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum
    endloop
    set i = 1
    loop//对于每个等级初始位置分配
        set udg_ItemIndexInLevel = udg_ItemIndexInLevel + udg_ItemIndexInLevel[i - 1]
        set i = i + 1
        exitwhen i >= udg_ItemLevelNum
    endloop
    set i= 0
    loop//对于物品类型数据排序
        set TempInteger = udg_ItemIndexInLevel[TempItemLevel] + TempItemNum[TempItemLevel]
        set udg_ItemTypeArray[TempInteger] = TempItemTypeArray
        set udg_ItemAppearRate[TempInteger] = TempItemAppearRate
        set udg_ItemLevel[TempInteger] = TempItemLevel
        set TempItemNum[TempItemLevel] = TempItemNum[TempItemLevel] + 1
        set i = i + 1
        exitwhen i >= udg_ItemTypeNum
    endloop         
endfunction
function MakeLevelKey takes integer Level,integer Key returns integer//将Level加入到Key中,注意不要重复添加,最大等级30
    local integer i = 0
    local integer TempKey = 1
    loop   
        exitwhen i == Level            
        set TempKey = TempKey * 2
        set i = i + 1
    endloop
    return Key + TempKey
endfunction
function IsBanItem takes integer ItemType returns boolean//返回物品类型ItemType是否可出现
    local integer i = 0
    loop
        if ItemType == udg_BanItemType then
            return false
        endif
        set i = i + 1
        exitwhen udg_BanItemType == 0
    endloop
    return true
endfunction
function AddBanItem takes integer ItemType returns nothing//增加一个禁用物品
    local integer i = 0
    loop
        exitwhen udg_BanItemType == 0
        set i = i + 1
    endloop  
    set udg_BanItemType = ItemType
endfunction
function RemoveBanItem takes integer ItemType returns nothing//将物品在禁用表中去除
    local integer i = 0
    local integer BanItemIndex = -1
    loop
        exitwhen udg_BanItemType == 0
        if udg_BanItemType == ItemType then
            set BanItemIndex = i
        endif
        set i = i + 1
    endloop  
    if  BanItemIndex == -1 then
        return
    endif
    set udg_BanItemType[BanItemIndex] = udg_BanItemType[i - 1]
    set udg_BanItemType[i - 1] = 0
endfunction
function GetRandomItemType takes integer Key returns integer//获得一个给定Key的随机物品
    local integer RandomRate
    local integer i = -1
    local integer j = 0
    local integer Level = 0
    local integer TempRate = 0
    local integer array TempRateArray
    local integer array TempLevel  
    local integer array TempItemType
    loop//获取记录有效的Level
        if Key != Key / 2 * 2 then   
            set i = i + 1
            set TempRateArray = udg_ItemLevelRate[j]
            set TempRate = TempRate + udg_ItemLevelRate[j]
            set TempLevel = j
        endif
        set Key = Key / 2  
        exitwhen Key == 0  
        set j = j + 1
    endloop
    set j = 1
    loop//分配等级概率               
        exitwhen j > i
        set TempRateArray[j] = TempRateArray[j] + TempRateArray[j - 1]
        set j = j + 1
    endloop
    set RandomRate = GetRandomInt(1,TempRate)
    set j = 0
    loop//获得随机等级
        if TempRateArray[j] >= RandomRate then
            set Level = TempLevel[j]   
            exitwhen true
        endif
        set j = j + 1        
    endloop
    set TempRate = 0
    set i = -1
    set j = udg_ItemIndexInLevel[Level]
    loop//记录有效的物品类型
        if IsBanItem(udg_ItemTypeArray[j]) then      
            set i = i + 1
            set TempRateArray = udg_ItemAppearRate[j]
            set TempItemType = udg_ItemTypeArray[j]  
            set TempRate = TempRate + udg_ItemAppearRate[j]
        endif
        set j = j + 1
        exitwhen j == udg_ItemIndexInLevel[Level + 1]
    endloop
    set j = 1
    loop//分配物品概率               
        exitwhen j > i
        set TempRateArray[j] = TempRateArray[j] + TempRateArray[j - 1]
        set j = j + 1
    endloop
    set j = 0     
    set RandomRate = GetRandomInt(1,TempRate)
    loop
        if TempRateArray[j] >= RandomRate then
            return TempItemType[j]
        endif
        set j = j + 1
    endloop
    return udg_ItemTypeArray[0]
endfunction
[/jass]

随机物品.rar

54 KB, 下载次数: 733

演示、代码在这里

随机物品多等级可禁用版.rar

29 KB, 下载次数: 378

可禁用版的代码和演示

评分

参与人数 1威望 +4 收起 理由
血戮魔动冰 + 4

查看全部评分

 楼主| 发表于 2009-10-19 16:42:49 | 显示全部楼层
因多物品随机部分未完成,故先不复制到教程区
回复

使用道具 举报

发表于 2009-10-19 16:48:33 | 显示全部楼层
hashtable~~

en~~不错~~
回复

使用道具 举报

 楼主| 发表于 2009-10-19 17:04:55 | 显示全部楼层
这个是纯数组的……
没有也不需要存储系统……
回复

使用道具 举报

发表于 2009-10-19 17:14:59 | 显示全部楼层
多个物品随机可以考虑用hashtable,我是这么认为的...

可能我的表达能力比较容易被人误解...
回复

使用道具 举报

 楼主| 发表于 2009-10-19 17:24:10 | 显示全部楼层
没办法……
考虑到兼容性……
而且现在的问题是怎么输入任意长个参数
jass不支持数组参数……
回复

使用道具 举报

 楼主| 发表于 2009-10-19 17:53:57 | 显示全部楼层
好吧悲剧了
演示的名称写反了
已经改正
回复

使用道具 举报

发表于 2009-10-19 18:35:56 | 显示全部楼层
提问:我那个需求,你有啥做的办法没?
回复

使用道具 举报

 楼主| 发表于 2009-10-19 18:37:57 | 显示全部楼层
引用第7楼eff于2009-10-19 18:35发表的  :
提问:我那个需求,你有啥做的办法没?
将添加禁用物品的功能……
也就是可以禁止某个物品出现
然后你那个附加等级我没看明白
回复

使用道具 举报

发表于 2009-10-19 18:50:59 | 显示全部楼层
就是说,可以指定一个随机列表,然后传进去一个值

一个怪能掉什么装备,是由这个随机列表+怪物携带的值决定的

一般来说,这个值越大,掉的东西越好
回复

使用道具 举报

 楼主| 发表于 2009-10-19 19:21:10 | 显示全部楼层
这个系统就能实现啊
你绑定到怪物的值是个整数
也就是说物品的等级
然后把这个怪物可能掉了的物品注册到数组中去
其中注册的物品等级为怪物绑定的等级
随机表是全部随机物品的
也就是注册好的数组
然后怪物死亡时
得到掉落物品等级
在该等级下随机物品
得到物品类型
然后你再创建物品就行了

马上完成可以禁用表中某个物品的系统了
这样就可以实现禁止某物品在随机中出现了

唯一的问题是暂时函数支持的最大等级是30
也就是只用30个物品等级(没办法,一个整数能够记录的上限了)
不过可以更改
很简单就可以扩展了
回复

使用道具 举报

发表于 2009-10-20 18:25:01 | 显示全部楼层
这个。。不是你这么说的。。

意思是:
列表
- 药水 Q:0
- 宝物 Q:10
- 垃圾 Q: -10

如果怪物的参考值是0,那么掉出来药水和宝物的几率是一样的

如果怪物额度参考值是100,那么宝物掉出来的几率会大一点,而垃圾掉出来的几率会小一点,药水不受影响
回复

使用道具 举报

发表于 2009-10-31 00:32:45 | 显示全部楼层
弱弱的问. T无法给物品添加技能,  而J可以给物品添加技能是吗
回复

使用道具 举报

 楼主| 发表于 2009-10-31 09:02:53 | 显示全部楼层
都不能……
不过有替换技能的方法
回复

使用道具 举报

发表于 2009-10-31 09:17:50 | 显示全部楼层

回 14楼(疯人¢衰人) 的帖子

我out了。。那么具体如何实现
回复

使用道具 举报

 楼主| 发表于 2009-10-31 09:41:35 | 显示全部楼层
回复

使用道具 举报

发表于 2009-10-31 09:59:32 | 显示全部楼层
但是这样循环变形的话…………貌似效率会比较低?
回复

使用道具 举报

 楼主| 发表于 2009-10-31 10:51:01 | 显示全部楼层
这个确实……
回复

使用道具 举报

发表于 2009-10-31 10:55:27 | 显示全部楼层
所以我觉得给物品绑定技能id。
单位获得物品添加技能。
单位丢弃/卖出/转移物品的时候删除技能。
而且还可以方便的动态修改物品的技能~
回复

使用道具 举报

发表于 2009-10-31 10:57:00 | 显示全部楼层
所以物品还是一个空架子比较好。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-11-21 23:25 , Processed in 0.105712 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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