请选择 进入手机版 | 继续访问电脑版

GA地精研究院

 找回密码
 立即注册
查看: 25066|回复: 82

[演示&系统] 一个简单强大的ORPGSL系统

[复制链接]
发表于 2011-6-9 22:47:08 | 显示全部楼层 |阅读模式
本帖最后由 希瓦 于 2018-6-20 11:59 编辑

系统原理

利用Preload系列函数在本地储存与读取数据

系统作用

在本地储存与读取数据,使地图可以接着上次玩

系统代码

[jass]
function SyncInteger takes gamecache gc, string missionKey, string key, integer value returns nothing
        local integer oldValue = GetStoredInteger(gc, missionKey, key)
        call StoreInteger(gc, missionKey, key, value)
        call SyncStoredInteger(gc, missionKey, key)
        call StoreInteger(gc, missionKey, key, oldValue)
endfunction

function LoadFile takes string file, gamecache gc returns nothing
        local string userId = I2S(GetPlayerId(GetLocalPlayer()) + 1)
        local integer count
        local integer index
        // Load data from file
        call SetPlayerTechMaxAllowed(Player(12),0,2147483647)
        call Preloader(file)
        set count = GetPlayerTechMaxAllowed(Player(12),0)
    if(count > 3000)then
        set count = 0
    endif
        // Sync data in the cache
        call SyncInteger(gc, userId, "0", -1)
        set index = 1
        loop
                exitwhen (index > count)
                if (GetPlayerTechMaxAllowed(Player(12), index) == 0) then
            call SyncInteger(gc, userId, I2S(index), GetPlayerTechMaxAllowed(Player(13), index))
        else
            call SyncInteger(gc, userId, I2S(index), -GetPlayerTechMaxAllowed(Player(13), index) - 1)
        endif
                set index = index + 1
        endloop
        // Use 0 as count
        call SyncInteger(gc, userId, "0", count)
endfunction

function SaveFile takes string file, gamecache gc returns nothing
    local string userId = I2S(GetPlayerId(GetLocalPlayer()) + 1)
    local integer count = GetStoredInteger(gc, userId, "0")
    local integer index
    local integer value
    // Use preload bug to save data
    call PreloadGenClear()
    call PreloadGenStart()
    call Preload("\")
    call SetPlayerTechMaxAllowed(Player(12), 0, " + I2S(count) + ") //")
    set index = 1
    loop
        exitwhen(index > count)
        set value = GetStoredInteger(gc, userId, I2S(index))
        if(value >= 0)then
            call Preload("\")
            call SetPlayerTechMaxAllowed(Player(12), " + I2S(index) + ", 0)
            call SetPlayerTechMaxAllowed(Player(13), " + I2S(index) + ", " + I2S(value) + ") //")
        else
            call Preload("\")
            call SetPlayerTechMaxAllowed(Player(12), " + I2S(index) + ", 1)
            call SetPlayerTechMaxAllowed(Player(13), " + I2S(index) + ", " + I2S(-(value + 1)) + ") //")
        endif
        set index = index + 1
    endloop
    call Preload("\")
    return //")
    call PreloadGenEnd(file)
endfunction

//LoadFile函数用于读档,可以将文件file里面储存的数据读取到游戏缓存gc里面
//SaveFile函数用于存档,可以把游戏缓存gc里面储存的数据储存到文件file里面
//数据储存在缓存中,类别名即为玩家序号,使用名为数据序号,0号数据用来储存数据数量
[/jass]
  
使用环境

1)支持多玩家
2)支持魔兽所有版本
3)不需要使用ORPG登陆器
4)读档必须开启Allow Local Files注册表项

使用方法

1)使用前,先将代码拷贝到地图的自定义代码区
Code.png

2)然后,将触发复制到地图中,并根据需求进行修改
Init.png
Load.png
Save.png

3)演示地图在此下载
ORPG演示.w3x (16.14 KB, 下载次数: 430)

评分

参与人数 1威望 +7 收起 理由
麦德三世 + 7 非常之好

查看全部评分

发表于 2011-6-9 23:51:13 | 显示全部楼层
希瓦好敬业啊,来顶下
回复 支持 反对

使用道具 举报

发表于 2011-6-11 00:24:57 | 显示全部楼层
貌似有个战役叫做什么“精灵游侠”什么的,
打过一遍之后,即使删除了通关记录文件W3j什么的,
再重新开始也仍然是十级,
也还保存了物品属性什么的,
不知道这什么的跟那什么的有没有啥关系?
回复 支持 反对

