找回密码
 点一下
查看: 3092|回复: 20

帮忙看下,会引起卡的地方

[复制链接]
发表于 2009-10-24 19:47:40 | 显示全部楼层 |阅读模式
我用的是1.24b的编辑器.反正本来用1.20的时候编写都没出现卡过- -1.22变就出现了,郁闷啊

[jass]
function BoomWaterC takes nothing returns nothing
local timer tm=GetExpiredTimer()
local integer i=GetHandleId(tm)
local unit u=LoadUnitHandle(udg_hs,i,StringInt("Source"))
local unit ut=null
local group g=LoadGroupHandle(udg_hs,i,StringInt("Group"))
local group g1=CreateGroup()
local integer j=LoadInteger(udg_hs,i,StringInt("RunTime"))
call GroupAddGroup(g,g1)
if j>0 then
loop
set ut=FirstOfGroup(g1)
exitwhen ut==null
call SetUnitFlyHeight(ut,(10000-(100-j)*(100-j))*0.06,0)
call GroupRemoveUnit(g1,ut)
endloop
call SaveInteger(udg_hs,i,StringInt("RunTime"),j-1)
else
loop
set ut=FirstOfGroup(g1)
exitwhen ut==null
call PauseUnit(ut,false)
set udg_s="洪流"
call damage(u,ut,1000,1)
call GroupRemoveUnit(g1,ut)
endloop
call DestroyGroup(g)
call DestroyTimer(tm)
call FlushChildHashtable(udg_hs,i)
endif
call DestroyGroup(g1)
set tm=null
set u=null
set ut=null
set g=null
set g1=null
endfunction

function BoomWaterB takes nothing returns boolean
if IsPlayer() then
call PauseUnit(GetFilterUnit(),true)
call UnitAddAbility(GetFilterUnit(),'Arav')
call UnitRemoveAbility(GetFilterUnit(),'Arav')
set udg_s="洪流"
call damage(LoadUnitHandle(udg_hs,GetHandleId(GetExpiredTimer()),StringInt("Source")),GetFilterUnit(),1000,3)
return true
endif
return false
endfunction

function BoomWaterA takes nothing returns nothing
local timer tm=GetExpiredTimer()
local integer i=GetHandleId(tm)
local unit u=LoadUnitHandle(udg_hs,i,StringInt("Source"))
local real x=LoadReal(udg_hs,i,StringInt("x"))
local real y=LoadReal(udg_hs,i,StringInt("y"))
local group g=CreateGroup()
local timer t=CreateTimer()
local integer j=0
local integer n=0
call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl",x,y))
call DestroyEffect(LoadEffectHandle(udg_hs,i,StringInt("FX0")))
call DestroyEffect(LoadEffectHandle(udg_hs,i,StringInt("FX1")))
call DestroyEffect(LoadEffectHandle(udg_hs,i,StringInt("FX2")))
call DestroyEffect(LoadEffectHandle(udg_hs,i,StringInt("FX3")))
call DestroyEffect(LoadEffectHandle(udg_hs,i,StringInt("FX4")))
call DestroyEffect(LoadEffectHandle(udg_hs,i,StringInt("FX5")))
call GroupEnumUnitsInRange(g,x,y,275,Condition(function BoomWaterB))
set j=GetHandleId(t)
call SaveUnitHandle(udg_hs,j,StringInt("Source"),u)
call SaveGroupHandle(udg_hs,j,StringInt("Group"),g)
call SaveInteger(udg_hs,j,StringInt("RunTime"),200)
call TimerStart(t,0.01,true,function BoomWaterC)
call DestroyTimer(tm)
call FlushChildHashtable(udg_hs,i)
set tm=null
set g=null
set t=null
set u=null
endfunction

function BoomWater takes nothing returns nothing
local timer tm=GetExpiredTimer()
local integer i=GetHandleId(tm)
local unit u=LoadUnitHandle(udg_hs,i,StringInt("Source"))
local timer t=null
local integer j=0
local real x=0
local real y=0
local integer n=0
set t=CreateTimer()
set j=GetHandleId(t)
loop
set n=GetRandomInt(0,9)
exitwhen udg_Hero[n]!=null and IsUnitType(udg_Hero[n],UNIT_TYPE_DEAD)==false
endloop
set x=GetUnitX(udg_Hero[n])
set y=GetUnitY(udg_Hero[n])
call SaveReal(udg_hs,j,StringInt("x"),x)
call SaveReal(udg_hs,j,StringInt("y"),y)
call SaveUnitHandle(udg_hs,j,StringInt("Source"),u)
set n=0
loop
exitwhen n>5
call SaveEffectHandle(udg_hs,j,StringInt("FX"+I2S(n)),AddSpecialEffect("Objects\\Spawnmodels\\Other\\IllidanFootprint\\IllidanWaterSpawnFootPrint.mdl",x+40*Cos(n*60*bj_DEGTORAD),y+40*Sin(n*60*bj_DEGTORAD)))
set n=n+1
endloop
call TimerStart(t,3,false,function BoomWaterA)
set t=null
set tm=null
set u=null
endfunction
[/jass]

