|
楼主 |
发表于 2009-4-2 00:01:52
|
显示全部楼层
很抱歉,我的本意只是先贴出缓存版的物品合成,然后在贴出数组版的,但是失控了,我没想到会有这么多字数...大家可以选择性的看一下,对此不感兴趣的可以直接去下一楼了。
以上说了拉链法中遇到的一个困难,我将在4L给出的物品合成的代码中初步的解决这个问题。接下我先贴出我的使用缓存的物品合成代码,是我在刚接触Jass时自己写的代码,书写习惯和现在略有不同,而且在代码的缩进方面也做的不太对,请大家见谅了。代码的思路如果和现在大家使用的物品合成的代码一样的话那是最好了,如果不一样也没关系,我会做一些注解帮助大家理解。
[codes=jass]//这个是物品合成代码的头文件,其实是我以前使用的Gc+ReturnBug系统的头文件,在这里我只留下目前所需要的。
globals
constant gamecache RGC=InitGameCache("|cffc5d43ecccty1l|r")
endglobals
//! define DEff(e) DestroyEffect(e)
//! define AEff(mod,x,y) AddSpecialEffect(mod,x,y)
//! define AEffT(mod,target,point) AddSpecialEffectTarget(mod,target,point)
//! define Eff(mod,x,y) DestroyEffect(AEff(mod,x,y))
//! define EffT(mod,target,point) DestroyEffect(AEffT(mod,target,point))
//! define If(b) if(b)then
//! define Or(b) elseif(b)then
//! define SetInt(arr,s,val) StoreInteger(RGC,arr,s,val)
//! define SetInts(arr,s,i) StoreInteger(RGC,arr,s,i+GetStoredInteger(RGC,arr,s))
//! define SetBoolean(arr,s,val) StoreBoolean(RGC,arr,s,val)
//! define SetReal(arr,s,val) StoreReal(RGC,arr,s,val)
//! define SetString(arr,s,val) StoreString(RGC,arr,s,val)
//! define GetInt(arr,s) GetStoredInteger(RGC,arr,s)
//! define GetBoolean(arr,s) GetStoredBoolean(RGC,arr,s)
//! define GetIf(arr,s) if(GetStoredBoolean(RGC,arr,s))then
//! define GetOr(arr,s) elseif(GetStoredBoolean(RGC,arr,s))then
//! define GetReal(arr,s) GetStoredReal(RGC,arr,s)
//! define GetString(arr,s) GetStoredString(RGC,arr,s)
//! define FreeString(s) FlushStoredMission(RGC,s)
//! define Freei(arr,s) FlushStoredInteger(RGC,arr,s)
//! define Freer(arr,s) FlushStoredReal(RGC,arr,s)
//! define Frees(arr,s) FlushStoredString(RGC,arr,s)
//! define Freeb(arr,s) FlushStoredBoolean(RGC,arr,s)
//! define IsI(arr,s) HaveStoredInteger(RGC,arr,s)
//! define IsR(arr,s) HaveStoredReal(RGC,arr,s)
//! define IsS(arr,s) HaveStoredString(RGC,arr,s)
//! define IsB(arr,s) HaveStoredBoolean(RGC,arr,s)[/codes]
好了,代码正式开始
[codes=jass]
globals
//这个整数变量记录的是合成公式的总数,每调用一次函数ComItem它都会作为该合成公式的编号,最后会增加1
integer ComItem_maxN=1
//创建一个函数,在下面应该使用下面的语句来使得物品合成代码生效
//call TriggerAddCondition(Trg_ComItem,Condition(function ComItem_trg))
//call TriggerRegisterUnitEvent(Trg_ComItem,XXXX,EVENT_UNIT_PICKUP_ITEM)
//函数ComItem_trg在代码的最下面
constant trigger Trg_ComItem=CreateTrigger()
endglobals
//! define ComItem_s "|cff123456ComItem|r"
//! define ComItem_sID "ITEM"
//! define ComItem1_1(a,h) ComItem(a,0,0,0,0,0,h,0,0,0,0,0,0)
//! define ComItem2_1(a,b,h) ComItem(a,b,0,0,0,0,h,0,0,0,0,0,0)
//! define ComItem2_2(a,b,h,j) ComItem(a,b,0,0,0,0,h,j,0,0,0,0,0)
//! define ComItem3_1(a,b,c,h) ComItem(a,b,c,0,0,0,h,0,0,0,0,0,0)
//! define ComItem3_2(a,b,c,h,j) ComItem(a,b,c,0,0,0,h,j,0,0,0,0,0)
//! define ComItem3_3(a,b,c,h,j,k) ComItem(a,b,c,0,0,0,h,j,k,0,0,0,0)
//! define ComItem4_1(a,b,c,d,h) ComItem(a,b,c,d,0,0,h,0,0,0,0,0,0)
//! define ComItem4_2(a,b,c,d,h,j) ComItem(a,b,c,d,0,0,h,j,0,0,0,0,0)
//! define ComItem4_3(a,b,c,d,h,j,k) ComItem(a,b,c,d,0,0,h,j,k,0,0,0,0)
//! define ComItem5_1(a,b,c,d,e,h) ComItem(a,b,c,d,e,0,h,0,0,0,0,0,0)
//! define ComItem5_2(a,b,c,d,e,h,j) ComItem(a,b,c,d,e,0,h,j,0,0,0,0,0)
//! define ComItem5_3(a,b,c,d,e,h,j,k) ComItem(a,b,c,d,e,0,h,j,k,0,0,0,0)
//! define ComItem1_u(a,h,unitID) ComItem(a,0,0,0,0,0,h,0,0,0,0,0,unitID)
//! define ComItem2_u(a,b,h,unitID) ComItem(a,b,0,0,0,0,h,0,0,0,0,0,unitID)
//! define ComItem3_u(a,b,c,h,unitID) ComItem(a,b,c,0,0,0,h,0,0,0,0,0,unitID)
//! define ComItem4_u(a,b,c,d,h,unitID) ComItem(a,b,c,d,0,0,h,0,0,0,0,0,unitID)
//! define ComItem5_u(a,b,c,d,e,h,unitID) ComItem(a,b,c,d,e,0,h,0,0,0,0,0,unitID)
//! define ComItem6_u(a,b,c,d,e,f,h,unitID) ComItem(a,b,c,d,e,f,h,0,0,0,0,0,unitID)
//这个函数是注册叠加物品的,用法如下
//call ComItemS('I000',12,'I001')
//call ComItemS('I001',3,'I002')
//这样物品'I000'会在叠加数量达到12时合成一个'I001',而物品'I001'在达到3时合成一个'I002'
//注意:在我的代码中,物品种类是ITEM_TYPE_PURCHASABLE才会叠加,并且只能参与叠加
function ComItemS takes integer a,integer num,integer h returns nothing
local item i=CreateItem(h,0,0)
local string s=I2S(a)+ComItem_sID
If(num>1)
//使用缓存记录下需要的数量和要合成的物品
call SetInt(s,"num",num)
call SetInt(s,"ComI",h)
//创建物品,然后判断它的种类是否是ITEM_TYPE_PURCHASABLE,用法见函数ComItem_trg2
If(GetItemType(i)==ITEM_TYPE_PURCHASABLE)
call SetBoolean(s,"boolean",true)
endif
endif
call RemoveItem(i)
set i=null
set s=null
endfunction
//这个函数是注册物品合成的,用法如下(配合上面的define,调用起来还是比较方便的)
//call ComItem1_1('I010','I011')
//↑可以由一个物品直接变成另外一个,一般处理东西的是合成卷轴
//call ComItem2_1('I014','I013','I020')
//↑最简单的,两个物品合成一个
//call ComItem3_1('I011','I013','I013','I021')
//↑三个物品合成一个,支持同一配方中的同类物品
//call ComItem5_2('I015','I017','I016','I018','I015','I022','I023')
//↑5合2,传参的顺序是无所谓的,可以合成多个物品,多物品合成多物品是为装备分解等功能做出来的
//call ComItem3_u('I021','I020','I022','I030','H001')
//↑支持合成专属,上例是为单位ID为'H001'合成专属的配方
//函数支持最多6物品合成6物品,如果搞不错传参的位置的话,可以直接调用函数ComItem
//注意,下面的调用是非法的
//call ComItem('I010',0,'I020',0,0,0,'I023',0,0,'I024',0,0,0)
//在读取物品ID时,函数会在遇到第一个0处停止,一次上一函数相当于↓
//call ComItem1_1('I010','I023')
function ComItem takes integer a,integer b,integer c,integer d,integer e,integerf,integer g,integer h,integer j,integer k,integer l,integer m,integerunitID returns nothing
local integer array i
local integer n=1
local integer z
local string s=I2S(ComItem_maxN)+ComItem_s
local string ItemID_s
//记录上传的原料物品ID,用循环处理
set i[1]=a
set i[2]=b
set i[3]=c
set i[4]=d
set i[5]=e
set i[6]=f
loop
exitwhen i[n]==0 or n>6
set ItemID_s=I2S(i[n])
//判断在该编号(ComItem_maxN)的合成配方中,该物品(i[n])是否已经添加了
if IsI(s,ItemID_s) then
//是!将该物品的编号加一
call SetInts(s,ItemID_s,1)
else
//否!生成该物品的编号,个位表示所需的数量,十位表示其顺序
call SetInt(s,ItemID_s,n*10+1)
//这个记录的该物品(i[n])参与的合成公式的编号
set z=GetInt(ComItem_sID,ItemID_s)+1
call SetInt(ItemID_s+ComItem_sID,I2S(z),ComItem_maxN)
call SetInt(ComItem_sID,ItemID_s,z)
endif
set n=n+1
endloop
//记录该合成公式的原料数量
call SetInt(s,"num",n-1)
//记录上传的生成物品ID,用循环处理
set n=1
set i[1]=g
set i[2]=h
set i[3]=j
set i[4]=k
set i[5]=l
set i[6]=m
loop
exitwhen i[n]==0 or n>6
call SetInt(s,I2S(n),i[n])
set n=n+1
endloop
//判断生成的物品是否是专属
If(unitID>0)
//是!记录下单位ID
call SetBoolean(s,"onlyone",true)
call SetInt(s,"unitID",unitID)
endif
//公式的编号加一,等待下次函数运行
set ComItem_maxN=ComItem_maxN+1
set s=null
set ItemID_s=null
endfunction
//上面的注册函数是在地图初始化后运行的,请在注册的时候注意代码执行上限的限制
//下面的函数就是动作函数了,单位在获取了物品之后会运行ComItem_trg1或ComItem_trg2
//这个函数是处理物品叠加的,可能看起来有些冗余,但是我觉得都是必须的
function ComItem_trg2 takes unit u,item i returns nothing
local item it
local integer id=GetItemTypeId(i)
local integer z=0
local integer n=GetItemCharges(i)
local integer maxN
local string s
loop
set it=UnitItemInSlot(u,z)
//判断各个物品栏中的物品是否是上传物品的同类型物品
If(it!=i and GetItemTypeId(it)==id)
//是!则删除物品i
call RemoveItem(i)
set i=it
//记录下能叠加的数量
set n=n+GetItemCharges(i)
endif
set z=z+1
exitwhen z>=6
endloop
//获取之前注册的叠加数量的上限
set s=I2S(id)+ComItem_sID
set maxN=GetInt(s,"num")
//判断是否能生成新的物品
If(n<maxN or maxN==0)
//否!设置物品i的数量,函数就此完成任务。
call SetItemCharges(i,n)
Or(n>=maxN)
//是!计算可以生成的新物品的数量以及合成后物品i的剩余数量
//这里的设计就是考虑到得到的物品的叠加数可能本身就是大于maxN的,这样z的值就会大于一
set z=n/maxN
set n=n-z*maxN
//判断物品i是否有剩余
If(n!=0)
//是!设置物品i的数量
call SetItemCharges(i,n)
else
//否!删除物品i
call RemoveItem(i)
endif
set id=GetInt(s,"ComI")
//判断生成物品的(叠加)数量是否大于1
If(z>1)
//是!
//判断生成的物品是否可以叠加
GetIf(s,"boolean")
//是!创建物品,设置好数量后送给单位
set i=CreateItem(id,0,0)
call SetItemCharges(i,z)
call UnitAddItem(u,i)
else
//否!则生成相应数量的物品给单位
loop
call UnitAddItemById(u,id)
set z=z-1
exitwhen z<=0
endloop
endif
Or(z==1)
//否!不需要别的考虑了,直接创建物品
call UnitAddItemById(u,id)
endif
endif
set s=null
set it=null
endfunction
//这个函数是处理物品合成的
function ComItem_trg1 takes unit u,integer n returns boolean
local string s=I2S(n)+ComItem_s
local integer array i
local item array it
local item it0=null
local integer z=0
local integer a
local integer b
local string ItemID_s=null
local boolean bo=false
//判断该合成公式是否是某些单位的专属
GetIf(s,"onlyone")
//是!
//判断获取物品的单位的ID是否符合条件
if GetUnitTypeId(u)!=GetInt(s,"unitID") then
//否!返回false
set s=null
return bo
endif
endif
//获取合成公式的原料物品数量
set n=GetInt(s,"num")
loop
set it0=UnitItemInSlot(u,z)
set ItemID_s=I2S(GetItemTypeId(it0))
//判断单位物品栏中第z个物品是否参与了该合成公式
if IsI(s,ItemID_s) then
//是!
//获取该物品在该公式中的编号和所需数量
set a=GetInt(s,ItemID_s)
set b=a/10
//判断该物品是否已经够用了
If(i<a)
//否!下面的代码就是修改i的值来用于上面一行的判断
If(i==0)
set i=b*10+1
else
set i=i+1
endif
//记录下物品,以后若能合成就删除它们
set it[n]=it0
set n=n-1
endif
endif
set z=z+1
//搜完所有的物品栏或者找齐了所有原料则跳出
exitwhen z>=6 or n<=0
endloop
//判断原料是否齐备了
If(n==0)
//是!
set bo=true
set n=1
//删除所有的原料
loop
exitwhen it[n]==null
call RemoveItem(it[n])
set it[n]=null
set n=n+1
endloop
//如果原料超过1则创建合成特效,排除掉了单个物品的转化
If(n>=2)
call EffT("Abilities\\\\Spells\\\\Items\\\\AIsm\\\\AIsmTarget.mdl",u,"origin")
endif
//如果专属只能合成一个,那么在此消除掉单位ID
GetIf(s,"onlyone")
call SetInt(s,"unitID",-1)
endif
//依次创建生成的物品
set n=1
loop
exitwhen not IsI(s,I2S(n))
call UnitAddItemById(u,GetInt(s,I2S(n)))
set n=n+1
endloop
endif
set s=null
set it0=null
set ItemID_s=null
//如果成功了会返回true,不然就是false,下面的循环会继续
return bo
endfunction
function ComItem_trg takes nothing returns boolean
local unit u=GetTriggerUnit()
local item it=GetManipulatedItem()
local string s=null
local integer i=1
//判断物品是否是用于叠加的
if GetItemType(it)==ITEM_TYPE_PURCHASABLE then
//是!调用ComItem_trg2
call ComItem_trg2(u,it)
else
//否!
set s=I2S(GetItemTypeId(it))+ComItem_sID
//历遍单位参与的所有的合成公式直到合成成功或找到最后
loop
exitwhen not IsI(s,I2S(i))
exitwhen ComItem_trg1(u,GetInt(s,I2S(i)))
set i=i+1
endloop
set s=null
endif
set u=null
set it=null
return false
endfunction[/codes]
不太习惯做注解,也不知道弄成这样有没影响大家查看,这个是很早之前做的模板了,基本上都忘了思路是怎样的了,这次一个一个做注解看下来,也算是给自己做数组版的一点思路吧。
下面看修改为数组版本的代码吧。 |
|