使用道具 举报

发表于 2011-6-11 10:39:57 | 显示全部楼层
可惜无法本地加密……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-11 11:01:51 | 显示全部楼层
正在改进优化,我准备把它做成UI~~
加密倒不是难事,只是加密算法是个问题~
回复 支持 反对

使用道具 举报

发表于 2011-6-11 11:44:45 | 显示全部楼层
问题在于你的加密脚本本身就在j中,拆开就全部知道了……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-11 12:29:22 | 显示全部楼层
所以只需要用简单的字符替换来加密就可以了吧……
毕竟再好的加密也挡不住会JASS的人……
回复 支持 反对

使用道具 举报

发表于 2011-6-11 14:26:42 | 显示全部楼层
不过需要一个效验算法,省的瞎填都会有效
回复 支持 反对

使用道具 举报

发表于 2011-6-12 00:38:24 | 显示全部楼层
哈哈哈....
回复 支持 反对

使用道具 举报

发表于 2011-6-12 08:55:09 | 显示全部楼层
强大.支持希瓦.
回复 支持 反对

使用道具 举报

发表于 2011-6-12 17:10:57 | 显示全部楼层
ORPGSL系统.w3x (15 K) 下载次数:0

AllowLocalFiles.rar (1 K) 下载次数:0

一幅ORPG地图.w3x (19 K) 下载次数:4

。。看来大家比较关心那张地图~~
回复 支持 反对

使用道具 举报

发表于 2011-6-13 19:14:55 | 显示全部楼层
非常之好~~希瓦加油啊~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-13 19:36:06 | 显示全部楼层
嗯嗯~真开心~
谢谢头目大人~~
我会继续努力完善它的~~
回复 支持 反对

使用道具 举报

发表于 2011-6-14 15:45:54 | 显示全部楼层
希瓦缺德啊……居然用那样的方法骗我下载……不过倒也不能全怪希瓦,都是绝影提出来的……
回复 支持 反对

使用道具 举报

发表于 2011-6-14 16:26:27 | 显示全部楼层
什么方法骗你下载?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-14 16:36:12 | 显示全部楼层
有人说想玩我做的地图~
我就在群里面放出过下载的链接~
结果就是这样了~~
回复 支持 1 反对 0

使用道具 举报

发表于 2011-6-15 16:26:41 | 显示全部楼层
这个贴是为我准备的么?小弟的暗黑图IMPK风云再起正想往这个方向优化S/L系统
真是踏破草鞋无处寻得来全不费工夫  - -!!



问一下老大,此系统能否实现完美支持1.24?可支持多人游戏?
相当的期待
回复 支持 反对

使用道具 举报

发表于 2011-6-15 17:20:24 | 显示全部楼层
这个...离用于实际地图中还有蛮远的差距吧,楼上可能要失望了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-15 18:14:41 | 显示全部楼层
这个系统虽然很简单,但是其实她已经能够独当一面了呢;
她支持魔兽的所有版本的,支持多玩家;
并且经过多次测试,并没有出现掉线问题。

只是需要注意几点:
1)如果数据太多了的话,最好分成几个文件来储存
2)要使用这个系统,必须开启Allow Local Files的注册表项

如果你想先试试其它的SL系统的话
可以试试U9枫霜前辈制作的ORPG系统
也可以试试楼上的actboy168前辈制作的YDWE的SL系统。

而如果你决定了使用这个SL系统
那么我可是一个认真负责的技术顾问哦~~欢迎随时反馈各种意见以及建议~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-15 18:51:14 | 显示全部楼层
引用第17楼leisel于2011-06-15 16:26发表的  :
这个贴是为我准备的么?小弟的暗黑图IMPK风云再起正想往这个方向优化S/L系统
真是踏破草鞋无处寻得来全不费工夫  - -!!



.......
你的地图使用的是记录码储存系统吧?
如果你感兴趣的话,等我上晚自习回来后,写一个可以直接储存/读取记录码的演示出来~
你可以移植试试~
回复 支持 反对

使用道具 举报

发表于 2011-6-17 09:32:04 | 显示全部楼层
特别注意一点,这一点最近很多人问到。

由于使用预读漏洞来读取文本,存在一个需要用注册表来允许war3读取本地文件的的关键。

所以你文件夹下存在什么UI Unit War3map.j的话必定会导致你无法和人联机。因为war3在运行的时候会读取它们,导致你的单位数据和别人的不一样。