运行到上述语句的时候,如果同时还有其他比如说暴风雪技能在释放(用计时器模拟的),就会卡.
下面放出暴风雪的代码-,-

[jass]
function A001B takes nothing returns nothing
call StopSound(gg_snd_BlizzardLoop1,false,false)
call DestroyTimer(GetExpiredTimer())
endfunction

function A001A takes nothing returns nothing
local timer tm=GetExpiredTimer()
local integer i=GetHandleId(tm)
local real x=LoadReal(udg_hs,i,StringInt("x"))
local real y=LoadReal(udg_hs,i,StringInt("y"))
local unit u=LoadUnitHandle(udg_hs,i,StringInt("Source"))
call RangeDmg(u,x,y,325,250,3,0,"暴风雪")
call DestroyTimer(tm)
call FlushChildHashtable(udg_hs,i)
set tm=null
set u=null
endfunction

function A001 takes nothing returns nothing
local trigger t=GetTriggeringTrigger()
local integer j=GetHandleId(t)
local unit u=LoadUnitHandle(udg_hs,j,StringInt("Source"))
local real x=LoadReal(udg_hs,j,StringInt("x"))
local real y=LoadReal(udg_hs,j,StringInt("y"))
local timer tm=null
local integer m=0
local group g=null
local integer n=0
if GetTriggerEventId()==EVENT_UNIT_SPELL_ENDCAST then
call TimerStart(CreateTimer(),1,false,function A001B)
call SaveBoolean(udg_hs,GetHandleId(GetTriggerUnit()),StringInt("IsSpelling"),false)
call DestroyTriggerAll(t)
else
set tm=CreateTimer()
set m=GetHandleId(tm)
call SaveUnitHandle(udg_hs,m,StringInt("Source"),u)
call SaveReal(udg_hs,m,StringInt("y"),y)
call SaveReal(udg_hs,m,StringInt("x"),x)
call TimerStart(tm,0.8,true,function A001A)
set tm=null
call StopSound(gg_snd_BlizzardLoop1,false,false)
call SetSoundPosition(gg_snd_BlizzardLoop1,x,y,0)
call SetSoundVolume(gg_snd_BlizzardLoop1,127)
call StartSound(gg_snd_BlizzardLoop1)
set n=10
loop
exitwhen n==0
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl",x+GetRandomReal(-325,325),y+GetRandomReal(-325,325)))
set n=n-1
endloop
set g=CreateGroup()
call GroupEnumUnitsInRange(g,x,y,325,Condition(function IsPlayer))
if FirstOfGroup(g)==null then
call IssueTargetOrder(u,"attack",udg_Hero[LoadInteger(udg_hs,j,StringInt("ArgoNum"))])
endif
call DestroyGroup(g)
set g=null
endif
set u=null
set t=null
endfunction