先确保联机双方war3安装目录下没有多余的会覆盖MPQ资源和数据的文件,这样才能保证正常运作。
回复 支持 反对

使用道具 举报

发表于 2011-6-17 09:35:46 | 显示全部楼层
很多人觉得奇怪,为啥我04年发的那个DDWE不用UI和Unit文件夹,却一定要包在一个Loader里面,做成一个单独的exe?

因为当时就已经有了Allow Local Files的这个问题,所以才尽力避免在war3的安装文件夹下放额外东西。
回复 支持 反对

使用道具 举报

发表于 2011-6-19 08:16:30 | 显示全部楼层
一般玩家很少会遇到此类问题。除非他们安装的硬盘版war3异常奇葩。

这种问题多是地图作者们会遇到的,由于不了解原理而以为那注册表文件把他们的war3给搞坏了。因为不少地图作者喜欢用那些强化UI文件。

老狼那个确实也会,所以测试时把他那些文件夹移走,等到要用了再移回来就是了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-17 00:10:04 | 显示全部楼层
s.w3x (11 KB, 下载次数: 93)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-24 19:23:34 | 显示全部楼层

表示没有使用ReturnBug
且经我测试,可以在1.26使用
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-26 20:58:30 | 显示全部楼层
伤害显示和储存系统没有关系吧……一般来说是不会有冲突的……
当然,你不要让伤害系统和储存系统共用一个GC……不然还是可能出错的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-6-26 20:59:31 | 显示全部楼层
对了,你的地图加入了我的那个系统之后出现了什么问题没有,可不可以正常使用呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-12-30 22:28:43 | 显示全部楼层
支持口牙~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-12-30 22:34:50 | 显示全部楼层
那很好呢~~

需要说明一下,这个中文字版移植比较麻烦。
所以还是等我再写一下移植说明吧,倒是你可以先试用一下~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-1-1 17:23:11 | 显示全部楼层
最近我也在不断的修改这个系统呢……
不过因为快要考试了,没有太多时间来做这个工作
所以一直都没有把修改版放上来,也没有写出详细的移植说明
因此,很多同学使用了本系统时由于用法不当,出现了一系列的问题
对此我深表歉意,我会在10号之后尽快做出完美版的
在此之前可以先使用这个版本

SL系统500上限版.w3x

12 KB, 下载次数: 11

回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-1-18 20:59:57 | 显示全部楼层
好吧,最新的无上限版……
读取少量数据时(1000以内)基本上没有问题
单人游戏时也基本没有问题

只是多开测试读取5000数据时,玩家“触发停顿”了很多秒钟。
这种“触发停顿”不是卡,但又很像卡,具体表现在:
游戏能完全正常的运行,所有你的单位都会受你的控制,且并没有延迟。
但是触发在发生了事件的情况下却不会运行动作,而是加入队列。
比如:
正常情况下,我输入load后直接就会有Loading...显示出来
但是实际上什么都不会显示……
直到差不多一分钟后,所有触发会一瞬间全部同时运行
以前输入了多少个load就会同时显示多少个Loading...

比较无语……

问题出在魔兽本身的同步速度太慢
以至于要很久很久才能同步完5000个数据……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-2-3 13:56:32 | 显示全部楼层
[jass]
function LoadFile takes string fn,gamecache gc returns nothing
    local string mk
    local string ky
    local string tc
    local integer px
    local integer di
    local integer ix
    local integer sl
    local integer tl
    local integer od
    local string array pn
    local string array ld
    set px = 0
    loop
        exitwhen(px>=16)
        set pn[px] = GetPlayerName(Player(px))
        call SetPlayerName(Player(px)," ")
        set px = px + 1
    endloop
    call Preloader(fn)
    set px = 0
    loop
        exitwhen(px>=16)
        set ld[px] = GetPlayerName(Player(px))
        call SetPlayerName(Player(px),pn[px])
        set px = px + 1        
    endloop
    set mk = I2S(GetPlayerId(GetLocalPlayer())+1)
    set ky = I2S(0)
    set od = GetStoredInteger(gc,mk,ky)
    call StoreInteger(gc,mk,ky,-1)
    call SyncStoredInteger(gc,mk,ky)
    call StoreInteger(gc,mk,ky,od)
    set di = 0
    set px = 0
    loop
        exitwhen(px>=16)
        set tc = ld[px]
        exitwhen(tc==" ")
        set sl = StringLength(tc)
        set ix = 0
        loop
            exitwhen(ix>=sl)
            set tl = ix
            loop
                exitwhen(ix>=sl)
                exitwhen(SubString(tc,ix,ix+1)==",")
                set ix = ix + 1
            endloop
            set di = di + 1
            set ky = I2S(di)
            set tl = S2I(SubString(tc,tl,ix))
            set od = GetStoredInteger(gc,mk,ky)
            call StoreInteger(gc,mk,ky,tl)
            call SyncStoredInteger(gc,mk,ky)
            call StoreInteger(gc,mk,ky,od)
            set ix = ix + 1   
        endloop
        set px = px + 1
    endloop   
    set ky = I2S(0)
    set od = GetStoredInteger(gc,mk,ky)
    call StoreInteger(gc,mk,ky,di)
    call SyncStoredInteger(gc,mk,ky)
    call StoreInteger(gc,mk,ky,od)        
endfunction

function SaveFile takes string fn,gamecache gc returns nothing
    local string mk
    local string ky
    local string sd
    local integer px
    local integer dc
    local integer di
    set mk = I2S(GetPlayerId(GetLocalPlayer())+1)
    set ky = I2S(0)
    set dc = GetStoredInteger(gc,mk,ky)
    call PreloadGenClear()
    call PreloadGenStart()
    set px = 0
    loop
        exitwhen(px>=16)
        exitwhen(px*16>=dc)
        set sd = ""
        set di = 0
        loop
            exitwhen(di>=16)
            exitwhen(px*16+di>=dc)
            set di = di + 1
            set ky = I2S(px*16+di)
            set sd = sd + I2S(GetStoredInteger(gc,mk,ky)) + ","                  
        endloop   
        call Preload("\\")
        call SetPlayerName(Player("+ I2S(px) +"),\\"" + sd + "\\")
        //")
        set px = px + 1         
    endloop
    call Preload("\\")
        return
        //")
    call PreloadGenEnd(fn)
endfunction

function sl_initgc takes integer si returns gamecache
    local string gn
    set gn = "ORPGSL(" + I2S(si) + ").w3v"
    call FlushGameCache(InitGameCache(gn))
    call InitGameCacheBJ(gn)
    call TriggerSleepAction(0.00)
    return bj_lastCreatedGameCache
endfunction

function sl_savefile takes string fn,gamecache gc returns nothing
    call SaveFile(fn,gc)
endfunction

function sl_savefileforplayer takes player lp,string fn,gamecache gc returns nothing
    if(GetLocalPlayer()==lp)then
        call SaveFile(fn,gc)   
    endif
endfunction

function sl_loadfile takes string fn,gamecache gc returns nothing
    local integer px
    set px = 0
    loop
        exitwhen(px>=12)
        if(GetPlayerController(Player(px))==MAP_CONTROL_USER and GetPlayerSlotState(Player(px))==PLAYER_SLOT_STATE_PLAYING)then
            call StoreInteger(gc,I2S(px+1),"0",-1)
        endif
        set px = px + 1
    endloop
    call LoadFile(fn,gc)
    loop
        call TriggerSleepAction(0.00)
        set px = 0
        loop
            exitwhen(px>=12)
            if(GetPlayerController(Player(px))==MAP_CONTROL_USER and GetPlayerSlotState(Player(px))==PLAYER_SLOT_STATE_PLAYING)then
                exitwhen(GetStoredInteger(gc,I2S(px+1),"0")==-1)
            endif
            set px = px + 1
        endloop
        exitwhen(px>=12)
    endloop
endfunction

function sl_loadfileforplayer takes player lp,string fn,gamecache gc returns nothing
    local string mk   
    if(GetPlayerController(lp)==MAP_CONTROL_USER and GetPlayerSlotState(lp)==PLAYER_SLOT_STATE_PLAYING)then
        set mk = I2S(GetPlayerId(lp)+1)
        call StoreInteger(gc,mk,"0",-1)
    else
        return               
    endif
    if(GetLocalPlayer()==lp)then
        call LoadFile(fn,gc)
    endif
    loop
        exitwhen(GetStoredInteger(gc,mk,"0")!=-1)
        exitwhen(GetPlayerController(lp)!=MAP_CONTROL_USER)
        exitwhen(GetPlayerSlotState(lp)!=PLAYER_SLOT_STATE_PLAYING)
        call TriggerSleepAction(0.00)        
    endloop
endfunction

function sl_itoc takes string qd,integer ri returns string
    return SubString(qd,ri-1,ri)   