function Trig_NPCSpell_Conditions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit ut=GetSpellTargetUnit()
local integer id=GetSpellAbilityId()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real xt=GetSpellTargetX()
local real yt=GetSpellTargetY()
local trigger t=null
local integer i=0
local integer j=0
local timer tm=null
local group g=null
local integer k=0
local string s
if id=='A002' then
call SaveBoolean(udg_hs,GetHandleId(u),StringInt("IsSpelling"),true)
set t=CreateTrigger()
set j=GetHandleId(t)
call SaveUnitHandle(udg_hs,j,StringInt("Source"),u)
call SaveReal(udg_hs,j,StringInt("y"),yt)
call SaveReal(udg_hs,j,StringInt("x"),xt)
call SaveTriggerConditionHandle(udg_hs,j,StringInt("TriggerCondition"),TriggerAddCondition(t,Condition(function A001)))
call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_SPELL_ENDCAST)
call TriggerRegisterTimerEvent(t,0.99,true)
set t=null
set tm=CreateTimer()
set i=GetHandleId(tm)
call SaveUnitHandle(udg_hs,i,StringInt("Source"),u)
call SaveReal(udg_hs,i,StringInt("y"),yt)
call SaveReal(udg_hs,i,StringInt("x"),xt)
call TimerStart(tm,0.8,true,function A001A)
set tm=null
call StopSound(gg_snd_BlizzardLoop1,false,false)
call SetSoundPosition(gg_snd_BlizzardLoop1,xt,yt,0)
call SetSoundVolume(gg_snd_BlizzardLoop1,127)
call StartSound(gg_snd_BlizzardLoop1)
set j=10
loop
exitwhen j==0
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl",x+GetRandomReal(-325,325),y+GetRandomReal(-325,325)))
set j=j-1
endloop
set g=CreateGroup()
call GroupEnumUnitsInRange(g,xt,yt,325,Condition(function IsPlayer))
if FirstOfGroup(g)==null then
call IssueTargetOrder(u,"attack",udg_Hero[LoadInteger(udg_hs,GetHandleId(u),StringInt("ArgoNum"))])
endif
call DestroyGroup(g)
set g=null
endif
set u=null
set ut=null
endfunction
[/jass]
发表于 2009-10-24 21:24:25 | 显示全部楼层
估计跟哈希表机制有关系

如果我没猜错,哈希表就是一个不可保存的缓存。。那么,暴雪的算法在搞字符串的时候有问题。。。

如果你完全不用哈希表,估计问题就解决了
回复

使用道具 举报

 楼主| 发表于 2009-10-25 00:08:46 | 显示全部楼层
字符串是我自己定义的函数,将一串大小写字母和数字转换为一串数字,不同的组合得到的结果绝对不同,用来做二维下标.
其实我也觉得应该是1.24的问题...........
我以前编写的都不会卡的说.............
回复

使用道具 举报

发表于 2009-10-25 01:33:38 | 显示全部楼层
所以我估计这个东西卡是和哈希算法有关。。
回复

使用道具 举报

 楼主| 发表于 2009-10-25 07:25:43 | 显示全部楼层
-,-果然不能太相信暴雪的编程实力- -
回复

使用道具 举报

发表于 2009-10-25 09:42:41 | 显示全部楼层
这个应该算是当年的bug
回复

使用道具 举报

发表于 2009-10-25 17:58:05 | 显示全部楼层
………………………………………………………………
第一:LZ,我非常疑问你为什么在1.24有StringHash这个函数的情况下,还自己编写某个无聊的StringInt函数,令人极端不解。
第二:没有什么理由可以认为由暴雪专业编程人员编写的hashtable在算法和效率上会比我们自己编写的要慢。
如果Eff和LZ仍然认为这不是因为LZ代码问题造成的而是hashtable本身的问题的话。
我表示理解不能。
顺便说一下,LZ已经确定不是因为特效过多的问题了吗?
回复

使用道具 举报

发表于 2009-10-25 17:59:25 | 显示全部楼层
引用第3楼eff于2009-10-25 01:33发表的  :
所以我估计这个东西卡是和哈希算法有关。。

在《数据结构》中Hashtable是很好的字典。
回复

使用道具 举报

发表于 2009-10-25 20:37:46 | 显示全部楼层
引用第6楼血戮魔动冰于2009-10-25 17:58发表的  :
………………………………………………………………
第二:没有什么理由可以认为由暴雪专业编程人员编写的hashtable在算法和效率上会比我们自己编写的要慢。
如果Eff和LZ仍然认为这不是因为LZ代码问题造成的而是hashtable本身的问题的话。
我表示理解不能。
.......
同等的功能肯定是blz的快,但blz的ht是双层key,而平时绑定数据时很多时候次级key都不是动态的,这种情况下blz的ht不见得比自己用jass代码写的单层ht快了(这里不涉及内部功能比cj函数的优越性,因为自写ht基本都是直接成为虚拟机代码的jass语法代码)
回复

使用道具 举报

 楼主| 发表于 2009-10-25 22:54:58 | 显示全部楼层
话说我不知道有StringHash这个函数- -刚接触1.24没多久........

另外.....特效是否堆积过多我很清楚- -在1.21等同情况下也是不会卡的................

我还是安心用我自己编写的HASH好了- -

令:StringHash这个函数具体的作用和语法是啥?貌似没注意到有这个函数的说.
回复

使用道具 举报

发表于 2009-10-26 00:30:38 | 显示全部楼层
我的结论是用n个计时器和用1个计时器并没有本质区别,而执行函数的最长时间是个问题
回复

使用道具 举报

发表于 2009-10-26 06:18:46 | 显示全部楼层
引用第9楼gducn于2009-10-25 22:54发表的  :
话说我不知道有StringHash这个函数- -刚接触1.24没多久........

另外.....特效是否堆积过多我很清楚- -在1.21等同情况下也是不会卡的................

我还是安心用我自己编写的HASH好了- -
.......

StringHash就是你的StringInt。只不过能识别所有任意字符而已。
回复

使用道具 举报

发表于 2009-10-26 06:50:15 | 显示全部楼层
还有:
你们以为BLZ给你们双层Hash就是用来让你们存储单项数据的?
典型脑子没转过弯来的人。
childKey为0(举个例子)的integer存储在数组里的索引下标,用数组存储所有单项数据。
双层Hash实际上是给你们存储对于指定对象绑定一维数组乃至于N维数组的能力。
至于我们自己写的双层keyHT…………
我倒是想看看谁就敢用只有8190个元素的HT存储n*m这个数量级的数据,效率不慢死才怪。
还有,暴雪的不是双层key,而是双层HashTable。绑定n*m数量级数据可比我们要快。
至于只绑定单项数据,那到底是暴雪快还是我们自己写的快。
这还需要进行测试。
回复

使用道具 举报

 楼主| 发表于 2009-10-26 10:18:03 | 显示全部楼层
非常感谢LS的小BOSS-,-
可是我到目前为止还是米发现卡的原因T,T
泪奔中........
回复

使用道具 举报

发表于 2009-10-26 10:23:26 | 显示全部楼层
小血最近似乎很鸡冻

如果要我说的话,你觉得会卡的话,就按照以下的顺序把代码去掉看看就知道了。

1-把创造单位,特效等东西去掉
2-用固定的数字代替字符串
3-不要用传说中的HashTable试试看。

另外,如果读取数据的跳跃性过大也是会卡的,这个东西和war3底层有关系。

一个很简单的触发器:

任意单位被攻击的时候,获得某个单位的索引,并且对(任意数组[索引])赋值=伤害值,就会非常的卡(也可能是被攻击的问题)。

所以我估计是HashTable的问题。
回复

使用道具 举报

发表于 2009-10-27 06:52:43 | 显示全部楼层
今天早上做了测试。
利用直接撑爆触发器执行字节数限制。
对比了hashtable和自己写的Hashtable的效率。
结果hashtable大获全胜,create,get,delete全部比自己写的快。
对比数据(数值越大说明单次执行字节数越小,效率越高):
       hashtable    array
create      18749         2884
get              3658         2264
delete        3529         1754
(get和delete执行了适当长度的无效字节数,以防止范围太大引起某些小小的偏差)

而且最重要的一点是,执行这6段撑破触发器执行限制字节数的代码,我的魔兽完全没感觉到卡的情况。
所以LZ的问题应该不在hashtable身上。


至于LS Eff的观点。jass的数组array其实就是个比较高效的table而已,根本不是真正的数组,war3hashtable自然没必要套用这个无聊的节省空间的table,100000(举个例子)的指针数组也没多大。
回复

使用道具 举报

发表于 2009-10-27 09:13:02 | 显示全部楼层
偶非常好奇你的Hash算法是怎么写的。。

而且偶发现如果你把需要处理的东西包在一个函数里面的时候会延长机器执行总代码的时间上限。
回复

使用道具 举报

发表于 2009-10-27 18:13:19 | 显示全部楼层
那么你是说……我们要测试自己编写的,写在测试函数里的Hash?
明显不符合实际情况要求。
回复

使用道具 举报

发表于 2009-10-27 23:34:26 | 显示全部楼层
引用第12楼血戮魔动冰于2009-10-26 06:50发表的  :
还有:
你们以为BLZ给你们双层Hash就是用来让你们存储单项数据的?
典型脑子没转过弯来的人。
childKey为0(举个例子)的integer存储在数组里的索引下标,用数组存储所有单项数据。
双层Hash实际上是给你们存储对于指定对象绑定一维数组乃至于N维数组的能力。
.......
没明白要表达什么……
回复

使用道具 举报

发表于 2009-10-28 00:00:38 | 显示全部楼层
也就是说,如果你把那个Hash包成一个函数的话,比如set ObjArray[GetObjectHashIndex(obj)] = obj的话,和你用StoreHash应该在运行限时方面是一样的
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-19 13:13 , Processed in 0.044382 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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