endfunction

function sl_cicf takes string qd,string rs returns integer
    local integer ix
    local integer sl
    set sl = StringLength(qd)
    set ix = 1
    loop
        exitwhen(ix>sl)
        exitwhen(SubString(qd,ix-1,ix)==rs)
        set ix = ix + 1
    endloop
    return ix
endfunction

function sl_cief takes nothing returns nothing
    set bj_forLoopAIndex = sl_cicf(bj_changeLevelMapName,bj_lastPlayedMusic)
endfunction

function sl_ctoi takes string qd,string rs returns integer
    local integer ti
    local integer li
    local string cn
    local string lm
    set li = bj_forLoopAIndex
    set cn = bj_changeLevelMapName
    set lm = bj_lastPlayedMusic
    set bj_changeLevelMapName = qd
    set bj_lastPlayedMusic = rs      
    call ExecuteFunc("sl_cief")
    set ti = bj_forLoopAIndex
    set bj_forLoopAIndex = li
    set bj_changeLevelMapName = cn
    set bj_lastPlayedMusic = lm
    return ti
endfunction

function sl_savestring takes string sd,string qd,player lp,gamecache gc returns nothing
    local string mk
    local integer sl
    local integer ix
    set mk = I2S(GetPlayerId(lp)+1)
    set sl = StringLength(sd)
    call StoreInteger(gc,mk,"0",sl)
    set ix = 1
    loop
        exitwhen(ix>sl)
        call StoreInteger(gc,mk,I2S(ix),sl_ctoi(qd,SubString(sd,ix-1,ix)))
    set ix = ix + 1      
    endloop
endfunction

function sl_loadstring takes string qd,player lp,gamecache gc returns string
    local string ld   
    local string mk
    local integer sl
    local integer ix
    set ld = ""
    set mk = I2S(GetPlayerId(lp)+1)
    set sl = GetStoredInteger(gc,mk,"0")
    set ix = 1
    loop
        exitwhen(ix>sl)
        set ld = ld + sl_itoc(qd,GetStoredInteger(gc,mk,I2S(ix)))
    set ix = ix + 1      
    endloop
    return ld   
endfunction

function sl_loadlist takes string fn,gamecache gc returns nothing
    local string ts
    local integer px
    local string array pn
    set px = 0
    loop
        exitwhen(px>=16)
        set pn[px] = GetPlayerName(Player(px))
        call SetPlayerName(Player(px)," ")
        set px = px + 1
    endloop   
    call Preloader(fn)
    set px = 0
    loop
        exitwhen(px>=16)
        set ts = GetPlayerName(Player(px))
        if(ts == " ")then
            call StoreString(gc,"list",I2S(px+1),"")
        else
            call StoreString(gc,"list",I2S(px+1),ts)
        endif
        call SetPlayerName(Player(px),pn[px])
        set px = px + 1
    endloop
endfunction

function sl_savelist takes string fn,gamecache gc returns nothing
    local string ts
    local integer px
    call PreloadGenClear()
    call PreloadGenStart()
    set px = 0
    loop
        exitwhen(px>=16)
        set ts = GetStoredString(gc,"list",I2S(px+1))
        if(ts=="")then
            set ts = " "
        endif
        call Preload("\\")
        call SetPlayerName(Player(" + I2S(px) + "),\\"" + ts + "\\")
        //")
        set px = px + 1
    endloop
    call Preload("\\")
        return
        //")
    call PreloadGenEnd(fn)
endfunction
[/jass]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-3-7 12:43:55 | 显示全部楼层
嗯嗯,于是又更新一遍吧~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-6-29 15:38:27 | 显示全部楼层

回 19860209 的帖子

19860209:请问 瓦西大大~~~既然有定义的创建缓存的存放的目录 那么有函数可以删除这个创建后而不需要的目录吗?(2012-03-09 14:48)嬀/color]
貌似是可以删除的,使用“游戏 - 删除存档文件夹”就可以了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-6-29 15:45:26 | 显示全部楼层
本帖最后由 希瓦 于 2012-12-1 15:47 编辑

读取物品的演示.w3x (18.39 KB, 下载次数: 29)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-11-10 14:28:28 | 显示全部楼层
本帖最后由 希瓦 于 2012-12-1 15:49 编辑

3000数据的存取.w3x (13.22 KB, 下载次数: 49)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2019-8-23 10:59 , Processed in 0.067622 second(s), 18 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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