| 09-04-2007, 01:39 AM | #1 |
The spells in my map are all based on the latest caster system. As I have said before, the latest spell factory orb/aura templates do not work. Can I add portions of the old caster system to the new one to make them work? If so, what would I need from the old? |
| 09-04-2007, 03:02 AM | #2 |
It is not the caster system it is CSCache, in theory you can add attacheable sets from old CSCache, It requires you to change the GetAttachedInt functions, perhaps if you post the newest CSCache and one of the old ones I can try making one (I don't have the old CSCache anymore) |
| 09-04-2007, 03:38 AM | #3 |
Thanks Vex... I GREATLY appreciate this! I have like 3 people so excited about you doing this... JASS:library CSCache initializer InitCSCache //*************************************************************************** //* * //* CSCache 14.3 [url]http://wc3campaigns.net/vexorian[/url] * //* ¯¯¯¯¯¯¯ * //* From attach variables to Dynamic Arrays, not forgetting the tables, * //* CSData and the Pools, this is a pack of storage options * //* * //*************************************************************************** //================================================================================================= // CSCache globals: // globals gamecache cs_cache = null integer array cs_array1 integer array cs_array3 integer array cs_array2 integer array cs_freeindexes integer array cs_pairx integer array cs_pairy integer array cs_freepairs gamecache udg_cscache = null //udg_ for compat! endglobals //================================================================================================= // Note: //! define macro commands are used accross the script, they are usually to be parsed by // WEHelper, no //! define parser is really required, but if present it would improve the // performance of some calls. // //================================================================================================= // a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems (I intended this // system to be easy to copy // function CS_H2I takes handle h returns integer return h return 0 endfunction //================================================================================================== // Bunch of other return bug exploiters // function CS_i2r takes integer i returns real return i return 0. endfunction function CS_h2r takes handle h returns real return h return 0. endfunction function CS_r2i takes real r returns integer return r return 0 endfunction function CS_lx takes location l returns location return GetLocationX(l) return null endfunction function CS_ly takes location l returns location return GetLocationY(l) return null endfunction function CS_i2l takes integer l returns location return l return null endfunction //================================================================================================== // location linked list kit // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Thanks: Pipedream | No thanks: Blizzard (for lame bug) // // It is a great irony, but locations are only useful when you don't use them as points but as // structs thanks to the return bug. They only allow 2 values so they are limited in comparission // to gamecache and arrays (see bellow) still useful for single linked lists. // // These functions are what I call enough to use locations as single list nodes, X holds values and // Y can just hold a location (or real) . The Get functions use bj globals to fix an odd operator // bug that can happen after converting pointer to real into pointer to integer. // // The Set functions can be replaced by the Location() constructor, the MoveLocation() native and // the return bug exploiters up there. // //=================================================================================================== // Constructors // function Location_IntLoc takes integer x , location y returns location return Location(CS_i2r(x),CS_h2r(y)) endfunction //! define Location_IntLoc(x,y) Location(CS_i2r(x),CS_h2r(y)) function Location_ObjectLoc takes handle x , location y returns location return Location(CS_h2r(x),CS_h2r(y)) endfunction //! define Location_ObjectLoc(x,y) Location(CS_h2r(x),CS_h2r(y)) function Location_LocLoc takes handle x , location y returns location return Location(CS_h2r(x),CS_h2r(y)) endfunction //! define Location_LocLoc(x,y) Location(CS_h2r(x),CS_h2r(y)) function Location_RealLoc takes real x , location y returns location return Location(x,CS_h2r(y)) endfunction //! define Location_RealLoc(x,y) Location(x,CS_h2r(y)) //==================================================================================================== // Combined assigments // function SetLocation_IntLoc takes location loc, integer x , location y returns nothing call MoveLocation(loc,CS_i2r(x),CS_h2r(y)) endfunction //! define SetLocation_IntLoc(loc,x,y) MoveLocation(loc,CS_i2r(x),CS_h2r(y)) function SetLocation_ObjectLoc takes location loc, handle x , location y returns nothing call MoveLocation(loc,CS_h2r(x),CS_h2r(y)) endfunction //! define SetLocation_ObjectLoc(loc,x,y) MoveLocation(loc,CS_h2r(x),CS_h2r(y)) function SetLocation_LocLoc takes location loc, handle x , location y returns nothing //Funny name call MoveLocation(loc,CS_h2r(x),CS_h2r(y)) endfunction //! define SetLocation_LocLoc(loc,x,y) MoveLocation(loc,CS_h2r(x),CS_h2r(y)) function SetLocation_RealLoc takes location loc, real x , location y returns nothing call MoveLocation(loc,x,CS_h2r(y)) endfunction //! define SetLocation_RealLoc(loc,x,y) MoveLocation(loc,x,CS_h2r(y)) //=================================================================================================== // Lack of SetLocationX / SetLocationY natives is kind of lame // function SetLocationX_Object takes location loc, handle val returns nothing call MoveLocation(loc,CS_h2r(val),GetLocationY(loc)) endfunction // Notice how define SetLocationX_Object(loc,v) MoveLocation(loc,CS_h2r(v),GetLocationY(loc)) // would have a chance of messing sometimes since it has 2 loc in the result. function SetLocationX_Loc takes location loc, location val returns nothing //just name candy call MoveLocation(loc,CS_h2r(val),GetLocationY(loc)) endfunction function SetLocationX_Real takes location loc, real val returns nothing call MoveLocation(loc,val,GetLocationY(loc)) endfunction function SetLocationX_Int takes location loc, integer val returns nothing call MoveLocation(loc,CS_i2r(val),GetLocationY(loc)) endfunction function SetLocationY_Loc takes location loc, location val returns nothing call MoveLocation(loc,GetLocationX(loc),CS_h2r(val)) endfunction //================================================================================================== // All right, crazyness that started with Attacheable variables, and had to continue with everything // from tables, arrays and now this. Sorry I can't help itç // // The good thing about these functions is that they are safe, you won't deal with real->(int/handle) // conversion related bugs thanks to the use of bj variables these functions do // function GetLocationX_Loc takes location loc returns location set bj_enumDestructableCenter=CS_lx(loc) return bj_enumDestructableCenter endfunction function GetLocationY_Loc takes location loc returns location set bj_enumDestructableCenter=CS_ly(loc) return bj_enumDestructableCenter endfunction function GetLocationX_Int takes location loc returns integer set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex endfunction function GetLocationX_Unit takes location loc returns unit set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Item takes location loc returns item set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Effect takes location loc returns effect set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Lightning takes location loc returns lightning set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Widget takes location loc returns widget set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Object takes location loc returns handle set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Rect takes location loc returns rect set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Region takes location loc returns region set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_TimerDialog takes location loc returns timerdialog set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Destructable takes location loc returns destructable set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Trigger takes location loc returns trigger set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Timer takes location loc returns timer set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Group takes location loc returns group set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_TriggerAction takes location loc returns triggeraction set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Image takes location loc returns image set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Ubersplat takes location loc returns ubersplat set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Sound takes location loc returns sound set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction // //That should be all we needed to abuse Locations, Love lists. // // CSCache initializer : function InitCSCache takes nothing returns nothing call FlushGameCache(InitGameCache("cscache")) set cs_cache=InitGameCache("cscache") set udg_cscache = cs_cache call ExecuteFunc("InitArrayIndexes") call ExecuteFunc("Pool_SetupCharMap") endfunction //================================================================================================== // CSData // ¯¯¯¯¯¯ // CSDatas are like UserData in units and items, they are faster than gamecache unless you have more // than 8191 handles in your map. In that case it would be a little slower but only for those // handles. And if you have more than 8191 handles your map is too slow already anyways. // // Notice that for public spells or systems to be distributed you should only use these // for private objects (those who the mapper would never have access to) If you are making something // for your map you can use them wherever you want. // // Best to be used in conjunction to CSArrays so you just specify an array id for a handle. // // DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag, // -any 'argument' handle (like playerstate, damagetype, etc) // function SetCSData takes handle h, integer v returns nothing local integer i=CS_H2I(h)-0x100000 if (i>=8191) then call StoreInteger(cs_cache,"csdata",I2S(i),v) else set cs_array3[i]=v endif endfunction function GetCSData takes handle h returns integer local integer i=CS_H2I(h)-0x100000 if (i>=8191) then //can't use Get without Set return GetStoredInteger(cs_cache,"csdata",I2S(i)) endif return cs_array3[i] endfunction //================================================================================================================= // CS Pairs // ¯¯¯¯¯¯¯¯ // This is a sub system to assist csarrays, you can use them but CSArrays of size 2 have the same functionality // although cspairs are be faster their space is limited and will start using gamecache if abused // function NewPair takes integer x, integer y returns integer local integer i if (cs_freepairs[0]==0) then set cs_freepairs[8190]=cs_freepairs[8190]+1 set i= cs_freepairs[8190] else set i= cs_freepairs[cs_freepairs[0]] set cs_freepairs[0]=cs_freepairs[0]-1 endif if (i>=8189) then //because we can only recycle up to 8189 (free pairs array uses indexes 0 and 8190 for other purposes) call StoreInteger(cs_cache,"pairx",I2S(i),x) call StoreInteger(cs_cache,"pairy",I2S(i),y) else set cs_pairx[i]=x set cs_pairy[i]=y endif return i endfunction function DestroyPair takes integer id returns nothing if (id>=8189) then call FlushStoredInteger(cs_cache,"pairx",I2S(id)) call FlushStoredInteger(cs_cache,"pairy",I2S(id)) else set cs_freepairs[0]=cs_freepairs[0]+1 set cs_freepairs[cs_freepairs[0]] = id endif endfunction function SetPairXY takes integer id, integer x, integer y returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairx",I2S(id),x) call StoreInteger(cs_cache,"pairy",I2S(id),y) else set cs_pairx[id]=x set cs_pairy[id]=y endif endfunction function SetPairX takes integer id, integer x returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairx",I2S(id),x) else set cs_pairx[id]=x endif endfunction function SetPairY takes integer id, integer y returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairy",I2S(id),y) else set cs_pairy[id]=y endif endfunction function GetPairX takes integer id returns integer if (id>=8189) then return GetStoredInteger(cs_cache,"pairy",I2S(id)) endif return cs_pairx[id] endfunction function GetPairY takes integer id returns integer if (id>=8189) then return GetStoredInteger(cs_cache,"pairx",I2S(id)) endif return cs_pairy[id] endfunction //================================================================================================================= // CS Dynamic Arrays // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Thanks: Pipedream, Peppar // // We can now create arrays in game! , also pass them as arguments or return values! // a 1 length array is a pointer! // function Array_TryFree takes nothing returns nothing local integer i local integer N=cs_array1[0] local integer k local boolean cleaned=false local integer loc local integer q local integer r set i=cs_array1[146] if (i>144) then call TimerStart(GetExpiredTimer(),60.,false,function Array_TryFree) return endif set loc=cs_freeindexes[i] set q=0 loop exitwhen (loc==0) // we could just have used: //set k=GetPairX(loc) //set r=GetPairY(loc) But it is slower than direct usage: if (loc>=8192) then set k=GetStoredInteger(cs_cache,"pairx",I2S(loc)) set r=GetStoredInteger(cs_cache,"pairy",I2S(loc)) else set k=cs_pairx[loc] set r=cs_pairy[loc] endif if (k+i-1==N) then //we found one we can remove from the list set cleaned=true //decrement N set N=k-2 //Remove from the list: if (q==null) then //That was the first, update the array as well set cs_freeindexes[i]=r else //Update the next of the previous one //We could use : call SetPairY(q,,r) but it is slower if (q>=8189) then call StoreInteger(cs_cache,"pairy",I2S(q),r) else set cs_pairy[q]=r endif endif if (r==null) then //This was the last one, update it in the array as well set cs_freeindexes[i+4096]=q endif call DestroyPair(loc) set loc=q endif set q=loc set loc=r endloop if (cleaned) then set cs_array1[0]=N set cs_array1[146]=1 else set cs_array1[146]=cs_array1[i+1] endif call TimerStart(GetExpiredTimer(),0.2,false,function Array_TryFree) endfunction function InitArrayIndexes2 takes nothing returns nothing local integer i=0 loop exitwhen (i==8191) set cs_pairx[i]=777 set cs_pairy[i]=777 set i=i+1 endloop endfunction function InitArrayIndexes takes nothing returns nothing local integer i=0 local integer a=1 local integer b=1 local integer c //By placing 777 there instead of 0 it is easier to recognize non correctly initialized bugs loop exitwhen (i== 8191) set cs_array1[i]=777 set cs_array2[i]=777 set cs_array3[i]=777 //set cs_pairx[i]=777 //set cs_pairy[i]=777 set i=i+1 endloop call ExecuteFunc("InitArrayIndexes2") set cs_freeindexes[0]=0 //The stack for the table indexes. set cs_freepairs[0]=0 set cs_freepairs[8190]=0 set i=1 loop set c=a+b set a=b set b=c exitwhen (b>144) //max size is 144 set cs_freeindexes[b]=0 //the first of the list set cs_freeindexes[b+4096]=0 //the last of the list loop exitwhen (i>b) set cs_array1[i]=b set i=i+1 endloop endloop set cs_array1[i]=b //i is 145 set cs_array1[146]=1 set cs_array1[147]=101 //initial table index is 101 set cs_array1[0]=147 //index 0: Last used index // 1 to 145 : Fibonacci sequence // 146 : last check // 147 : Table indexes check //This has a good chance to compress the thing when necesary call TimerStart(CreateTimer(),60.,false,function Array_TryFree) endfunction //============================================================================================= // Create an array of size, max size is 144, if doinit is true it will put a bunch of zeros // in the indexes // function NewArray takes integer size, boolean doinit returns integer local integer i local integer rsize=cs_array1[size] local integer loc set loc=cs_freeindexes[rsize] if (loc!=0) then set cs_freeindexes[rsize]= GetPairY(loc) if (cs_freeindexes[rsize]==0) then set cs_freeindexes[4096+rsize]=0 endif set i=GetPairX(loc) call DestroyPair(loc) if (i==0) then //this code was probably a good idea when we used locations for the free indexes list, now we use pairs which should not ever //do this unless someone modiffied the pair array incorrectly call BJDebugMsg("Caster System: Unexpected error (5): corrupt stack, attempt to recover "+I2S(rsize)) // recovering involves forgetting about the stack which got corrupted and start again from zero, it will leak // and probably get slow due to usage of gamecache but it is better than the problems that a corrupt stack might cause set cs_freeindexes[rsize]=0 set cs_freeindexes[4096+rsize]=0 return NewArray(size,doinit) endif else //sz i i+1 i+2 //[ ][ ][ ][ ] set i=cs_array1[0]+2 set cs_array1[0]=i+rsize-1 endif //It used to store size in the index equal to the array's id // but that required the get/set functions to increment 1 in every index // calculation. Instead, making size the previous index to the array works if (i<=8191) then set cs_array1[i-1]=size elseif (i<=16382) then set cs_array2[i-8192]=size else call StoreInteger(cs_cache,I2S(-i),"size",size) endif if (not doinit) then return i endif // 3 //[i][i+1][i+2] set size=i+size-1 if (size>=16382) then set size=16381 endif loop exitwhen (size<i) or (size<8191) set cs_array2[size-8191]=0 set size=size-1 endloop loop exitwhen (size<i) set cs_array1[size]=0 set size=size-1 endloop //call DisplayTextToPlayer(GetLocalPlayer(),0,0,I2S(i)) return i endfunction //=============================================================================================================== // Remember to destroy arrays when you no longer need them, else new arrays will get slower after a bunch of // arrays are active // function DestroyArray takes integer id returns nothing local integer L local integer loc // local string k=I2S(-id) local integer lstpace if (id<=8191) then set L=cs_array1[cs_array1[id-1]] elseif (id<=16382) then set L=cs_array1[cs_array2[id-8191]] else set L=cs_array1[GetStoredInteger(cs_cache,I2S(-id),"size")] //No way you are gonna call DestroyArray without calling //NewArray first, so we can use the gamecache variable directly instead endif set lstpace=id+L-1 call FlushStoredMission(cs_cache,I2S(-id)) if (lstpace>16382) then if (lstpace==cs_array1[0]) then //We just destroyed the array that happens to be at the end of the heap. //Just get it back set cs_array1[0]=id-2 set cs_array1[146]=1 else //Add to the last set loc=cs_freeindexes[L+4096] if (loc==0) then set loc=NewPair(id,0) set cs_freeindexes[L]=loc set cs_freeindexes[L+4096]=loc else set cs_freeindexes[L+4096]= NewPair(id,0) //we could just use: call SetPairY(loc, cs_freeindexes[L+4096] ) //but that's slower if (loc>=8189) then call StoreInteger(cs_cache,"pairy",I2S(loc), cs_freeindexes[L+4096] ) else set cs_pairy[loc]=cs_freeindexes[L+4096] endif endif endif elseif (lstpace==cs_array1[0]) then //We just destroyed the array that happens to be at the end of the heap. //Just get it back set cs_array1[0]=id-2 set cs_array1[146]=1 else set loc=cs_freeindexes[L] set cs_freeindexes[L]=NewPair(id,loc) if (loc==0) then set cs_freeindexes[L+4096]=cs_freeindexes[L] endif endif endfunction //================================================================================================================ // Int Set/Get array usage prototypes. // // These are the actual functions, the rest are just the result of copy paste, if these functions are updated // the other ones should be updated as well (They are just return bugged variations) // function SetArrayInt takes integer id, integer index, integer val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=val elseif (index<16382) then set cs_array2[index-8191]=val else call StoreInteger(cs_cache,I2S(-id),I2S(index),val) endif endfunction function GetArrayInt takes integer id, integer index returns integer set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) endfunction //================================================================================================================ // String Set/Get array // // Due String related return bug issues, these are forced to use gamecache // function SetArrayString takes integer id, integer index, string val returns nothing call StoreString(cs_cache,I2S(-id),I2S(index),val) endfunction function GetArrayString takes integer id, integer index returns string return GetStoredString(cs_cache,I2S(-id),I2S(index)) endfunction //(Boolean is not needed) //=================================================================================================== // Indexes of real types // function SetArrayReal takes integer id, integer index, real val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=CS_r2i(val) elseif (index<16382) then set cs_array2[index-8191]=CS_r2i(val) else call StoreInteger(cs_cache,I2S(-id),I2S(index),CS_r2i(val)) endif endfunction function GetArrayReal takes integer id, integer index returns real set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return 0.0 endfunction //=================================================================================================== // <Indexes of handle types> // function SetArrayObject takes integer id, integer index, handle val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=CS_H2I(val) elseif (index<16382) then set cs_array2[index-8191]=CS_H2I(val) else call StoreInteger(cs_cache,I2S(-id),I2S(index),CS_H2I(val)) endif endfunction // // //Yep, I am crazy. But These are FASTER than using the function and a return bug exploiter separatedly. function GetArrayObject takes integer id, integer index returns handle set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayWidget takes integer id, integer index returns widget set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTimer takes integer id, integer index returns timer set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayUnit takes integer id, integer index returns unit set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayLoc takes integer id, integer index returns location set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTrigger takes integer id, integer index returns trigger set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTriggerAction takes integer id, integer index returns triggeraction set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayGroup takes integer id, integer index returns group set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayEffect takes integer id, integer index returns effect set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayItem takes integer id, integer index returns item set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayLightning takes integer id, integer index returns lightning set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction //The rest are not used that much and they are a waste of space instead of a save of speed //most of the times. THEY ARE STILL MUCH FASTER THAN GAMECACHE function GetArrayRect takes integer id, integer index returns rect return GetArrayInt(id,index) return null endfunction function GetArrayRegion takes integer id, integer index returns region return GetArrayInt(id,index) return null endfunction function GetArrayTimerDialog takes integer id, integer index returns timerdialog return GetArrayInt(id,index) return null endfunction function GetArrayDestructable takes integer id, integer index returns destructable return GetArrayInt(id,index) return null endfunction function GetArrayImage takes integer id, integer index returns image return GetArrayInt(id,index) return null endfunction function GetArrayUbersplat takes integer id, integer index returns ubersplat return GetArrayInt(id,index) return null endfunction function GetArraySound takes integer id, integer index returns sound return GetArrayInt(id,index) return null endfunction // </Indexes of handle types> // The horror! // //========================================================================================================================== // Returns the size of an array (the specified by player one, not the actual size of it) should be useful. // function GetArraySize takes integer id returns integer if (id<=8191) then return cs_array1[id-1] elseif (id<=16382) then return cs_array2[id-8192] endif return GetStoredInteger(cs_cache,I2S(-id),"size") endfunction //=========================================================================================================================== // Returns an array that is an exact copy of the given array // function CloneArray takes integer id returns integer local integer sz local integer i local integer sz2 local integer x local integer y if (id<=8191) then set sz=cs_array1[id-1] elseif (id<=16382) then set sz=cs_array2[id-8192] else set sz=GetStoredInteger(cs_cache,I2S(-id),"size") //No way you are gonna call DestroyArray without calling //NewArray first, so we can use the gamecache variable directly instead endif set i=NewArray(sz,false) set sz2=i+sz-1 set sz=id+sz-1 set x=i set y=id loop exitwhen ((y>sz) or (y>=8191) or (x>=8191)) set cs_array1[x]=cs_array1[y] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=8191) or (x>=16382)) set cs_array2[x-8191]=cs_array1[y] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=8191)) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array1[y]) set x=y+1 set y=y+1 endloop //... loop exitwhen ((y>sz) or (y>=16382) or (x>=8191)) set cs_array1[x]=cs_array2[y-8191] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=16382) or (x>=16382)) set cs_array2[x-8191]=cs_array2[y-8191] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=16382)) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array2[y-8191]) set y=y+1 set x=x+1 endloop //... loop exitwhen ((y>sz) or (x>=8191)) set cs_array1[x]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)) set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (x>=16382)) set cs_array2[x-8191]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)) set y=y+1 set x=x+1 endloop loop exitwhen (y>sz) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))) set y=y+1 set x=x+1 endloop return i endfunction //================================================================================================== // Attachable vars : Attacheable variables are what most other people call Handle Variables, they // allow to relate data with any handle, using a label, and its value, the stuff auto flushes if // the value is 0, false, "", or null . // // Differences between Attacheable variables and "Local Handle Variables" : // - The names of the functions // - The name of the function group does not cause confusion, it is difficult to say: // "you should set local handle variables to null at the end of a function" since // it sounds as if you were talking about the "Local Handle Variables" // - And can work together with Tables. // // Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!) // // // Although locations and dynamic arrays are faster than gamecache, gamecache still keeps the flexibility // Best thing to do in my opinion is to combine these options. By combining you can acquire gamecache // flexibility and arrays/locs speed to solve a problem // //============================================================================================================ // For integers // function AttachInt takes handle h, string label, integer x returns nothing if x==0 then call FlushStoredInteger(cs_cache,I2S(CS_H2I(h)),label) else call StoreInteger(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedInt takes handle h, string label returns integer return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) endfunction //============================================================================================================= function AttachReal takes handle h, string label, real x returns nothing if x==0 then call FlushStoredReal(cs_cache,I2S(CS_H2I(h)),label) else call StoreReal(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedReal takes handle h, string label returns real return GetStoredReal(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachBoolean takes handle h, string label, boolean x returns nothing if not x then call FlushStoredBoolean(cs_cache,I2S(CS_H2I(h)),label) else call StoreBoolean(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedBoolean takes handle h, string label returns boolean return GetStoredBoolean(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachString takes handle h, string label, string x returns nothing if ((x=="") or (x==null)) then call FlushStoredString(cs_cache,I2S(CS_H2I(h)),label) else call StoreString(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedString takes handle h, string label returns string return GetStoredString(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachObject takes handle h, string label, handle x returns nothing if (x==null) then call FlushStoredInteger(cs_cache,I2S(CS_H2I(h)),label) else call StoreInteger(cs_cache,I2S(CS_H2I(h)),label,CS_H2I(x)) endif endfunction function GetAttachedObject takes handle h, string label returns handle return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedWidget takes handle h, string label returns widget return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedRect takes handle h, string label returns rect return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedRegion takes handle h, string label returns region return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedTimerDialog takes handle h, string label returns timerdialog return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedUnit takes handle h, string label returns unit return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedItem takes handle h, string label returns item return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedEffect takes handle h, string label returns effect return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedDestructable takes handle h, string label returns destructable return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedTrigger takes handle h, string label returns trigger return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedTimer takes handle h, string label returns timer return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedGroup takes handle h, string label returns group return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedTriggerAction takes handle h, string label returns triggeraction return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedLightning takes handle h, string label returns lightning return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedImage takes handle h, string label returns image return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedUbersplat takes handle h, string label returns ubersplat return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedSound takes handle h, string label returns sound return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction function GetAttachedLoc takes handle h, string label returns location return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction //============================================================================================================ function CleanAttachedVars takes handle h returns nothing call FlushStoredMission(cs_cache,I2S(CS_H2I(h))) endfunction //! define CleanAttachedVars(h) FlushStoredMission(cs_cache,I2S(CS_H2I(h))) //============================================================================================================ // Left for compat function CleanAttachedVars_NoSets takes handle h returns nothing call FlushStoredMission(cs_cache,I2S(CS_H2I(h))) endfunction //! define CleanAttachedVars_NoSets(h) FlushStoredMission(cs_cache,I2S(CS_H2I(h))) //============================================================================================= // Tables // // Tables are lame, the real name would be hash tables, they are just abbreviated usage // of gamecache natives with the addition that you can also Copy the values of a table to // another one, but don't expect it to be automatic, it must use a FieldData object to know // which fields and of wich types to copy, Copying a table to another, with a lot of Fields, // should surelly be lag friendly. // // The other thing about tables is that I can say that the Attached variables of a handle work // inside a table and GetAttachmentTable which is just return bug and I2S , works to allow you // to manipulate a handle's attached variables through a table. // // NewTable and DestroyTable were created to allow to create tables in the fly, but you can // simply use strings for tables, but place the table names should be between "("")" for example // "(mytable)" to avoid conflicts with other caster system stuff. // function NewTableIndex takes nothing returns integer local integer loc=cs_freeindexes[0] local integer i if (loc!=0) then set i=GetPairX(loc) set cs_freeindexes[0]=GetPairY(loc) call DestroyPair(loc) return i endif set i=cs_array1[147]+1 set cs_array1[147]=i return i endfunction function NewTable takes nothing returns string local integer loc=cs_freeindexes[0] local integer i if (loc!=0) then set i=GetPairX(loc) set cs_freeindexes[0]=GetPairY(loc) call DestroyPair(loc) return I2S(i) endif set i=cs_array1[147]+1 set cs_array1[147]=i return I2S(i) endfunction function GetAttachmentTable takes handle h returns string return I2S(CS_H2I(h)) endfunction //! define GetAttachmentTable(h) I2S(CS_H2I(h)) //============================================================================================================ function DestroyTable takes string table returns nothing local integer i=S2I(table) local integer n call FlushStoredMission(cs_cache,table) if ((i>100) and (i<1000000)) then //All right, more than 1000000 tables is just wrong. if (i==cs_array1[147]) then set cs_array1[147]=cs_array1[147]-1 else set cs_freeindexes[0]= NewPair(i,cs_freeindexes[0]) endif endif endfunction //============================================================================================================ function ClearTable takes string table returns nothing call FlushStoredMission(cs_cache,table) endfunction //============================================================================================================ function SetTableInt takes string table, string field, integer val returns nothing if (val==0) then call FlushStoredInteger(cs_cache,table,field) else call StoreInteger(cs_cache,table,field,val) endif endfunction function GetTableInt takes string table, string field returns integer return GetStoredInteger(cs_cache,table,field) endfunction //! define GetTableInt(table,field) GetStoredInteger(cs_cache,table,field) //============================================================================================================ function SetTableReal takes string table, string field, real val returns nothing if (val==0) then call FlushStoredReal(cs_cache,table,field) else call StoreReal(cs_cache,table,field,val) endif endfunction function GetTableReal takes string table, string field returns real return GetStoredReal(cs_cache,table,field) endfunction //! define GetTableReal(table,field) GetStoredReal(cs_cache,table,field) //============================================================================================================ function SetTableBoolean takes string table, string field, boolean val returns nothing if (not(val)) then call FlushStoredBoolean(cs_cache,table,field) else call StoreBoolean(cs_cache,table,field,val) endif endfunction function GetTableBoolean takes string table, string field returns boolean return GetStoredBoolean(cs_cache,table,field) endfunction //! define GetTableBoolean(table,field) GetStoredBoolean(cs_cache,table,field) //============================================================================================================ function SetTableString takes string table, string field, string val returns nothing if (val=="") or (val==null) then call FlushStoredString(cs_cache,table,field) else call StoreString(cs_cache,table,field,val) endif endfunction function GetTableString takes string table, string field returns string return GetStoredString(cs_cache,table,field) endfunction //! define GetTableString(table,field) GetStoredString(cs_cache,table,field) //============================================================================================================ // You may ask why am I using thousands of functions instead of multi-use return bug exploiters? Well, // these make the thing much easier to read (in my opinion) and it is also better in performance since we // have less function calls (H2U(GetTableObject("table","unit"))) would be worse than GetTableUnit that is // quite direct. // function SetTableObject takes string table, string field, handle val returns nothing if (val==null) then call FlushStoredInteger(cs_cache,table,field) else call StoreInteger(cs_cache,table,field,CS_H2I(val)) endif endfunction function GetTableObject takes string table, string field returns handle return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableWidget takes string table, string field returns widget return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableRect takes string table, string field returns rect return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableRegion takes string table, string field returns region return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTimerDialog takes string table, string field returns timerdialog return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableUnit takes string table, string field returns unit return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableItem takes string table, string field returns item return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableEffect takes string table, string field returns effect return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableDestructable takes string table, string field returns destructable return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTrigger takes string table, string field returns trigger return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTimer takes string table, string field returns timer return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableGroup takes string table, string field returns group return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTriggerAction takes string table, string field returns triggeraction return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableLightning takes string table, string field returns lightning return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableImage takes string table, string field returns image return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableUbersplat takes string table, string field returns ubersplat return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableSound takes string table, string field returns sound return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableLoc takes string table, string field returns location return GetStoredInteger(cs_cache,table,field) return null endfunction //============================================================================================================ // Returns true if the fiel contains a value different from 0, false, null, or "" (depending on the type) // it is worthless to use this with boolean, since it would be the same as reading the boolean value // function HaveSetField takes string table, string field, integer fieldType returns boolean if (fieldType == bj_GAMECACHE_BOOLEAN) then return HaveStoredBoolean(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_INTEGER) then return HaveStoredInteger(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_REAL) then return HaveStoredReal(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_STRING) then return HaveStoredString(cs_cache,table,field) endif return false endfunction //============================================================================================================ // Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type // it is supposed to copy. // function CopyTable takes integer FieldData, string sourceTable, string destTable returns nothing local integer i=1 local string k=I2S(FieldData) local string k2 local string k3 local integer n=GetStoredInteger(cs_cache,k,"N") local integer t loop exitwhen (i>n) set k2=I2S(i) set t=GetStoredInteger(cs_cache,k,k2) set k3=GetStoredString(cs_cache,k,k2) if (t==bj_GAMECACHE_BOOLEAN) then if (HaveStoredBoolean(cs_cache,sourceTable,k3)) then call StoreBoolean(cs_cache,destTable,k3,GetStoredBoolean(cs_cache,sourceTable,k3)) else call FlushStoredBoolean(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_INTEGER) then if (HaveStoredInteger(cs_cache,sourceTable,k3)) then call StoreInteger(cs_cache,destTable,k3,GetStoredInteger(cs_cache,sourceTable,k3)) else call FlushStoredInteger(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_REAL) then if (HaveStoredReal(cs_cache,sourceTable,k3)) then call StoreReal(cs_cache,destTable,k3,GetStoredReal(cs_cache,sourceTable,k3)) else call FlushStoredReal(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_STRING) then if (HaveStoredString(cs_cache,sourceTable,k3)) then call StoreString(cs_cache,destTable,k3,GetStoredString(cs_cache,sourceTable,k3)) else call FlushStoredString(cs_cache,destTable,k3) endif endif set i=i+1 endloop endfunction //============================================================================================= // FieldData inherits from Table, was just designed to be used by CopyTable. // function FieldData_Create takes nothing returns integer return NewTableIndex() endfunction //! define FieldData_Create NewTableIndex //============================================================================================================ // valueType uses the same integer variables from blizzard.j : // bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING // function FieldData_AddField takes integer fielddata, string field, integer valueType returns nothing local string k=I2S(fielddata) local integer n=GetStoredInteger(cs_cache,k,"N")+1 local string k2=I2S(n) call StoreString(cs_cache,k,k2,field) call StoreInteger(cs_cache,k,k2,valueType) call StoreInteger(cs_cache,k,"N",n) endfunction //============================================================================================= // Destroys Field Data function FieldData_Destroy takes integer fielddata returns nothing call DestroyTable(I2S(fielddata)) endfunction //! define FieldData_Destroy(fielddata) DestroyTable(I2S(fielddata)) //============================================================================================= // Pools // // A better name for pools would be sets, but by the time I made them I couldn't think of that // name, besides the word set is already a JASS syntax word so it would have been problematic. // // Another naming failure is that values of a pool are called "items" but that conflicts with // the word item that points to wc3 items, Pools can only store integer values, but if you want // you can go and use the return bug on them. // function CreatePool takes nothing returns integer local integer i=NewArray(34,false) call SetArrayInt(i,0,0) return i endfunction function ClearPool takes integer poolid returns nothing call SetArrayInt(poolid,0,0) //[0:integer:n] call FlushStoredMission(cs_cache,I2S(-poolid)) endfunction function DestroyPool takes integer poolid returns nothing call DestroyArray(poolid) endfunction //! define DestroyPool(p) DestroyArray(p) function PoolAddItem takes integer poolid, integer value returns nothing local integer n local string k=I2S(-poolid) local string vk="#"+I2S(value) if not HaveStoredInteger(cs_cache,k,vk) then set n=GetArrayInt(poolid,0)+1 //[0:integer:N] call StoreInteger(cs_cache,k,vk,n) if (n>33) then call StoreInteger(cs_cache,k,I2S(n),value) else call SetArrayInt(poolid,n,value) endif call SetArrayInt(poolid,0,n) //[0:integer:N] endif endfunction function PoolRemoveItem takes integer poolid, integer value returns nothing local string k=I2S(-poolid) local string vk="#"+I2S(value) local integer p=GetStoredInteger(cs_cache,k,vk) local integer n if (p!=0) then set n=GetArrayInt(poolid,0) //[0:integer:N] call FlushStoredInteger( cs_cache, k, vk) if (n>p) then if (n>33) then set vk=I2S(n) set value=GetStoredInteger(cs_cache,k,vk) call FlushStoredInteger(cs_cache,k,vk) else set value=GetArrayInt(poolid,n) endif call StoreInteger(cs_cache,k,"#"+I2S(value),p) if (p>33) then call StoreInteger(cs_cache,k,I2S(p),value) else call SetArrayInt(poolid,p,value) endif elseif (p>33) then call FlushStoredInteger(cs_cache,k,I2S(p)) endif call SetArrayInt( poolid,0,n - 1) //[0:integer:N] endif endfunction //=================================================================================== function PoolGetItem takes integer poolid, integer itemn returns integer if (itemn>33) then return GetStoredInteger( cs_cache, I2S(-poolid), I2S(itemn)) endif return GetArrayInt(poolid,itemn) endfunction //=================================================================================== function CountItemsInPool takes integer poolid returns integer return GetArrayInt(poolid,0) //[0:integer:N] endfunction //! define CountItemsInPool(p) GetArrayInt(p,0) //=================================================================================== // Removed : GetEnumPoolItem , ForPool and ForPool2 they are much worse than just // using CountItemsInPool and PoolGetItem to iterate the pool // //=================================================================================== function GetFirstOfPool takes integer poolid returns integer return GetArrayInt(poolid,1) //[1 is just the first of the pool] endfunction //! define GetFirstOfPool(p) GetArrayInt(p,1) //=================================================================================== function PoolPickRandomItem takes integer poolid returns integer local integer p=GetRandomInt( 1, GetArrayInt(poolid,0) ) if (p>33) then return GetStoredInteger( cs_cache, I2S(-poolid), I2S(p)) endif return GetArrayInt(poolid,p) endfunction //=================================================================================== function GetItemPositionInPool takes integer poolid, integer it returns integer return GetStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) endfunction //! define GetItemPositionInPool(p,i) GetStoredInteger( cs_cache, I2S(- (p) ), "#"+I2S(i)) //=================================================================================== function IsItemInPool takes integer poolid, integer it returns boolean return(HaveStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) ) endfunction //! define IsItemInPool(p,i) HaveStoredInteger( cs_cache, I2S(- (p) ), "#"+I2S(i)) //=================================================================================== // This had to be optimized for speed, if it was just a loop using the above functions // that would have been too slow to be worth keeping. That's a bad thing about JASS // it is such an slow language that code reusability always has the cost of speed // function PoolAddPool takes integer sourcepoolid, integer destpoolid returns nothing local integer a=1 local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N] local integer dn=GetArrayInt( destpoolid,0) //[0:integer:N] local string sk=I2S(-sourcepoolid) local string k=I2S(-destpoolid) local integer v local string vk loop exitwhen (a>n) if (a>33) then set v=GetStoredInteger(cs_cache,sk,I2S(a)) else set v=GetArrayInt(sourcepoolid,a) endif set vk="#"+I2S(v) if not HaveStoredInteger(cs_cache,k,vk) then set dn=dn+1 call StoreInteger(cs_cache,k,vk,dn) if (dn>33) then call StoreInteger(cs_cache,k,I2S(dn),v) else call SetArrayInt(destpoolid,dn,v) endif endif set a=a+1 endloop call SetArrayInt(destpoolid,0,dn) //[0:integer:N] endfunction //============================================================================================= // Oh darn, After making PoolAddPool I don't feel like writting this one // All right I am at least make the get code // function PoolRemovePool takes integer sourcepoolid, integer destpoolid returns nothing local integer a=1 local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N] local integer v local string sk=I2S(-sourcepoolid) loop exitwhen a>n if (a>33) then set v=GetStoredInteger(cs_cache,sk,I2S(a) ) else set v=GetArrayInt(sourcepoolid,a) endif call PoolRemoveItem( destpoolid, v) set a=a+1 endloop endfunction //=================================================================================== // Adds a tokenized string to a pool, // Example: PoolAddS(udg_p, "1;2;3;4") will add to the udg_p pool : 1,2,3 and 4 // function PoolAddS takes integer poolid, string s returns nothing local integer i=0 local integer st local string c set s=s+";" set st=0 loop set c=SubString(s, i, i+1) exitwhen (c == "") or (c == null) if (c == ";") then call PoolAddItem( poolid, S2I(SubString(s, st, i)) ) set st=i+1 endif set i=i+1 endloop endfunction //=================================================================================== // Converts a tokenized string into a pool, // Example: S2Pool( "1;2;3;4") will return a pool that has 1,2,3 and 4 inside // function S2Pool takes string s returns integer local integer spool= CreatePool() call PoolAddS(spool,s) return spool endfunction //=================================================================================== // Does the opposite of S2Pool, debugging is a good use for this function. // function Pool2S takes integer P returns string local integer N=CountItemsInPool(P) local integer i local string s if (N>=1) then set s=I2S(PoolGetItem(P,1) ) set i=2 else return "" endif loop exitwhen (i>N) set s=s+";"+I2S(PoolGetItem(P,i)) set i=i+1 endloop return s endfunction //============================================================================================================= // Fixes a lame bug by blizzard related to the custom script section (The condition of the if statement might // actually be true. // function Pool_Percent takes nothing returns string if ("%"=="") then return "%%" endif return "%" endfunction function Pool_SetupCharMap takes nothing returns nothing local string cm=".................................!.#$"+Pool_Percent()+"&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................." local integer i=0 local string c if HaveStoredInteger(cs_cache,"charmap_upper","A") then return endif loop set c=SubString(cm,i,i+1) exitwhen (c==null) or (c=="") if (c!=".") then if c==StringCase(c,true) then call StoreInteger(cs_cache,"charmap_upper",c,i) else call StoreInteger(cs_cache,"charmap_lower",c,i) endif endif set i=i+1 endloop endfunction function Pool_Rawcode2Int takes string s returns integer local string c local integer i=0 local integer r=0 loop exitwhen i>3 set c=SubString(s,i,i+1) set r=r*256 if c==StringCase(c,true) then set r=r+GetStoredInteger(cs_cache,"charmap_upper",c) else set r=r+GetStoredInteger(cs_cache,"charmap_lower",c) endif set i=i+1 endloop return r endfunction function PoolAddRawcodes_thread takes nothing returns nothing //Threaded because I don't want it to halt execution for no reason // local string s=bj_lastPlayedMusic local integer poolid=bj_groupEnumTypeId local string c local integer i=0 local integer st=0 set s=s+";" loop set c=SubString(s, i, i+1) exitwhen (c == "") or (c == null) if c == ";" then call PoolAddItem(poolid, Pool_Rawcode2Int(SubString(s,st,i) )) set st=i+1 endif set i=i+1 endloop endfunction //===================================================================================================================== // Adds a string of tokenized rawcodes to a pool // Example: PoolAddRawcodes(udg_p,"A000;A001") will add 'A000' and 'A001' to the pool // // (Saves some lines, but is not as good efficiency wise) // function PoolAddRawcodes takes integer poolid, string s returns nothing local string b=bj_lastPlayedMusic set bj_groupEnumTypeId=poolid set bj_lastPlayedMusic=s call ExecuteFunc("PoolAddRawcodes_thread") set bj_lastPlayedMusic=b endfunction //=================================================================================================================== // Converts a tokenized string of rawcodes into a pool, // Example: Rawcodes2Pool( "A000;A001;AHbz;S000") will return a pool that has 'A000,'A001','AHbx' and 'S000' inside // // (Saves some lines, but is not as good efficiency wise) // function Rawcodes2Pool takes string s returns integer local integer spool= CreatePool() call PoolAddRawcodes(spool,s) return spool endfunction //=================================================================================================================== // A subproduct of the Pool's Rawcode support is that we can easily have this function so I am including it even if // it has nothing to do with data storage. // // takes "Aloc" and converts it into 'Aloc' // it is different to the Pool_Rawcode2Int function in that it is safe to use it when it is the first CSCache // function ever used. But it is a little slower (wc3mapoptimizer should make it as fast though) // function CS_Rawcode2Int takes string s returns integer local string c local integer i=0 local integer r=0 loop exitwhen i>3 set c=SubString(s,i,i+1) set r=r*256 if c==StringCase(c,true) then set r=r+GetStoredInteger(cs_cache,"charmap_upper",c) else set r=r+GetStoredInteger(cs_cache,"charmap_lower",c) endif set i=i+1 endloop return r endfunction function CSCache takes nothing returns gamecache return cs_cache //Left for compat. endfunction endlibrary //Forced by WE function InitTrig_CSCache takes nothing returns nothing endfunction JASS://##Begin of CS Gamecache engine## //================================================================================================= // GameCache - Return bug module : Without gamecache or return bug, JASS would be a // retarded-limited scripting language. // //================================================================================================= // a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems (I intended this // system to be easy to copy // function CS_H2I takes handle h returns integer return h return 0 endfunction //================================================================================================= // Main Gamecache handler // function CSCache takes nothing returns gamecache if udg_cscache==null then call FlushGameCache(InitGameCache("CasterSystem.vx")) set udg_cscache=InitGameCache("CasterSystem.vx") call StoreInteger(udg_cscache,"misc","TableMaxReleasedIndex",100) endif return udg_cscache endfunction //================================================================================================== // Attachable vars : Attacheable variables are what most other people call Handle Variables, they // allow to relate data with any handle, using a label, and its value, the stuff auto flushes if // the value is 0, false, "", or null . // // Differences between Attacheable variables and "Local Handle Variables" : // - The names of the functions // - The name of the function group does not cause confusion, it is difficult to say: // "you should set local handle variables to null at the end of a function" since // it sounds as if you were talking about the "Local Handle Variables" // - Also Have Attacheable Sets. // - And can work together with Tables. // // Notes: don't "attach" variables on texttags nor those handle types used mostly for parameters // (for example damagetype) , Although there is no reason to do so anyways // // Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!) // //============================================================================================================ // For integers // function AttachInt takes handle h, string label, integer x returns nothing local string k=I2S(CS_H2I(h)) if x==0 then call FlushStoredInteger(CSCache(),k,label) else call StoreInteger(CSCache(),k,label,x) endif endfunction function GetAttachedInt_FromSet takes handle h, gamecache g returns integer return GetStoredInteger(g,I2S(CS_H2I(h))+";"+GetStoredString(g,"argpass","set"),GetStoredString(g,"argpass","seti")) endfunction function GetAttachedInt takes handle h, string label returns integer if (label=="") then return GetAttachedInt_FromSet(h,CSCache()) endif return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label) endfunction //============================================================================================================= function AttachReal takes handle h, string label, real x returns nothing local string k=I2S(CS_H2I(h)) if x==0 then call FlushStoredReal(CSCache(),k,label) else call StoreReal(CSCache(),k,label,x) endif endfunction function GetAttachedReal takes handle h, string label returns real return GetStoredReal(CSCache(),I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachBoolean takes handle h, string label, boolean x returns nothing local string k=I2S(CS_H2I(h)) if not x then call FlushStoredBoolean(CSCache(),k,label) else call StoreBoolean(CSCache(),k,label,x) endif endfunction function GetAttachedBoolean takes handle h, string label returns boolean return GetStoredBoolean(CSCache(),I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachString takes handle h, string label, string x returns nothing local string k=I2S(CS_H2I(h)) if x=="" then call FlushStoredString(CSCache(),k,label) else call StoreString(CSCache(),k,label,x) endif endfunction function GetAttachedString takes handle h, string label returns string return GetStoredString(CSCache(),I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachObject takes handle h, string label, handle x returns nothing local string k=I2S(CS_H2I(h)) if (x==null) then call FlushStoredInteger(CSCache(),k,label) else call StoreInteger(CSCache(),k,label,CS_H2I(x)) endif endfunction function GetAttachedObject takes handle h, string label returns handle return GetAttachedInt(h,label) return null endfunction function GetAttachedWidget takes handle h, string label returns widget return GetAttachedInt(h,label) return null endfunction function GetAttachedRect takes handle h, string label returns rect return GetAttachedInt(h,label) return null endfunction function GetAttachedRegion takes handle h, string label returns region return GetAttachedInt(h,label) return null endfunction function GetAttachedTimerDialog takes handle h, string label returns timerdialog return GetAttachedInt(h,label) return null endfunction function GetAttachedUnit takes handle h, string label returns unit return GetAttachedInt(h,label) return null endfunction function GetAttachedItem takes handle h, string label returns item return GetAttachedInt(h,label) return null endfunction function GetAttachedEffect takes handle h, string label returns effect return GetAttachedInt(h,label) return null endfunction function GetAttachedDestructable takes handle h, string label returns destructable return GetAttachedInt(h,label) return null endfunction function GetAttachedTrigger takes handle h, string label returns trigger return GetAttachedInt(h,label) return null endfunction function GetAttachedTimer takes handle h, string label returns timer return GetAttachedInt(h,label) return null endfunction function GetAttachedGroup takes handle h, string label returns group return GetAttachedInt(h,label) return null endfunction function GetAttachedTriggerAction takes handle h, string label returns triggeraction return GetAttachedInt(h,label) return null endfunction function GetAttachedLightning takes handle h, string label returns lightning return GetAttachedInt(h,label) return null endfunction function GetAttachedImage takes handle h, string label returns image return GetAttachedInt(h,label) return null endfunction function GetAttachedUbersplat takes handle h, string label returns ubersplat return GetAttachedInt(h,label) return null endfunction function GetAttachedSound takes handle h, string label returns sound return GetAttachedInt(h,label) return null endfunction //============================================================================================================ // Attached Sets: Attachable Sets are handy in some situations and are a part of attachable variables, // you can add integers or objects to a set, order doesn't matter and adding the same object twice is // meaningless. CleanAttachedVars is always ready to clean every set owned by the handle. // //============================================================================================================ function AttachedSetAddInt takes handle h, string setn, integer int returns nothing local gamecache g=CSCache() local string k=I2S(CS_H2I(h)) local integer n local integer x=GetStoredInteger(g,k,"#setnumberof;"+setn) local integer y if x==0 then set y=GetStoredInteger(g,k,"#totalsets")+1 call StoreInteger(g,k,"#totalsets",y) call StoreInteger(g,k,"#setnumberof;"+setn,y) call StoreString(g,k,"#setName;"+I2S(y),setn) endif set k=k+";"+setn if not HaveStoredInteger(g,k,"Pos"+I2S(int)) then set n=GetStoredInteger(g,k,"n")+1 call StoreInteger(g,k,"n",n) call StoreInteger(g,k,I2S(n),int) call StoreInteger(g,k,"Pos"+I2S(int),n) endif set g=null endfunction function AttachedSetAddObject takes handle h, string setn, handle val returns nothing call AttachedSetAddInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function AttachedSetHasInt takes handle h, string setn, integer int returns boolean return HaveStoredInteger(CSCache(),I2S(CS_H2I(h))+";"+setn,"Pos"+I2S(int)) endfunction function AttachedSetHasObject takes handle h, string setn, handle val returns boolean return AttachedSetHasInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function GetAttachedSetSize takes handle h, string setn returns integer return GetStoredInteger(CSCache(),I2S(CS_H2I(h))+";"+setn,"n") endfunction //============================================================================================================ function AttachedSetRemInt takes handle h, string setn, integer int returns nothing local gamecache g=CSCache() local string k=I2S(CS_H2I(h))+";"+setn local integer n local integer x local integer y if HaveStoredInteger(g,k,"Pos"+I2S(int)) then set x=GetStoredInteger(g,k,"Pos"+I2S(int)) set n=GetStoredInteger(g,k,"n") if x!=n then set y=GetStoredInteger(g,k,I2S(n)) call StoreInteger(g,k,I2S(x),y) call StoreInteger(g,k,"Pos"+I2S(y),x) endif call FlushStoredInteger(g,k,"Pos"+I2S(int)) call FlushStoredInteger(g,k,I2S(n)) call StoreInteger(g,k,"n",n-1) endif set g=null endfunction function AttachedSetRemObject takes handle h, string setn, handle val returns nothing call AttachedSetRemInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function FromSetElement takes string setn, integer index returns string local gamecache g=CSCache() call StoreString(g,"argpass","set",setn) call StoreString(g,"argpass","seti",I2S(index)) set g=null return "" endfunction //============================================================================================================ function ClearAttachedSet takes handle h, string setn returns nothing call FlushStoredMission(CSCache(),I2S(CS_H2I(h))+";"+setn) endfunction function CleanAttachedVars takes handle h returns nothing local gamecache g=CSCache() local string k=I2S(CS_H2I(h)) local integer n=GetStoredInteger(g,k,"#totalsets") local integer i=1 loop exitwhen i>n call FlushStoredMission(g,k+";"+GetStoredString(g,k,"#setName;"+I2S(i))) set i=i+1 endloop call FlushStoredMission(g, k ) set g=null endfunction function CleanAttachedVars_NoSets takes handle h returns nothing call FlushStoredMission(CSCache(), I2S(CS_H2I(h)) ) endfunction //============================================================================================= // Tables // // Tables are lame, the real name would be hash tables, they are just abbreviated usage // of gamecache natives with the addition that you can also Copy the values of a table to // another one, but don't expect it to be automatic, it must use a FieldData object to know // which fields and of wich types to copy, Copying a table to another, with a lot of Fields, // should surelly be lag friendly. // // The other thing about tables is that I can say that the Attached variables of a handle work // inside a table and GetAttachmentTable which is just return bug and I2S , works to allow you // to manipulate a handle's attached variables through a table. // // NewTable and DestroyTable were created to allow to create tables in the fly, but you can // simply use strings for tables, but place the table names should be between "("")" for example // "(mytable)" to avoid conflicts with other caster system stuff. // function NewTableIndex takes nothing returns integer local gamecache g=CSCache() local integer n=GetStoredInteger(g,"misc","FreeTableTotal") local integer i if (n>0) then set i=GetStoredInteger(g,"misc","FreeTable1") if (n>1) then call StoreInteger(g,"misc","FreeTable1", GetStoredInteger(g,"misc","FreeTable"+I2S(n)) ) call FlushStoredInteger(g,"misc","FreeTable"+I2S(n)) endif call StoreInteger(g,"misc","FreeTableTotal", n-1) else set i=GetStoredInteger(g,"misc","TableMaxReleasedIndex")+1 call StoreInteger(g,"misc","TableMaxReleasedIndex",i) endif call StoreBoolean(g,"misc","Created"+I2S(i),true) set g=null return i endfunction function NewTable takes nothing returns string return I2S(NewTableIndex()) endfunction function GetAttachmentTable takes handle h returns string return I2S(CS_H2I(h)) endfunction //============================================================================================================ function DestroyTable takes string table returns nothing local gamecache g=CSCache() local integer i=S2I(table) local integer n if (i!=0) and (GetStoredBoolean(g,"misc","Created"+table)) then call FlushStoredBoolean(g,"misc","Created"+table) set n=GetStoredInteger(g,"misc","FreeTableTotal")+1 call StoreInteger(g,"misc","FreeTableTotal",n) call StoreInteger(g,"misc","FreeTable"+I2S(n),i) endif call FlushStoredMission(g,table) set g=null endfunction //============================================================================================================ function ClearTable takes string table returns nothing call FlushStoredMission(CSCache(),table) endfunction //============================================================================================================ function SetTableInt takes string table, string field, integer val returns nothing local gamecache g=CSCache() if (val==0) then call FlushStoredInteger(g,table,field) else call StoreInteger(g,table,field,val) endif set g=null endfunction function GetTableInt takes string table, string field returns integer return GetStoredInteger(CSCache(),table,field) endfunction //============================================================================================================ function SetTableReal takes string table, string field, real val returns nothing local gamecache g=CSCache() if (val==0) then call FlushStoredReal(g,table,field) else call StoreReal(g,table,field,val) endif set g=null endfunction function GetTableReal takes string table, string field returns real return GetStoredReal(CSCache(),table,field) endfunction //============================================================================================================ function SetTableBoolean takes string table, string field, boolean val returns nothing local gamecache g=CSCache() if (not(val)) then call FlushStoredBoolean(g,table,field) else call StoreBoolean(g,table,field,val) endif set g=null endfunction function GetTableBoolean takes string table, string field returns boolean return GetStoredBoolean(CSCache(),table,field) endfunction //============================================================================================================ function SetTableString takes string table, string field, string val returns nothing local gamecache g=CSCache() if (val=="") or (val==null) then call FlushStoredString(g,table,field) else call StoreString(g,table,field,val) endif set g=null endfunction function GetTableString takes string table, string field returns string return GetStoredString(CSCache(),table,field) endfunction //============================================================================================================ // You may ask why am I using thousands of functions instead of multi-use return bug exploiters? Well, // these make the thing much easier to read (in my opinion) and it is also better in performance since we // have less function calls (H2U(GetTableObject("table","unit"))) would be worse than GetTableUnit that is // quite direct. // function SetTableObject takes string table, string field, handle val returns nothing local gamecache g=CSCache() if (val==null) then call FlushStoredInteger(g,table,field) else call StoreInteger(g,table,field,CS_H2I(val)) endif set g=null endfunction function GetTableObject takes string table, string field returns handle return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableWidget takes string table, string field returns widget return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableRect takes string table, string field returns rect return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableRegion takes string table, string field returns region return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableTimerDialog takes string table, string field returns timerdialog return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableUnit takes string table, string field returns unit return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableItem takes string table, string field returns item return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableEffect takes string table, string field returns effect return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableDestructable takes string table, string field returns destructable return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableTrigger takes string table, string field returns trigger return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableTimer takes string table, string field returns timer return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableGroup takes string table, string field returns group return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableTriggerAction takes string table, string field returns triggeraction return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableLightning takes string table, string field returns lightning return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableImage takes string table, string field returns image return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableUbersplat takes string table, string field returns ubersplat return GetStoredInteger(CSCache(),table,field) return null endfunction function GetTableSound takes string table, string field returns sound return GetStoredInteger(CSCache(),table,field) return null endfunction //============================================================================================================ // Returns true if the fiel contains a value different from 0, false, null, or "" (depending on the type) // it is worthless to use this with boolean, since it would be the same as reading the boolean value // function HaveSetField takes string table, string field, integer fieldType returns boolean if (fieldType == bj_GAMECACHE_BOOLEAN) then return HaveStoredBoolean(CSCache(),table,field) elseif (fieldType == bj_GAMECACHE_INTEGER) then return HaveStoredInteger(CSCache(),table,field) elseif (fieldType == bj_GAMECACHE_REAL) then return HaveStoredReal(CSCache(),table,field) elseif (fieldType == bj_GAMECACHE_STRING) then return HaveStoredString(CSCache(),table,field) endif return false endfunction //============================================================================================================ // Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type // it is supposed to copy. // function CopyTable takes integer FieldData, string sourceTable, string destTable returns nothing local gamecache g=CSCache() local integer i=1 local string k=I2S(FieldData) local string k2 local string k3 local integer n=GetStoredInteger(g,k,"N") local integer t loop exitwhen (i>n) set k2=I2S(i) set t=GetStoredInteger(g,k,k2) set k3=GetStoredString(g,k,k2) if (t==bj_GAMECACHE_BOOLEAN) then if (HaveStoredBoolean(g,sourceTable,k3)) then call StoreBoolean(g,destTable,k3,GetStoredBoolean(g,sourceTable,k3)) else call FlushStoredBoolean(g,destTable,k3) endif elseif (t==bj_GAMECACHE_INTEGER) then if (HaveStoredInteger(g,sourceTable,k3)) then call StoreInteger(g,destTable,k3,GetStoredInteger(g,sourceTable,k3)) else call FlushStoredInteger(g,destTable,k3) endif elseif (t==bj_GAMECACHE_REAL) then if (HaveStoredReal(g,sourceTable,k3)) then call StoreReal(g,destTable,k3,GetStoredReal(g,sourceTable,k3)) else call FlushStoredReal(g,destTable,k3) endif elseif (t==bj_GAMECACHE_STRING) then if (HaveStoredString(g,sourceTable,k3)) then call StoreString(g,destTable,k3,GetStoredString(g,sourceTable,k3)) else call FlushStoredString(g,destTable,k3) endif endif set i=i+1 endloop set g=null endfunction //============================================================================================= // FieldData inherits from Table, was just designed to be used by CopyTable. // function FieldData_Create takes nothing returns integer return NewTableIndex() endfunction //============================================================================================================ // valueType uses the same integer variables from blizzard.j : // bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING // function FieldData_AddField takes integer fielddata, string field, integer valueType returns nothing local gamecache g=CSCache() local string k=I2S(fielddata) local integer n=GetStoredInteger(g,k,"N")+1 local string k2=I2S(n) call StoreString(g,k,k2,field) call StoreInteger(g,k,k2,valueType) call StoreInteger(g,k,"N",n) set g=null endfunction //============================================================================================= // Destroys Field Data function FieldData_Destroy takes integer fielddata returns nothing call DestroyTable(I2S(fielddata)) endfunction //##End of CS Gamecache engine## Once again, THANKS!!! |
| 09-04-2007, 02:25 PM | #4 |
I have not even compiled it, expect bugs since it is the first try JASS:library CSCache initializer InitCSCache //*************************************************************************** //* * //* CSCache 14.3+attachedsets http://wc3campaigns.net/vexorian * //* ¯¯¯¯¯¯¯ * //* From attach variables to Dynamic Arrays, not forgetting the tables, * //* CSData and the Pools, this is a pack of storage options * //* * //*************************************************************************** //================================================================================================= // CSCache globals: // globals gamecache cs_cache = null integer array cs_array1 integer array cs_array3 integer array cs_array2 integer array cs_freeindexes integer array cs_pairx integer array cs_pairy integer array cs_freepairs gamecache udg_cscache = null //udg_ for compat! endglobals //================================================================================================= // Note: //! define macro commands are used accross the script, they are usually to be parsed by // WEHelper, no //! define parser is really required, but if present it would improve the // performance of some calls. // //================================================================================================= // a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems (I intended this // system to be easy to copy // function CS_H2I takes handle h returns integer return h return 0 endfunction //================================================================================================== // Bunch of other return bug exploiters // function CS_i2r takes integer i returns real return i return 0. endfunction function CS_h2r takes handle h returns real return h return 0. endfunction function CS_r2i takes real r returns integer return r return 0 endfunction function CS_lx takes location l returns location return GetLocationX(l) return null endfunction function CS_ly takes location l returns location return GetLocationY(l) return null endfunction function CS_i2l takes integer l returns location return l return null endfunction //================================================================================================== // location linked list kit // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Thanks: Pipedream | No thanks: Blizzard (for lame bug) // // It is a great irony, but locations are only useful when you don't use them as points but as // structs thanks to the return bug. They only allow 2 values so they are limited in comparission // to gamecache and arrays (see bellow) still useful for single linked lists. // // These functions are what I call enough to use locations as single list nodes, X holds values and // Y can just hold a location (or real) . The Get functions use bj globals to fix an odd operator // bug that can happen after converting pointer to real into pointer to integer. // // The Set functions can be replaced by the Location() constructor, the MoveLocation() native and // the return bug exploiters up there. // //=================================================================================================== // Constructors // function Location_IntLoc takes integer x , location y returns location return Location(CS_i2r(x),CS_h2r(y)) endfunction //! define Location_IntLoc(x,y) Location(CS_i2r(x),CS_h2r(y)) function Location_ObjectLoc takes handle x , location y returns location return Location(CS_h2r(x),CS_h2r(y)) endfunction //! define Location_ObjectLoc(x,y) Location(CS_h2r(x),CS_h2r(y)) function Location_LocLoc takes handle x , location y returns location return Location(CS_h2r(x),CS_h2r(y)) endfunction //! define Location_LocLoc(x,y) Location(CS_h2r(x),CS_h2r(y)) function Location_RealLoc takes real x , location y returns location return Location(x,CS_h2r(y)) endfunction //! define Location_RealLoc(x,y) Location(x,CS_h2r(y)) //==================================================================================================== // Combined assigments // function SetLocation_IntLoc takes location loc, integer x , location y returns nothing call MoveLocation(loc,CS_i2r(x),CS_h2r(y)) endfunction //! define SetLocation_IntLoc(loc,x,y) MoveLocation(loc,CS_i2r(x),CS_h2r(y)) function SetLocation_ObjectLoc takes location loc, handle x , location y returns nothing call MoveLocation(loc,CS_h2r(x),CS_h2r(y)) endfunction //! define SetLocation_ObjectLoc(loc,x,y) MoveLocation(loc,CS_h2r(x),CS_h2r(y)) function SetLocation_LocLoc takes location loc, handle x , location y returns nothing //Funny name call MoveLocation(loc,CS_h2r(x),CS_h2r(y)) endfunction //! define SetLocation_LocLoc(loc,x,y) MoveLocation(loc,CS_h2r(x),CS_h2r(y)) function SetLocation_RealLoc takes location loc, real x , location y returns nothing call MoveLocation(loc,x,CS_h2r(y)) endfunction //! define SetLocation_RealLoc(loc,x,y) MoveLocation(loc,x,CS_h2r(y)) //=================================================================================================== // Lack of SetLocationX / SetLocationY natives is kind of lame // function SetLocationX_Object takes location loc, handle val returns nothing call MoveLocation(loc,CS_h2r(val),GetLocationY(loc)) endfunction // Notice how define SetLocationX_Object(loc,v) MoveLocation(loc,CS_h2r(v),GetLocationY(loc)) // would have a chance of messing sometimes since it has 2 loc in the result. function SetLocationX_Loc takes location loc, location val returns nothing //just name candy call MoveLocation(loc,CS_h2r(val),GetLocationY(loc)) endfunction function SetLocationX_Real takes location loc, real val returns nothing call MoveLocation(loc,val,GetLocationY(loc)) endfunction function SetLocationX_Int takes location loc, integer val returns nothing call MoveLocation(loc,CS_i2r(val),GetLocationY(loc)) endfunction function SetLocationY_Loc takes location loc, location val returns nothing call MoveLocation(loc,GetLocationX(loc),CS_h2r(val)) endfunction //================================================================================================== // All right, crazyness that started with Attacheable variables, and had to continue with everything // from tables, arrays and now this. Sorry I can't help itç // // The good thing about these functions is that they are safe, you won't deal with real->(int/handle) // conversion related bugs thanks to the use of bj variables these functions do // function GetLocationX_Loc takes location loc returns location set bj_enumDestructableCenter=CS_lx(loc) return bj_enumDestructableCenter endfunction function GetLocationY_Loc takes location loc returns location set bj_enumDestructableCenter=CS_ly(loc) return bj_enumDestructableCenter endfunction function GetLocationX_Int takes location loc returns integer set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex endfunction function GetLocationX_Unit takes location loc returns unit set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Item takes location loc returns item set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Effect takes location loc returns effect set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Lightning takes location loc returns lightning set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Widget takes location loc returns widget set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Object takes location loc returns handle set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Rect takes location loc returns rect set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Region takes location loc returns region set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_TimerDialog takes location loc returns timerdialog set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Destructable takes location loc returns destructable set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Trigger takes location loc returns trigger set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Timer takes location loc returns timer set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Group takes location loc returns group set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_TriggerAction takes location loc returns triggeraction set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Image takes location loc returns image set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Ubersplat takes location loc returns ubersplat set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Sound takes location loc returns sound set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction // //That should be all we needed to abuse Locations, Love lists. // // CSCache initializer : function InitCSCache takes nothing returns nothing call FlushGameCache(InitGameCache("cscache")) set cs_cache=InitGameCache("cscache") set udg_cscache = cs_cache call ExecuteFunc("InitArrayIndexes") call ExecuteFunc("Pool_SetupCharMap") endfunction //================================================================================================== // CSData // ¯¯¯¯¯¯ // CSDatas are like UserData in units and items, they are faster than gamecache unless you have more // than 8191 handles in your map. In that case it would be a little slower but only for those // handles. And if you have more than 8191 handles your map is too slow already anyways. // // Notice that for public spells or systems to be distributed you should only use these // for private objects (those who the mapper would never have access to) If you are making something // for your map you can use them wherever you want. // // Best to be used in conjunction to CSArrays so you just specify an array id for a handle. // // DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag, // -any 'argument' handle (like playerstate, damagetype, etc) // function SetCSData takes handle h, integer v returns nothing local integer i=CS_H2I(h)-0x100000 if (i>=8191) then call StoreInteger(cs_cache,"csdata",I2S(i),v) else set cs_array3[i]=v endif endfunction function GetCSData takes handle h returns integer local integer i=CS_H2I(h)-0x100000 if (i>=8191) then //can't use Get without Set return GetStoredInteger(cs_cache,"csdata",I2S(i)) endif return cs_array3[i] endfunction //================================================================================================================= // CS Pairs // ¯¯¯¯¯¯¯¯ // This is a sub system to assist csarrays, you can use them but CSArrays of size 2 have the same functionality // although cspairs are be faster their space is limited and will start using gamecache if abused // function NewPair takes integer x, integer y returns integer local integer i if (cs_freepairs[0]==0) then set cs_freepairs[8190]=cs_freepairs[8190]+1 set i= cs_freepairs[8190] else set i= cs_freepairs[cs_freepairs[0]] set cs_freepairs[0]=cs_freepairs[0]-1 endif if (i>=8189) then //because we can only recycle up to 8189 (free pairs array uses indexes 0 and 8190 for other purposes) call StoreInteger(cs_cache,"pairx",I2S(i),x) call StoreInteger(cs_cache,"pairy",I2S(i),y) else set cs_pairx[i]=x set cs_pairy[i]=y endif return i endfunction function DestroyPair takes integer id returns nothing if (id>=8189) then call FlushStoredInteger(cs_cache,"pairx",I2S(id)) call FlushStoredInteger(cs_cache,"pairy",I2S(id)) else set cs_freepairs[0]=cs_freepairs[0]+1 set cs_freepairs[cs_freepairs[0]] = id endif endfunction function SetPairXY takes integer id, integer x, integer y returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairx",I2S(id),x) call StoreInteger(cs_cache,"pairy",I2S(id),y) else set cs_pairx[id]=x set cs_pairy[id]=y endif endfunction function SetPairX takes integer id, integer x returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairx",I2S(id),x) else set cs_pairx[id]=x endif endfunction function SetPairY takes integer id, integer y returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairy",I2S(id),y) else set cs_pairy[id]=y endif endfunction function GetPairX takes integer id returns integer if (id>=8189) then return GetStoredInteger(cs_cache,"pairy",I2S(id)) endif return cs_pairx[id] endfunction function GetPairY takes integer id returns integer if (id>=8189) then return GetStoredInteger(cs_cache,"pairx",I2S(id)) endif return cs_pairy[id] endfunction //================================================================================================================= // CS Dynamic Arrays // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Thanks: Pipedream, Peppar // // We can now create arrays in game! , also pass them as arguments or return values! // a 1 length array is a pointer! // function Array_TryFree takes nothing returns nothing local integer i local integer N=cs_array1[0] local integer k local boolean cleaned=false local integer loc local integer q local integer r set i=cs_array1[146] if (i>144) then call TimerStart(GetExpiredTimer(),60.,false,function Array_TryFree) return endif set loc=cs_freeindexes[i] set q=0 loop exitwhen (loc==0) // we could just have used: //set k=GetPairX(loc) //set r=GetPairY(loc) But it is slower than direct usage: if (loc>=8192) then set k=GetStoredInteger(cs_cache,"pairx",I2S(loc)) set r=GetStoredInteger(cs_cache,"pairy",I2S(loc)) else set k=cs_pairx[loc] set r=cs_pairy[loc] endif if (k+i-1==N) then //we found one we can remove from the list set cleaned=true //decrement N set N=k-2 //Remove from the list: if (q==null) then //That was the first, update the array as well set cs_freeindexes[i]=r else //Update the next of the previous one //We could use : call SetPairY(q,,r) but it is slower if (q>=8189) then call StoreInteger(cs_cache,"pairy",I2S(q),r) else set cs_pairy[q]=r endif endif if (r==null) then //This was the last one, update it in the array as well set cs_freeindexes[i+4096]=q endif call DestroyPair(loc) set loc=q endif set q=loc set loc=r endloop if (cleaned) then set cs_array1[0]=N set cs_array1[146]=1 else set cs_array1[146]=cs_array1[i+1] endif call TimerStart(GetExpiredTimer(),0.2,false,function Array_TryFree) endfunction function InitArrayIndexes2 takes nothing returns nothing local integer i=0 loop exitwhen (i==8191) set cs_pairx[i]=777 set cs_pairy[i]=777 set i=i+1 endloop endfunction function InitArrayIndexes takes nothing returns nothing local integer i=0 local integer a=1 local integer b=1 local integer c //By placing 777 there instead of 0 it is easier to recognize non correctly initialized bugs loop exitwhen (i== 8191) set cs_array1[i]=777 set cs_array2[i]=777 set cs_array3[i]=777 //set cs_pairx[i]=777 //set cs_pairy[i]=777 set i=i+1 endloop call ExecuteFunc("InitArrayIndexes2") set cs_freeindexes[0]=0 //The stack for the table indexes. set cs_freepairs[0]=0 set cs_freepairs[8190]=0 set i=1 loop set c=a+b set a=b set b=c exitwhen (b>144) //max size is 144 set cs_freeindexes[b]=0 //the first of the list set cs_freeindexes[b+4096]=0 //the last of the list loop exitwhen (i>b) set cs_array1[i]=b set i=i+1 endloop endloop set cs_array1[i]=b //i is 145 set cs_array1[146]=1 set cs_array1[147]=101 //initial table index is 101 set cs_array1[0]=147 //index 0: Last used index // 1 to 145 : Fibonacci sequence // 146 : last check // 147 : Table indexes check //This has a good chance to compress the thing when necesary call TimerStart(CreateTimer(),60.,false,function Array_TryFree) endfunction //============================================================================================= // Create an array of size, max size is 144, if doinit is true it will put a bunch of zeros // in the indexes // function NewArray takes integer size, boolean doinit returns integer local integer i local integer rsize=cs_array1[size] local integer loc set loc=cs_freeindexes[rsize] if (loc!=0) then set cs_freeindexes[rsize]= GetPairY(loc) if (cs_freeindexes[rsize]==0) then set cs_freeindexes[4096+rsize]=0 endif set i=GetPairX(loc) call DestroyPair(loc) if (i==0) then //this code was probably a good idea when we used locations for the free indexes list, now we use pairs which should not ever //do this unless someone modiffied the pair array incorrectly call BJDebugMsg("Caster System: Unexpected error (5): corrupt stack, attempt to recover "+I2S(rsize)) // recovering involves forgetting about the stack which got corrupted and start again from zero, it will leak // and probably get slow due to usage of gamecache but it is better than the problems that a corrupt stack might cause set cs_freeindexes[rsize]=0 set cs_freeindexes[4096+rsize]=0 return NewArray(size,doinit) endif else //sz i i+1 i+2 //[ ][ ][ ][ ] set i=cs_array1[0]+2 set cs_array1[0]=i+rsize-1 endif //It used to store size in the index equal to the array's id // but that required the get/set functions to increment 1 in every index // calculation. Instead, making size the previous index to the array works if (i<=8191) then set cs_array1[i-1]=size elseif (i<=16382) then set cs_array2[i-8192]=size else call StoreInteger(cs_cache,I2S(-i),"size",size) endif if (not doinit) then return i endif // 3 //[i][i+1][i+2] set size=i+size-1 if (size>=16382) then set size=16381 endif loop exitwhen (size<i) or (size<8191) set cs_array2[size-8191]=0 set size=size-1 endloop loop exitwhen (size<i) set cs_array1[size]=0 set size=size-1 endloop //call DisplayTextToPlayer(GetLocalPlayer(),0,0,I2S(i)) return i endfunction //=============================================================================================================== // Remember to destroy arrays when you no longer need them, else new arrays will get slower after a bunch of // arrays are active // function DestroyArray takes integer id returns nothing local integer L local integer loc // local string k=I2S(-id) local integer lstpace if (id<=8191) then set L=cs_array1[cs_array1[id-1]] elseif (id<=16382) then set L=cs_array1[cs_array2[id-8191]] else set L=cs_array1[GetStoredInteger(cs_cache,I2S(-id),"size")] //No way you are gonna call DestroyArray without calling //NewArray first, so we can use the gamecache variable directly instead endif set lstpace=id+L-1 call FlushStoredMission(cs_cache,I2S(-id)) if (lstpace>16382) then if (lstpace==cs_array1[0]) then //We just destroyed the array that happens to be at the end of the heap. //Just get it back set cs_array1[0]=id-2 set cs_array1[146]=1 else //Add to the last set loc=cs_freeindexes[L+4096] if (loc==0) then set loc=NewPair(id,0) set cs_freeindexes[L]=loc set cs_freeindexes[L+4096]=loc else set cs_freeindexes[L+4096]= NewPair(id,0) //we could just use: call SetPairY(loc, cs_freeindexes[L+4096] ) //but that's slower if (loc>=8189) then call StoreInteger(cs_cache,"pairy",I2S(loc), cs_freeindexes[L+4096] ) else set cs_pairy[loc]=cs_freeindexes[L+4096] endif endif endif elseif (lstpace==cs_array1[0]) then //We just destroyed the array that happens to be at the end of the heap. //Just get it back set cs_array1[0]=id-2 set cs_array1[146]=1 else set loc=cs_freeindexes[L] set cs_freeindexes[L]=NewPair(id,loc) if (loc==0) then set cs_freeindexes[L+4096]=cs_freeindexes[L] endif endif endfunction //================================================================================================================ // Int Set/Get array usage prototypes. // // These are the actual functions, the rest are just the result of copy paste, if these functions are updated // the other ones should be updated as well (They are just return bugged variations) // function SetArrayInt takes integer id, integer index, integer val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=val elseif (index<16382) then set cs_array2[index-8191]=val else call StoreInteger(cs_cache,I2S(-id),I2S(index),val) endif endfunction function GetArrayInt takes integer id, integer index returns integer set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) endfunction //================================================================================================================ // String Set/Get array // // Due String related return bug issues, these are forced to use gamecache // function SetArrayString takes integer id, integer index, string val returns nothing call StoreString(cs_cache,I2S(-id),I2S(index),val) endfunction function GetArrayString takes integer id, integer index returns string return GetStoredString(cs_cache,I2S(-id),I2S(index)) endfunction //(Boolean is not needed) //=================================================================================================== // Indexes of real types // function SetArrayReal takes integer id, integer index, real val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=CS_r2i(val) elseif (index<16382) then set cs_array2[index-8191]=CS_r2i(val) else call StoreInteger(cs_cache,I2S(-id),I2S(index),CS_r2i(val)) endif endfunction function GetArrayReal takes integer id, integer index returns real set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return 0.0 endfunction //=================================================================================================== // <Indexes of handle types> // function SetArrayObject takes integer id, integer index, handle val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=CS_H2I(val) elseif (index<16382) then set cs_array2[index-8191]=CS_H2I(val) else call StoreInteger(cs_cache,I2S(-id),I2S(index),CS_H2I(val)) endif endfunction // // //Yep, I am crazy. But These are FASTER than using the function and a return bug exploiter separatedly. function GetArrayObject takes integer id, integer index returns handle set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayWidget takes integer id, integer index returns widget set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTimer takes integer id, integer index returns timer set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayUnit takes integer id, integer index returns unit set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayLoc takes integer id, integer index returns location set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTrigger takes integer id, integer index returns trigger set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTriggerAction takes integer id, integer index returns triggeraction set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayGroup takes integer id, integer index returns group set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayEffect takes integer id, integer index returns effect set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayItem takes integer id, integer index returns item set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayLightning takes integer id, integer index returns lightning set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction //The rest are not used that much and they are a waste of space instead of a save of speed //most of the times. THEY ARE STILL MUCH FASTER THAN GAMECACHE function GetArrayRect takes integer id, integer index returns rect return GetArrayInt(id,index) return null endfunction function GetArrayRegion takes integer id, integer index returns region return GetArrayInt(id,index) return null endfunction function GetArrayTimerDialog takes integer id, integer index returns timerdialog return GetArrayInt(id,index) return null endfunction function GetArrayDestructable takes integer id, integer index returns destructable return GetArrayInt(id,index) return null endfunction function GetArrayImage takes integer id, integer index returns image return GetArrayInt(id,index) return null endfunction function GetArrayUbersplat takes integer id, integer index returns ubersplat return GetArrayInt(id,index) return null endfunction function GetArraySound takes integer id, integer index returns sound return GetArrayInt(id,index) return null endfunction // </Indexes of handle types> // The horror! // //========================================================================================================================== // Returns the size of an array (the specified by player one, not the actual size of it) should be useful. // function GetArraySize takes integer id returns integer if (id<=8191) then return cs_array1[id-1] elseif (id<=16382) then return cs_array2[id-8192] endif return GetStoredInteger(cs_cache,I2S(-id),"size") endfunction //=========================================================================================================================== // Returns an array that is an exact copy of the given array // function CloneArray takes integer id returns integer local integer sz local integer i local integer sz2 local integer x local integer y if (id<=8191) then set sz=cs_array1[id-1] elseif (id<=16382) then set sz=cs_array2[id-8192] else set sz=GetStoredInteger(cs_cache,I2S(-id),"size") //No way you are gonna call DestroyArray without calling //NewArray first, so we can use the gamecache variable directly instead endif set i=NewArray(sz,false) set sz2=i+sz-1 set sz=id+sz-1 set x=i set y=id loop exitwhen ((y>sz) or (y>=8191) or (x>=8191)) set cs_array1[x]=cs_array1[y] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=8191) or (x>=16382)) set cs_array2[x-8191]=cs_array1[y] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=8191)) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array1[y]) set x=y+1 set y=y+1 endloop //... loop exitwhen ((y>sz) or (y>=16382) or (x>=8191)) set cs_array1[x]=cs_array2[y-8191] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=16382) or (x>=16382)) set cs_array2[x-8191]=cs_array2[y-8191] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=16382)) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array2[y-8191]) set y=y+1 set x=x+1 endloop //... loop exitwhen ((y>sz) or (x>=8191)) set cs_array1[x]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)) set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (x>=16382)) set cs_array2[x-8191]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)) set y=y+1 set x=x+1 endloop loop exitwhen (y>sz) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))) set y=y+1 set x=x+1 endloop return i endfunction //================================================================================================== // Attachable vars : Attacheable variables are what most other people call Handle Variables, they // allow to relate data with any handle, using a label, and its value, the stuff auto flushes if // the value is 0, false, "", or null . // // Differences between Attacheable variables and "Local Handle Variables" : // - The names of the functions // - The name of the function group does not cause confusion, it is difficult to say: // "you should set local handle variables to null at the end of a function" since // it sounds as if you were talking about the "Local Handle Variables" // - And can work together with Tables. // // Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!) // // // Although locations and dynamic arrays are faster than gamecache, gamecache still keeps the flexibility // Best thing to do in my opinion is to combine these options. By combining you can acquire gamecache // flexibility and arrays/locs speed to solve a problem // //============================================================================================================ // For integers // function AttachInt takes handle h, string label, integer x returns nothing if x==0 then call FlushStoredInteger(cs_cache,I2S(CS_H2I(h)),label) else call StoreInteger(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction globals private string argpass_set="null" private string argpass_seti="null" endglobals function GetAttachedInt_FromSet takes handle h returns integer return GetStoredInteger(cs_cache,I2S(CS_H2I(h))+";"+argpass_set,argpass_seti) endfunction function GetAttachedInt takes handle h, string label returns integer if (label=="") then return GetAttachedInt_FromSet(h) endif return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label) endfunction //! textmacro GetAttached takes typename, type function GetAttached$typename$ takes handle h, string label return $type$ if (label=="") then return GetAttachedInt_FromSet(h) endif return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label) return null endfunction //! endtextmacro //============================================================================================================= function AttachReal takes handle h, string label, real x returns nothing if x==0 then call FlushStoredReal(cs_cache,I2S(CS_H2I(h)),label) else call StoreReal(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedReal takes handle h, string label returns real return GetStoredReal(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachBoolean takes handle h, string label, boolean x returns nothing if not x then call FlushStoredBoolean(cs_cache,I2S(CS_H2I(h)),label) else call StoreBoolean(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedBoolean takes handle h, string label returns boolean return GetStoredBoolean(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachString takes handle h, string label, string x returns nothing if ((x=="") or (x==null)) then call FlushStoredString(cs_cache,I2S(CS_H2I(h)),label) else call StoreString(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedString takes handle h, string label returns string return GetStoredString(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachObject takes handle h, string label, handle x returns nothing if (x==null) then call FlushStoredInteger(cs_cache,I2S(CS_H2I(h)),label) else call StoreInteger(cs_cache,I2S(CS_H2I(h)),label,CS_H2I(x)) endif endfunction //! runtextmacro GetAttached("Object","handle") //! runtextmacro GetAttached("Widget","widget") //! runtextmacro GetAttached("Rect","rect") //! runtextmacro GetAttached("Region","region") //! runtextmacro GetAttached("TimerDialog","timerdialog") //! runtextmacro GetAttached("Unit","unit") //! runtextmacro GetAttached("Item","item") //! runtextmacro GetAttached("Effect","effect") //! runtextmacro GetAttached("Destructable","destructable") //! runtextmacro GetAttached("Trigger","trigger") //! runtextmacro GetAttached("Timer","timer") //! runtextmacro GetAttached("Group","group") //! runtextmacro GetAttached("TriggerAction","triggeraction") //! runtextmacro GetAttached("Lightning","lightning") //! runtextmacro GetAttached("Image","image") //! runtextmacro GetAttached("Ubersplat","ubersplat") //! runtextmacro GetAttached("Sound","sound") //! runtextmacro GetAttached("Loc","location") //============================================================================================================ // Attached Sets: Attachable Sets are handy in some situations and are a part of attachable variables, // you can add integers or objects to a set, order doesn't matter and adding the same object twice is // meaningless. CleanAttachedVars is always ready to clean every set owned by the handle. // //============================================================================================================ function AttachedSetAddInt takes handle h, string setn, integer int returns nothing local string k=I2S(CS_H2I(h)) local integer n local integer x=GetStoredInteger(cs_cache,k,"#setnumberof;"+setn) local integer y if x==0 then set y=GetStoredInteger(cs_cache,k,"#totalsets")+1 call StoreInteger(cs_cache,k,"#totalsets",y) call StoreInteger(cs_cache,k,"#setnumberof;"+setn,y) call StoreString(cs_cache,k,"#setName;"+I2S(y),setn) endif set k=k+";"+setn if not HaveStoredInteger(cs_cache,k,"Pos"+I2S(int)) then set n=GetStoredInteger(cs_cache,k,"n")+1 call StoreInteger(cs_cache,k,"n",n) call StoreInteger(cs_cache,k,I2S(n),int) call StoreInteger(cs_cache,k,"Pos"+I2S(int),n) endif endfunction function AttachedSetAddObject takes handle h, string setn, handle val returns nothing call AttachedSetAddInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function AttachedSetHasInt takes handle h, string setn, integer int returns boolean return HaveStoredInteger(cs_cache,I2S(CS_H2I(h))+";"+setn,"Pos"+I2S(int)) endfunction function AttachedSetHasObject takes handle h, string setn, handle val returns boolean return AttachedSetHasInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function GetAttachedSetSize takes handle h, string setn returns integer return GetStoredInteger(cs_cache,I2S(CS_H2I(h))+";"+setn,"n") endfunction //============================================================================================================ function AttachedSetRemInt takes handle h, string setn, integer int returns nothing local string k=I2S(CS_H2I(h))+";"+setn local integer n local integer x local integer y if HaveStoredInteger(cs_cache,k,"Pos"+I2S(int)) then set x=GetStoredInteger(cs_cache,k,"Pos"+I2S(int)) set n=GetStoredInteger(cs_cache,k,"n") if x!=n then set y=GetStoredInteger(cs_cache,k,I2S(n)) call StoreInteger(cs_cache,k,I2S(x),y) call StoreInteger(cs_cache,k,"Pos"+I2S(y),x) endif call FlushStoredInteger(cs_cache,k,"Pos"+I2S(int)) call FlushStoredInteger(cs_cache,k,I2S(n)) call StoreInteger(cs_cache,k,"n",n-1) endif endfunction function AttachedSetRemObject takes handle h, string setn, handle val returns nothing call AttachedSetRemInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function FromSetElement takes string setn, integer index returns string set argpass_set=setn set argpass_seti=I2S(index) return "" endfunction //============================================================================================================ function ClearAttachedSet takes handle h, string setn returns nothing call FlushStoredMission(cs_cache,I2S(CS_H2I(h))+";"+setn) endfunction //============================================================================================================ function CleanAttachedVars takes handle h returns nothing local string k=I2S(CS_H2I(h)) local integer n=GetStoredInteger(cs_cache,k,"#totalsets") local integer i=1 loop exitwhen i>n call FlushStoredMission(cs_cache,k+";"+GetStoredString(g,k,"#setName;"+I2S(i))) set i=i+1 endloop call FlushStoredMission(cs_cache, k ) endfunction function CleanAttachedVars_NoSets takes handle h returns nothing call FlushStoredMission(cs_cache,I2S(CS_H2I(h))) endfunction //! define CleanAttachedVars_NoSets(h) FlushStoredMission(cs_cache,I2S(CS_H2I(h))) //============================================================================================= // Tables // // Tables are lame, the real name would be hash tables, they are just abbreviated usage // of gamecache natives with the addition that you can also Copy the values of a table to // another one, but don't expect it to be automatic, it must use a FieldData object to know // which fields and of wich types to copy, Copying a table to another, with a lot of Fields, // should surelly be lag friendly. // // The other thing about tables is that I can say that the Attached variables of a handle work // inside a table and GetAttachmentTable which is just return bug and I2S , works to allow you // to manipulate a handle's attached variables through a table. // // NewTable and DestroyTable were created to allow to create tables in the fly, but you can // simply use strings for tables, but place the table names should be between "("")" for example // "(mytable)" to avoid conflicts with other caster system stuff. // function NewTableIndex takes nothing returns integer local integer loc=cs_freeindexes[0] local integer i if (loc!=0) then set i=GetPairX(loc) set cs_freeindexes[0]=GetPairY(loc) call DestroyPair(loc) return i endif set i=cs_array1[147]+1 set cs_array1[147]=i return i endfunction function NewTable takes nothing returns string local integer loc=cs_freeindexes[0] local integer i if (loc!=0) then set i=GetPairX(loc) set cs_freeindexes[0]=GetPairY(loc) call DestroyPair(loc) return I2S(i) endif set i=cs_array1[147]+1 set cs_array1[147]=i return I2S(i) endfunction function GetAttachmentTable takes handle h returns string return I2S(CS_H2I(h)) endfunction //! define GetAttachmentTable(h) I2S(CS_H2I(h)) //============================================================================================================ function DestroyTable takes string table returns nothing local integer i=S2I(table) local integer n call FlushStoredMission(cs_cache,table) if ((i>100) and (i<1000000)) then //All right, more than 1000000 tables is just wrong. if (i==cs_array1[147]) then set cs_array1[147]=cs_array1[147]-1 else set cs_freeindexes[0]= NewPair(i,cs_freeindexes[0]) endif endif endfunction //============================================================================================================ function ClearTable takes string table returns nothing call FlushStoredMission(cs_cache,table) endfunction //============================================================================================================ function SetTableInt takes string table, string field, integer val returns nothing if (val==0) then call FlushStoredInteger(cs_cache,table,field) else call StoreInteger(cs_cache,table,field,val) endif endfunction function GetTableInt takes string table, string field returns integer return GetStoredInteger(cs_cache,table,field) endfunction //! define GetTableInt(table,field) GetStoredInteger(cs_cache,table,field) //============================================================================================================ function SetTableReal takes string table, string field, real val returns nothing if (val==0) then call FlushStoredReal(cs_cache,table,field) else call StoreReal(cs_cache,table,field,val) endif endfunction function GetTableReal takes string table, string field returns real return GetStoredReal(cs_cache,table,field) endfunction //! define GetTableReal(table,field) GetStoredReal(cs_cache,table,field) //============================================================================================================ function SetTableBoolean takes string table, string field, boolean val returns nothing if (not(val)) then call FlushStoredBoolean(cs_cache,table,field) else call StoreBoolean(cs_cache,table,field,val) endif endfunction function GetTableBoolean takes string table, string field returns boolean return GetStoredBoolean(cs_cache,table,field) endfunction //! define GetTableBoolean(table,field) GetStoredBoolean(cs_cache,table,field) //============================================================================================================ function SetTableString takes string table, string field, string val returns nothing if (val=="") or (val==null) then call FlushStoredString(cs_cache,table,field) else call StoreString(cs_cache,table,field,val) endif endfunction function GetTableString takes string table, string field returns string return GetStoredString(cs_cache,table,field) endfunction //! define GetTableString(table,field) GetStoredString(cs_cache,table,field) //============================================================================================================ // You may ask why am I using thousands of functions instead of multi-use return bug exploiters? Well, // these make the thing much easier to read (in my opinion) and it is also better in performance since we // have less function calls (H2U(GetTableObject("table","unit"))) would be worse than GetTableUnit that is // quite direct. // function SetTableObject takes string table, string field, handle val returns nothing if (val==null) then call FlushStoredInteger(cs_cache,table,field) else call StoreInteger(cs_cache,table,field,CS_H2I(val)) endif endfunction function GetTableObject takes string table, string field returns handle return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableWidget takes string table, string field returns widget return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableRect takes string table, string field returns rect return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableRegion takes string table, string field returns region return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTimerDialog takes string table, string field returns timerdialog return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableUnit takes string table, string field returns unit return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableItem takes string table, string field returns item return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableEffect takes string table, string field returns effect return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableDestructable takes string table, string field returns destructable return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTrigger takes string table, string field returns trigger return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTimer takes string table, string field returns timer return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableGroup takes string table, string field returns group return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTriggerAction takes string table, string field returns triggeraction return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableLightning takes string table, string field returns lightning return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableImage takes string table, string field returns image return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableUbersplat takes string table, string field returns ubersplat return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableSound takes string table, string field returns sound return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableLoc takes string table, string field returns location return GetStoredInteger(cs_cache,table,field) return null endfunction //============================================================================================================ // Returns true if the fiel contains a value different from 0, false, null, or "" (depending on the type) // it is worthless to use this with boolean, since it would be the same as reading the boolean value // function HaveSetField takes string table, string field, integer fieldType returns boolean if (fieldType == bj_GAMECACHE_BOOLEAN) then return HaveStoredBoolean(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_INTEGER) then return HaveStoredInteger(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_REAL) then return HaveStoredReal(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_STRING) then return HaveStoredString(cs_cache,table,field) endif return false endfunction //============================================================================================================ // Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type // it is supposed to copy. // function CopyTable takes integer FieldData, string sourceTable, string destTable returns nothing local integer i=1 local string k=I2S(FieldData) local string k2 local string k3 local integer n=GetStoredInteger(cs_cache,k,"N") local integer t loop exitwhen (i>n) set k2=I2S(i) set t=GetStoredInteger(cs_cache,k,k2) set k3=GetStoredString(cs_cache,k,k2) if (t==bj_GAMECACHE_BOOLEAN) then if (HaveStoredBoolean(cs_cache,sourceTable,k3)) then call StoreBoolean(cs_cache,destTable,k3,GetStoredBoolean(cs_cache,sourceTable,k3)) else call FlushStoredBoolean(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_INTEGER) then if (HaveStoredInteger(cs_cache,sourceTable,k3)) then call StoreInteger(cs_cache,destTable,k3,GetStoredInteger(cs_cache,sourceTable,k3)) else call FlushStoredInteger(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_REAL) then if (HaveStoredReal(cs_cache,sourceTable,k3)) then call StoreReal(cs_cache,destTable,k3,GetStoredReal(cs_cache,sourceTable,k3)) else call FlushStoredReal(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_STRING) then if (HaveStoredString(cs_cache,sourceTable,k3)) then call StoreString(cs_cache,destTable,k3,GetStoredString(cs_cache,sourceTable,k3)) else call FlushStoredString(cs_cache,destTable,k3) endif endif set i=i+1 endloop endfunction //============================================================================================= // FieldData inherits from Table, was just designed to be used by CopyTable. // function FieldData_Create takes nothing returns integer return NewTableIndex() endfunction //! define FieldData_Create NewTableIndex //============================================================================================================ // valueType uses the same integer variables from blizzard.j : // bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING // function FieldData_AddField takes integer fielddata, string field, integer valueType returns nothing local string k=I2S(fielddata) local integer n=GetStoredInteger(cs_cache,k,"N")+1 local string k2=I2S(n) call StoreString(cs_cache,k,k2,field) call StoreInteger(cs_cache,k,k2,valueType) call StoreInteger(cs_cache,k,"N",n) endfunction //============================================================================================= // Destroys Field Data function FieldData_Destroy takes integer fielddata returns nothing call DestroyTable(I2S(fielddata)) endfunction //! define FieldData_Destroy(fielddata) DestroyTable(I2S(fielddata)) //============================================================================================= // Pools // // A better name for pools would be sets, but by the time I made them I couldn't think of that // name, besides the word set is already a JASS syntax word so it would have been problematic. // // Another naming failure is that values of a pool are called "items" but that conflicts with // the word item that points to wc3 items, Pools can only store integer values, but if you want // you can go and use the return bug on them. // function CreatePool takes nothing returns integer local integer i=NewArray(34,false) call SetArrayInt(i,0,0) return i endfunction function ClearPool takes integer poolid returns nothing call SetArrayInt(poolid,0,0) //[0:integer:n] call FlushStoredMission(cs_cache,I2S(-poolid)) endfunction function DestroyPool takes integer poolid returns nothing call DestroyArray(poolid) endfunction //! define DestroyPool(p) DestroyArray(p) function PoolAddItem takes integer poolid, integer value returns nothing local integer n local string k=I2S(-poolid) local string vk="#"+I2S(value) if not HaveStoredInteger(cs_cache,k,vk) then set n=GetArrayInt(poolid,0)+1 //[0:integer:N] call StoreInteger(cs_cache,k,vk,n) if (n>33) then call StoreInteger(cs_cache,k,I2S(n),value) else call SetArrayInt(poolid,n,value) endif call SetArrayInt(poolid,0,n) //[0:integer:N] endif endfunction function PoolRemoveItem takes integer poolid, integer value returns nothing local string k=I2S(-poolid) local string vk="#"+I2S(value) local integer p=GetStoredInteger(cs_cache,k,vk) local integer n if (p!=0) then set n=GetArrayInt(poolid,0) //[0:integer:N] call FlushStoredInteger( cs_cache, k, vk) if (n>p) then if (n>33) then set vk=I2S(n) set value=GetStoredInteger(cs_cache,k,vk) call FlushStoredInteger(cs_cache,k,vk) else set value=GetArrayInt(poolid,n) endif call StoreInteger(cs_cache,k,"#"+I2S(value),p) if (p>33) then call StoreInteger(cs_cache,k,I2S(p),value) else call SetArrayInt(poolid,p,value) endif elseif (p>33) then call FlushStoredInteger(cs_cache,k,I2S(p)) endif call SetArrayInt( poolid,0,n - 1) //[0:integer:N] endif endfunction //=================================================================================== function PoolGetItem takes integer poolid, integer itemn returns integer if (itemn>33) then return GetStoredInteger( cs_cache, I2S(-poolid), I2S(itemn)) endif return GetArrayInt(poolid,itemn) endfunction //=================================================================================== function CountItemsInPool takes integer poolid returns integer return GetArrayInt(poolid,0) //[0:integer:N] endfunction //! define CountItemsInPool(p) GetArrayInt(p,0) //=================================================================================== // Removed : GetEnumPoolItem , ForPool and ForPool2 they are much worse than just // using CountItemsInPool and PoolGetItem to iterate the pool // //=================================================================================== function GetFirstOfPool takes integer poolid returns integer return GetArrayInt(poolid,1) //[1 is just the first of the pool] endfunction //! define GetFirstOfPool(p) GetArrayInt(p,1) //=================================================================================== function PoolPickRandomItem takes integer poolid returns integer local integer p=GetRandomInt( 1, GetArrayInt(poolid,0) ) if (p>33) then return GetStoredInteger( cs_cache, I2S(-poolid), I2S(p)) endif return GetArrayInt(poolid,p) endfunction //=================================================================================== function GetItemPositionInPool takes integer poolid, integer it returns integer return GetStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) endfunction //! define GetItemPositionInPool(p,i) GetStoredInteger( cs_cache, I2S(- (p) ), "#"+I2S(i)) //=================================================================================== function IsItemInPool takes integer poolid, integer it returns boolean return(HaveStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) ) endfunction //! define IsItemInPool(p,i) HaveStoredInteger( cs_cache, I2S(- (p) ), "#"+I2S(i)) //=================================================================================== // This had to be optimized for speed, if it was just a loop using the above functions // that would have been too slow to be worth keeping. That's a bad thing about JASS // it is such an slow language that code reusability always has the cost of speed // function PoolAddPool takes integer sourcepoolid, integer destpoolid returns nothing local integer a=1 local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N] local integer dn=GetArrayInt( destpoolid,0) //[0:integer:N] local string sk=I2S(-sourcepoolid) local string k=I2S(-destpoolid) local integer v local string vk loop exitwhen (a>n) if (a>33) then set v=GetStoredInteger(cs_cache,sk,I2S(a)) else set v=GetArrayInt(sourcepoolid,a) endif set vk="#"+I2S(v) if not HaveStoredInteger(cs_cache,k,vk) then set dn=dn+1 call StoreInteger(cs_cache,k,vk,dn) if (dn>33) then call StoreInteger(cs_cache,k,I2S(dn),v) else call SetArrayInt(destpoolid,dn,v) endif endif set a=a+1 endloop call SetArrayInt(destpoolid,0,dn) //[0:integer:N] endfunction //============================================================================================= // Oh darn, After making PoolAddPool I don't feel like writting this one // All right I am at least make the get code // function PoolRemovePool takes integer sourcepoolid, integer destpoolid returns nothing local integer a=1 local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N] local integer v local string sk=I2S(-sourcepoolid) loop exitwhen a>n if (a>33) then set v=GetStoredInteger(cs_cache,sk,I2S(a) ) else set v=GetArrayInt(sourcepoolid,a) endif call PoolRemoveItem( destpoolid, v) set a=a+1 endloop endfunction //=================================================================================== // Adds a tokenized string to a pool, // Example: PoolAddS(udg_p, "1;2;3;4") will add to the udg_p pool : 1,2,3 and 4 // function PoolAddS takes integer poolid, string s returns nothing local integer i=0 local integer st local string c set s=s+";" set st=0 loop set c=SubString(s, i, i+1) exitwhen (c == "") or (c == null) if (c == ";") then call PoolAddItem( poolid, S2I(SubString(s, st, i)) ) set st=i+1 endif set i=i+1 endloop endfunction //=================================================================================== // Converts a tokenized string into a pool, // Example: S2Pool( "1;2;3;4") will return a pool that has 1,2,3 and 4 inside // function S2Pool takes string s returns integer local integer spool= CreatePool() call PoolAddS(spool,s) return spool endfunction //=================================================================================== // Does the opposite of S2Pool, debugging is a good use for this function. // function Pool2S takes integer P returns string local integer N=CountItemsInPool(P) local integer i local string s if (N>=1) then set s=I2S(PoolGetItem(P,1) ) set i=2 else return "" endif loop exitwhen (i>N) set s=s+";"+I2S(PoolGetItem(P,i)) set i=i+1 endloop return s endfunction //============================================================================================================= // Fixes a lame bug by blizzard related to the custom script section (The condition of the if statement might // actually be true. // function Pool_Percent takes nothing returns string if ("%"=="") then return "%%" endif return "%" endfunction function Pool_SetupCharMap takes nothing returns nothing local string cm=".................................!.#$"+Pool_Percent()+"&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................." local integer i=0 local string c if HaveStoredInteger(cs_cache,"charmap_upper","A") then return endif loop set c=SubString(cm,i,i+1) exitwhen (c==null) or (c=="") if (c!=".") then if c==StringCase(c,true) then call StoreInteger(cs_cache,"charmap_upper",c,i) else call StoreInteger(cs_cache,"charmap_lower",c,i) endif endif set i=i+1 endloop endfunction function Pool_Rawcode2Int takes string s returns integer local string c local integer i=0 local integer r=0 loop exitwhen i>3 set c=SubString(s,i,i+1) set r=r*256 if c==StringCase(c,true) then set r=r+GetStoredInteger(cs_cache,"charmap_upper",c) else set r=r+GetStoredInteger(cs_cache,"charmap_lower",c) endif set i=i+1 endloop return r endfunction function PoolAddRawcodes_thread takes nothing returns nothing //Threaded because I don't want it to halt execution for no reason // local string s=bj_lastPlayedMusic local integer poolid=bj_groupEnumTypeId local string c local integer i=0 local integer st=0 set s=s+";" loop set c=SubString(s, i, i+1) exitwhen (c == "") or (c == null) if c == ";" then call PoolAddItem(poolid, Pool_Rawcode2Int(SubString(s,st,i) )) set st=i+1 endif set i=i+1 endloop endfunction //===================================================================================================================== // Adds a string of tokenized rawcodes to a pool // Example: PoolAddRawcodes(udg_p,"A000;A001") will add 'A000' and 'A001' to the pool // // (Saves some lines, but is not as good efficiency wise) // function PoolAddRawcodes takes integer poolid, string s returns nothing local string b=bj_lastPlayedMusic set bj_groupEnumTypeId=poolid set bj_lastPlayedMusic=s call ExecuteFunc("PoolAddRawcodes_thread") set bj_lastPlayedMusic=b endfunction //=================================================================================================================== // Converts a tokenized string of rawcodes into a pool, // Example: Rawcodes2Pool( "A000;A001;AHbz;S000") will return a pool that has 'A000,'A001','AHbx' and 'S000' inside // // (Saves some lines, but is not as good efficiency wise) // function Rawcodes2Pool takes string s returns integer local integer spool= CreatePool() call PoolAddRawcodes(spool,s) return spool endfunction //=================================================================================================================== // A subproduct of the Pool's Rawcode support is that we can easily have this function so I am including it even if // it has nothing to do with data storage. // // takes "Aloc" and converts it into 'Aloc' // it is different to the Pool_Rawcode2Int function in that it is safe to use it when it is the first CSCache // function ever used. But it is a little slower (wc3mapoptimizer should make it as fast though) // function CS_Rawcode2Int takes string s returns integer local string c local integer i=0 local integer r=0 loop exitwhen i>3 set c=SubString(s,i,i+1) set r=r*256 if c==StringCase(c,true) then set r=r+GetStoredInteger(cs_cache,"charmap_upper",c) else set r=r+GetStoredInteger(cs_cache,"charmap_lower",c) endif set i=i+1 endloop return r endfunction function CSCache takes nothing returns gamecache return cs_cache //Left for compat. endfunction endlibrary //Forced by WE function InitTrig_CSCache takes nothing returns nothing endfunction The reason I removed attached sets is that they make GetAttachedInt a little slower and CleanAttachedVars much slower. |
| 09-05-2007, 12:48 AM | #5 |
Thanks for your help! JASS:function GetAttachedObject takes handle h, string label return handle Expected "returns", I could be wrong, but is that just a typo not having an "s"? Sorry, I am a know nothing idiot when it comes to jass. |
| 09-05-2007, 03:28 AM | #6 |
find this: JASS:
//! textmacro GetAttached takes typename, type
function GetAttached$typename$ takes handle h, string label return $type$
if (label=="") then
return GetAttachedInt_FromSet(h)
endif
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
//! endtextmacroreplace with: JASS:
//! textmacro GetAttached takes typename, type
function GetAttached$typename$ takes handle h, string label returns $type$
if (label=="") then
return GetAttachedInt_FromSet(h)
endif
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
//! endtextmacro |
| 09-05-2007, 09:17 PM | #7 |
I am not sure why I am getting this error... But on the Jump template on the spell factory I am getting the following error: JASS:local unit u=GetTriggerUnit() //Identifier redeclared: "u" JASS:return GetStoredInteger(CSCache() , I2S(CS_H2I(h)) , label) //Undeclared Function CSCache JASS:call FlushStoredMission(cs_cache , k + ";" + GetStoredString(g , k , "#setName;" + I2S(i))) //Undeclared variable g |
| 09-05-2007, 10:13 PM | #8 |
this one should do it: JASS:library CSCache initializer InitCSCache //*************************************************************************** //* * //* CSCache 14.3+attachedsets [url]http://wc3campaigns.net/vexorian[/url] * //* ¯¯¯¯¯¯¯ * //* From attach variables to Dynamic Arrays, not forgetting the tables, * //* CSData and the Pools, this is a pack of storage options * //* * //*************************************************************************** //================================================================================================= // CSCache globals: // globals gamecache cs_cache = null integer array cs_array1 integer array cs_array3 integer array cs_array2 integer array cs_freeindexes integer array cs_pairx integer array cs_pairy integer array cs_freepairs gamecache udg_cscache = null //udg_ for compat! endglobals //================================================================================================= // Note: //! define macro commands are used accross the script, they are usually to be parsed by // WEHelper, no //! define parser is really required, but if present it would improve the // performance of some calls. // //================================================================================================= // a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems (I intended this // system to be easy to copy // function CS_H2I takes handle h returns integer return h return 0 endfunction //================================================================================================== // Bunch of other return bug exploiters // function CS_i2r takes integer i returns real return i return 0. endfunction function CS_h2r takes handle h returns real return h return 0. endfunction function CS_r2i takes real r returns integer return r return 0 endfunction function CS_lx takes location l returns location return GetLocationX(l) return null endfunction function CS_ly takes location l returns location return GetLocationY(l) return null endfunction function CS_i2l takes integer l returns location return l return null endfunction //================================================================================================== // location linked list kit // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Thanks: Pipedream | No thanks: Blizzard (for lame bug) // // It is a great irony, but locations are only useful when you don't use them as points but as // structs thanks to the return bug. They only allow 2 values so they are limited in comparission // to gamecache and arrays (see bellow) still useful for single linked lists. // // These functions are what I call enough to use locations as single list nodes, X holds values and // Y can just hold a location (or real) . The Get functions use bj globals to fix an odd operator // bug that can happen after converting pointer to real into pointer to integer. // // The Set functions can be replaced by the Location() constructor, the MoveLocation() native and // the return bug exploiters up there. // //=================================================================================================== // Constructors // function Location_IntLoc takes integer x , location y returns location return Location(CS_i2r(x),CS_h2r(y)) endfunction //! define Location_IntLoc(x,y) Location(CS_i2r(x),CS_h2r(y)) function Location_ObjectLoc takes handle x , location y returns location return Location(CS_h2r(x),CS_h2r(y)) endfunction //! define Location_ObjectLoc(x,y) Location(CS_h2r(x),CS_h2r(y)) function Location_LocLoc takes handle x , location y returns location return Location(CS_h2r(x),CS_h2r(y)) endfunction //! define Location_LocLoc(x,y) Location(CS_h2r(x),CS_h2r(y)) function Location_RealLoc takes real x , location y returns location return Location(x,CS_h2r(y)) endfunction //! define Location_RealLoc(x,y) Location(x,CS_h2r(y)) //==================================================================================================== // Combined assigments // function SetLocation_IntLoc takes location loc, integer x , location y returns nothing call MoveLocation(loc,CS_i2r(x),CS_h2r(y)) endfunction //! define SetLocation_IntLoc(loc,x,y) MoveLocation(loc,CS_i2r(x),CS_h2r(y)) function SetLocation_ObjectLoc takes location loc, handle x , location y returns nothing call MoveLocation(loc,CS_h2r(x),CS_h2r(y)) endfunction //! define SetLocation_ObjectLoc(loc,x,y) MoveLocation(loc,CS_h2r(x),CS_h2r(y)) function SetLocation_LocLoc takes location loc, handle x , location y returns nothing //Funny name call MoveLocation(loc,CS_h2r(x),CS_h2r(y)) endfunction //! define SetLocation_LocLoc(loc,x,y) MoveLocation(loc,CS_h2r(x),CS_h2r(y)) function SetLocation_RealLoc takes location loc, real x , location y returns nothing call MoveLocation(loc,x,CS_h2r(y)) endfunction //! define SetLocation_RealLoc(loc,x,y) MoveLocation(loc,x,CS_h2r(y)) //=================================================================================================== // Lack of SetLocationX / SetLocationY natives is kind of lame // function SetLocationX_Object takes location loc, handle val returns nothing call MoveLocation(loc,CS_h2r(val),GetLocationY(loc)) endfunction // Notice how define SetLocationX_Object(loc,v) MoveLocation(loc,CS_h2r(v),GetLocationY(loc)) // would have a chance of messing sometimes since it has 2 loc in the result. function SetLocationX_Loc takes location loc, location val returns nothing //just name candy call MoveLocation(loc,CS_h2r(val),GetLocationY(loc)) endfunction function SetLocationX_Real takes location loc, real val returns nothing call MoveLocation(loc,val,GetLocationY(loc)) endfunction function SetLocationX_Int takes location loc, integer val returns nothing call MoveLocation(loc,CS_i2r(val),GetLocationY(loc)) endfunction function SetLocationY_Loc takes location loc, location val returns nothing call MoveLocation(loc,GetLocationX(loc),CS_h2r(val)) endfunction //================================================================================================== // All right, crazyness that started with Attacheable variables, and had to continue with everything // from tables, arrays and now this. Sorry I can't help itç // // The good thing about these functions is that they are safe, you won't deal with real->(int/handle) // conversion related bugs thanks to the use of bj variables these functions do // function GetLocationX_Loc takes location loc returns location set bj_enumDestructableCenter=CS_lx(loc) return bj_enumDestructableCenter endfunction function GetLocationY_Loc takes location loc returns location set bj_enumDestructableCenter=CS_ly(loc) return bj_enumDestructableCenter endfunction function GetLocationX_Int takes location loc returns integer set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex endfunction function GetLocationX_Unit takes location loc returns unit set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Item takes location loc returns item set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Effect takes location loc returns effect set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Lightning takes location loc returns lightning set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Widget takes location loc returns widget set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Object takes location loc returns handle set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Rect takes location loc returns rect set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Region takes location loc returns region set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_TimerDialog takes location loc returns timerdialog set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Destructable takes location loc returns destructable set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Trigger takes location loc returns trigger set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Timer takes location loc returns timer set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Group takes location loc returns group set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_TriggerAction takes location loc returns triggeraction set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Image takes location loc returns image set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Ubersplat takes location loc returns ubersplat set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction function GetLocationX_Sound takes location loc returns sound set bj_forLoopAIndex=CS_r2i(GetLocationX(loc)) return bj_forLoopAIndex return null endfunction // //That should be all we needed to abuse Locations, Love lists. // // CSCache initializer : function InitCSCache takes nothing returns nothing call FlushGameCache(InitGameCache("cscache")) set cs_cache=InitGameCache("cscache") set udg_cscache = cs_cache call ExecuteFunc("InitArrayIndexes") call ExecuteFunc("Pool_SetupCharMap") endfunction //================================================================================================== // CSData // ¯¯¯¯¯¯ // CSDatas are like UserData in units and items, they are faster than gamecache unless you have more // than 8191 handles in your map. In that case it would be a little slower but only for those // handles. And if you have more than 8191 handles your map is too slow already anyways. // // Notice that for public spells or systems to be distributed you should only use these // for private objects (those who the mapper would never have access to) If you are making something // for your map you can use them wherever you want. // // Best to be used in conjunction to CSArrays so you just specify an array id for a handle. // // DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag, // -any 'argument' handle (like playerstate, damagetype, etc) // function SetCSData takes handle h, integer v returns nothing local integer i=CS_H2I(h)-0x100000 if (i>=8191) then call StoreInteger(cs_cache,"csdata",I2S(i),v) else set cs_array3[i]=v endif endfunction function GetCSData takes handle h returns integer local integer i=CS_H2I(h)-0x100000 if (i>=8191) then //can't use Get without Set return GetStoredInteger(cs_cache,"csdata",I2S(i)) endif return cs_array3[i] endfunction //================================================================================================================= // CS Pairs // ¯¯¯¯¯¯¯¯ // This is a sub system to assist csarrays, you can use them but CSArrays of size 2 have the same functionality // although cspairs are be faster their space is limited and will start using gamecache if abused // function NewPair takes integer x, integer y returns integer local integer i if (cs_freepairs[0]==0) then set cs_freepairs[8190]=cs_freepairs[8190]+1 set i= cs_freepairs[8190] else set i= cs_freepairs[cs_freepairs[0]] set cs_freepairs[0]=cs_freepairs[0]-1 endif if (i>=8189) then //because we can only recycle up to 8189 (free pairs array uses indexes 0 and 8190 for other purposes) call StoreInteger(cs_cache,"pairx",I2S(i),x) call StoreInteger(cs_cache,"pairy",I2S(i),y) else set cs_pairx[i]=x set cs_pairy[i]=y endif return i endfunction function DestroyPair takes integer id returns nothing if (id>=8189) then call FlushStoredInteger(cs_cache,"pairx",I2S(id)) call FlushStoredInteger(cs_cache,"pairy",I2S(id)) else set cs_freepairs[0]=cs_freepairs[0]+1 set cs_freepairs[cs_freepairs[0]] = id endif endfunction function SetPairXY takes integer id, integer x, integer y returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairx",I2S(id),x) call StoreInteger(cs_cache,"pairy",I2S(id),y) else set cs_pairx[id]=x set cs_pairy[id]=y endif endfunction function SetPairX takes integer id, integer x returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairx",I2S(id),x) else set cs_pairx[id]=x endif endfunction function SetPairY takes integer id, integer y returns nothing if (id>=8189) then call StoreInteger(cs_cache,"pairy",I2S(id),y) else set cs_pairy[id]=y endif endfunction function GetPairX takes integer id returns integer if (id>=8189) then return GetStoredInteger(cs_cache,"pairy",I2S(id)) endif return cs_pairx[id] endfunction function GetPairY takes integer id returns integer if (id>=8189) then return GetStoredInteger(cs_cache,"pairx",I2S(id)) endif return cs_pairy[id] endfunction //================================================================================================================= // CS Dynamic Arrays // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ // Thanks: Pipedream, Peppar // // We can now create arrays in game! , also pass them as arguments or return values! // a 1 length array is a pointer! // function Array_TryFree takes nothing returns nothing local integer i local integer N=cs_array1[0] local integer k local boolean cleaned=false local integer loc local integer q local integer r set i=cs_array1[146] if (i>144) then call TimerStart(GetExpiredTimer(),60.,false,function Array_TryFree) return endif set loc=cs_freeindexes[i] set q=0 loop exitwhen (loc==0) // we could just have used: //set k=GetPairX(loc) //set r=GetPairY(loc) But it is slower than direct usage: if (loc>=8192) then set k=GetStoredInteger(cs_cache,"pairx",I2S(loc)) set r=GetStoredInteger(cs_cache,"pairy",I2S(loc)) else set k=cs_pairx[loc] set r=cs_pairy[loc] endif if (k+i-1==N) then //we found one we can remove from the list set cleaned=true //decrement N set N=k-2 //Remove from the list: if (q==null) then //That was the first, update the array as well set cs_freeindexes[i]=r else //Update the next of the previous one //We could use : call SetPairY(q,,r) but it is slower if (q>=8189) then call StoreInteger(cs_cache,"pairy",I2S(q),r) else set cs_pairy[q]=r endif endif if (r==null) then //This was the last one, update it in the array as well set cs_freeindexes[i+4096]=q endif call DestroyPair(loc) set loc=q endif set q=loc set loc=r endloop if (cleaned) then set cs_array1[0]=N set cs_array1[146]=1 else set cs_array1[146]=cs_array1[i+1] endif call TimerStart(GetExpiredTimer(),0.2,false,function Array_TryFree) endfunction function InitArrayIndexes2 takes nothing returns nothing local integer i=0 loop exitwhen (i==8191) set cs_pairx[i]=777 set cs_pairy[i]=777 set i=i+1 endloop endfunction function InitArrayIndexes takes nothing returns nothing local integer i=0 local integer a=1 local integer b=1 local integer c //By placing 777 there instead of 0 it is easier to recognize non correctly initialized bugs loop exitwhen (i== 8191) set cs_array1[i]=777 set cs_array2[i]=777 set cs_array3[i]=777 //set cs_pairx[i]=777 //set cs_pairy[i]=777 set i=i+1 endloop call ExecuteFunc("InitArrayIndexes2") set cs_freeindexes[0]=0 //The stack for the table indexes. set cs_freepairs[0]=0 set cs_freepairs[8190]=0 set i=1 loop set c=a+b set a=b set b=c exitwhen (b>144) //max size is 144 set cs_freeindexes[b]=0 //the first of the list set cs_freeindexes[b+4096]=0 //the last of the list loop exitwhen (i>b) set cs_array1[i]=b set i=i+1 endloop endloop set cs_array1[i]=b //i is 145 set cs_array1[146]=1 set cs_array1[147]=101 //initial table index is 101 set cs_array1[0]=147 //index 0: Last used index // 1 to 145 : Fibonacci sequence // 146 : last check // 147 : Table indexes check //This has a good chance to compress the thing when necesary call TimerStart(CreateTimer(),60.,false,function Array_TryFree) endfunction //============================================================================================= // Create an array of size, max size is 144, if doinit is true it will put a bunch of zeros // in the indexes // function NewArray takes integer size, boolean doinit returns integer local integer i local integer rsize=cs_array1[size] local integer loc set loc=cs_freeindexes[rsize] if (loc!=0) then set cs_freeindexes[rsize]= GetPairY(loc) if (cs_freeindexes[rsize]==0) then set cs_freeindexes[4096+rsize]=0 endif set i=GetPairX(loc) call DestroyPair(loc) if (i==0) then //this code was probably a good idea when we used locations for the free indexes list, now we use pairs which should not ever //do this unless someone modiffied the pair array incorrectly call BJDebugMsg("Caster System: Unexpected error (5): corrupt stack, attempt to recover "+I2S(rsize)) // recovering involves forgetting about the stack which got corrupted and start again from zero, it will leak // and probably get slow due to usage of gamecache but it is better than the problems that a corrupt stack might cause set cs_freeindexes[rsize]=0 set cs_freeindexes[4096+rsize]=0 return NewArray(size,doinit) endif else //sz i i+1 i+2 //[ ][ ][ ][ ] set i=cs_array1[0]+2 set cs_array1[0]=i+rsize-1 endif //It used to store size in the index equal to the array's id // but that required the get/set functions to increment 1 in every index // calculation. Instead, making size the previous index to the array works if (i<=8191) then set cs_array1[i-1]=size elseif (i<=16382) then set cs_array2[i-8192]=size else call StoreInteger(cs_cache,I2S(-i),"size",size) endif if (not doinit) then return i endif // 3 //[i][i+1][i+2] set size=i+size-1 if (size>=16382) then set size=16381 endif loop exitwhen (size<i) or (size<8191) set cs_array2[size-8191]=0 set size=size-1 endloop loop exitwhen (size<i) set cs_array1[size]=0 set size=size-1 endloop //call DisplayTextToPlayer(GetLocalPlayer(),0,0,I2S(i)) return i endfunction //=============================================================================================================== // Remember to destroy arrays when you no longer need them, else new arrays will get slower after a bunch of // arrays are active // function DestroyArray takes integer id returns nothing local integer L local integer loc // local string k=I2S(-id) local integer lstpace if (id<=8191) then set L=cs_array1[cs_array1[id-1]] elseif (id<=16382) then set L=cs_array1[cs_array2[id-8191]] else set L=cs_array1[GetStoredInteger(cs_cache,I2S(-id),"size")] //No way you are gonna call DestroyArray without calling //NewArray first, so we can use the gamecache variable directly instead endif set lstpace=id+L-1 call FlushStoredMission(cs_cache,I2S(-id)) if (lstpace>16382) then if (lstpace==cs_array1[0]) then //We just destroyed the array that happens to be at the end of the heap. //Just get it back set cs_array1[0]=id-2 set cs_array1[146]=1 else //Add to the last set loc=cs_freeindexes[L+4096] if (loc==0) then set loc=NewPair(id,0) set cs_freeindexes[L]=loc set cs_freeindexes[L+4096]=loc else set cs_freeindexes[L+4096]= NewPair(id,0) //we could just use: call SetPairY(loc, cs_freeindexes[L+4096] ) //but that's slower if (loc>=8189) then call StoreInteger(cs_cache,"pairy",I2S(loc), cs_freeindexes[L+4096] ) else set cs_pairy[loc]=cs_freeindexes[L+4096] endif endif endif elseif (lstpace==cs_array1[0]) then //We just destroyed the array that happens to be at the end of the heap. //Just get it back set cs_array1[0]=id-2 set cs_array1[146]=1 else set loc=cs_freeindexes[L] set cs_freeindexes[L]=NewPair(id,loc) if (loc==0) then set cs_freeindexes[L+4096]=cs_freeindexes[L] endif endif endfunction //================================================================================================================ // Int Set/Get array usage prototypes. // // These are the actual functions, the rest are just the result of copy paste, if these functions are updated // the other ones should be updated as well (They are just return bugged variations) // function SetArrayInt takes integer id, integer index, integer val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=val elseif (index<16382) then set cs_array2[index-8191]=val else call StoreInteger(cs_cache,I2S(-id),I2S(index),val) endif endfunction function GetArrayInt takes integer id, integer index returns integer set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) endfunction //================================================================================================================ // String Set/Get array // // Due String related return bug issues, these are forced to use gamecache // function SetArrayString takes integer id, integer index, string val returns nothing call StoreString(cs_cache,I2S(-id),I2S(index),val) endfunction function GetArrayString takes integer id, integer index returns string return GetStoredString(cs_cache,I2S(-id),I2S(index)) endfunction //(Boolean is not needed) //=================================================================================================== // Indexes of real types // function SetArrayReal takes integer id, integer index, real val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=CS_r2i(val) elseif (index<16382) then set cs_array2[index-8191]=CS_r2i(val) else call StoreInteger(cs_cache,I2S(-id),I2S(index),CS_r2i(val)) endif endfunction function GetArrayReal takes integer id, integer index returns real set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return 0.0 endfunction //=================================================================================================== // <Indexes of handle types> // function SetArrayObject takes integer id, integer index, handle val returns nothing set index=id+index if (index<8191) then set cs_array1[index]=CS_H2I(val) elseif (index<16382) then set cs_array2[index-8191]=CS_H2I(val) else call StoreInteger(cs_cache,I2S(-id),I2S(index),CS_H2I(val)) endif endfunction // // //Yep, I am crazy. But These are FASTER than using the function and a return bug exploiter separatedly. function GetArrayObject takes integer id, integer index returns handle set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayWidget takes integer id, integer index returns widget set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTimer takes integer id, integer index returns timer set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayUnit takes integer id, integer index returns unit set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayLoc takes integer id, integer index returns location set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTrigger takes integer id, integer index returns trigger set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayTriggerAction takes integer id, integer index returns triggeraction set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayGroup takes integer id, integer index returns group set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayEffect takes integer id, integer index returns effect set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayItem takes integer id, integer index returns item set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction function GetArrayLightning takes integer id, integer index returns lightning set index=id+index if (index<8191) then return cs_array1[index] elseif (index<16382) then return cs_array2[index-8191] endif return GetStoredInteger(cs_cache,I2S(-id),I2S(index)) return null endfunction //The rest are not used that much and they are a waste of space instead of a save of speed //most of the times. THEY ARE STILL MUCH FASTER THAN GAMECACHE function GetArrayRect takes integer id, integer index returns rect return GetArrayInt(id,index) return null endfunction function GetArrayRegion takes integer id, integer index returns region return GetArrayInt(id,index) return null endfunction function GetArrayTimerDialog takes integer id, integer index returns timerdialog return GetArrayInt(id,index) return null endfunction function GetArrayDestructable takes integer id, integer index returns destructable return GetArrayInt(id,index) return null endfunction function GetArrayImage takes integer id, integer index returns image return GetArrayInt(id,index) return null endfunction function GetArrayUbersplat takes integer id, integer index returns ubersplat return GetArrayInt(id,index) return null endfunction function GetArraySound takes integer id, integer index returns sound return GetArrayInt(id,index) return null endfunction // </Indexes of handle types> // The horror! // //========================================================================================================================== // Returns the size of an array (the specified by player one, not the actual size of it) should be useful. // function GetArraySize takes integer id returns integer if (id<=8191) then return cs_array1[id-1] elseif (id<=16382) then return cs_array2[id-8192] endif return GetStoredInteger(cs_cache,I2S(-id),"size") endfunction //=========================================================================================================================== // Returns an array that is an exact copy of the given array // function CloneArray takes integer id returns integer local integer sz local integer i local integer sz2 local integer x local integer y if (id<=8191) then set sz=cs_array1[id-1] elseif (id<=16382) then set sz=cs_array2[id-8192] else set sz=GetStoredInteger(cs_cache,I2S(-id),"size") //No way you are gonna call DestroyArray without calling //NewArray first, so we can use the gamecache variable directly instead endif set i=NewArray(sz,false) set sz2=i+sz-1 set sz=id+sz-1 set x=i set y=id loop exitwhen ((y>sz) or (y>=8191) or (x>=8191)) set cs_array1[x]=cs_array1[y] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=8191) or (x>=16382)) set cs_array2[x-8191]=cs_array1[y] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=8191)) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array1[y]) set x=y+1 set y=y+1 endloop //... loop exitwhen ((y>sz) or (y>=16382) or (x>=8191)) set cs_array1[x]=cs_array2[y-8191] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=16382) or (x>=16382)) set cs_array2[x-8191]=cs_array2[y-8191] set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (y>=16382)) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array2[y-8191]) set y=y+1 set x=x+1 endloop //... loop exitwhen ((y>sz) or (x>=8191)) set cs_array1[x]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)) set y=y+1 set x=x+1 endloop loop exitwhen ((y>sz) or (x>=16382)) set cs_array2[x-8191]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)) set y=y+1 set x=x+1 endloop loop exitwhen (y>sz) call StoreInteger(cs_cache,I2S(-i),I2S(x-i),GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))) set y=y+1 set x=x+1 endloop return i endfunction //================================================================================================== // Attachable vars : Attacheable variables are what most other people call Handle Variables, they // allow to relate data with any handle, using a label, and its value, the stuff auto flushes if // the value is 0, false, "", or null . // // Differences between Attacheable variables and "Local Handle Variables" : // - The names of the functions // - The name of the function group does not cause confusion, it is difficult to say: // "you should set local handle variables to null at the end of a function" since // it sounds as if you were talking about the "Local Handle Variables" // - And can work together with Tables. // // Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!) // // // Although locations and dynamic arrays are faster than gamecache, gamecache still keeps the flexibility // Best thing to do in my opinion is to combine these options. By combining you can acquire gamecache // flexibility and arrays/locs speed to solve a problem // //============================================================================================================ // For integers // function AttachInt takes handle h, string label, integer x returns nothing if x==0 then call FlushStoredInteger(cs_cache,I2S(CS_H2I(h)),label) else call StoreInteger(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction globals private string argpass_set="null" private string argpass_seti="null" endglobals function GetAttachedInt_FromSet takes handle h returns integer return GetStoredInteger(cs_cache,I2S(CS_H2I(h))+";"+argpass_set,argpass_seti) endfunction function GetAttachedInt takes handle h, string label returns integer if (label=="") then return GetAttachedInt_FromSet(h) endif return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label) endfunction //! textmacro GetAttached takes typename, type function GetAttached$typename$ takes handle h, string label returns $type$ if (label=="") then return GetAttachedInt_FromSet(h) endif return GetStoredInteger(cs_cache, I2S(CS_H2I(h)), label) return null endfunction //! endtextmacro //============================================================================================================= function AttachReal takes handle h, string label, real x returns nothing if x==0 then call FlushStoredReal(cs_cache,I2S(CS_H2I(h)),label) else call StoreReal(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedReal takes handle h, string label returns real return GetStoredReal(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachBoolean takes handle h, string label, boolean x returns nothing if not x then call FlushStoredBoolean(cs_cache,I2S(CS_H2I(h)),label) else call StoreBoolean(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedBoolean takes handle h, string label returns boolean return GetStoredBoolean(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachString takes handle h, string label, string x returns nothing if ((x=="") or (x==null)) then call FlushStoredString(cs_cache,I2S(CS_H2I(h)),label) else call StoreString(cs_cache,I2S(CS_H2I(h)),label,x) endif endfunction function GetAttachedString takes handle h, string label returns string return GetStoredString(cs_cache,I2S(CS_H2I(h)),label) endfunction //============================================================================================================= function AttachObject takes handle h, string label, handle x returns nothing if (x==null) then call FlushStoredInteger(cs_cache,I2S(CS_H2I(h)),label) else call StoreInteger(cs_cache,I2S(CS_H2I(h)),label,CS_H2I(x)) endif endfunction //! runtextmacro GetAttached("Object","handle") //! runtextmacro GetAttached("Widget","widget") //! runtextmacro GetAttached("Rect","rect") //! runtextmacro GetAttached("Region","region") //! runtextmacro GetAttached("TimerDialog","timerdialog") //! runtextmacro GetAttached("Unit","unit") //! runtextmacro GetAttached("Item","item") //! runtextmacro GetAttached("Effect","effect") //! runtextmacro GetAttached("Destructable","destructable") //! runtextmacro GetAttached("Trigger","trigger") //! runtextmacro GetAttached("Timer","timer") //! runtextmacro GetAttached("Group","group") //! runtextmacro GetAttached("TriggerAction","triggeraction") //! runtextmacro GetAttached("Lightning","lightning") //! runtextmacro GetAttached("Image","image") //! runtextmacro GetAttached("Ubersplat","ubersplat") //! runtextmacro GetAttached("Sound","sound") //! runtextmacro GetAttached("Loc","location") //============================================================================================================ // Attached Sets: Attachable Sets are handy in some situations and are a part of attachable variables, // you can add integers or objects to a set, order doesn't matter and adding the same object twice is // meaningless. CleanAttachedVars is always ready to clean every set owned by the handle. // //============================================================================================================ function AttachedSetAddInt takes handle h, string setn, integer int returns nothing local string k=I2S(CS_H2I(h)) local integer n local integer x=GetStoredInteger(cs_cache,k,"#setnumberof;"+setn) local integer y if x==0 then set y=GetStoredInteger(cs_cache,k,"#totalsets")+1 call StoreInteger(cs_cache,k,"#totalsets",y) call StoreInteger(cs_cache,k,"#setnumberof;"+setn,y) call StoreString(cs_cache,k,"#setName;"+I2S(y),setn) endif set k=k+";"+setn if not HaveStoredInteger(cs_cache,k,"Pos"+I2S(int)) then set n=GetStoredInteger(cs_cache,k,"n")+1 call StoreInteger(cs_cache,k,"n",n) call StoreInteger(cs_cache,k,I2S(n),int) call StoreInteger(cs_cache,k,"Pos"+I2S(int),n) endif endfunction function AttachedSetAddObject takes handle h, string setn, handle val returns nothing call AttachedSetAddInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function AttachedSetHasInt takes handle h, string setn, integer int returns boolean return HaveStoredInteger(cs_cache,I2S(CS_H2I(h))+";"+setn,"Pos"+I2S(int)) endfunction function AttachedSetHasObject takes handle h, string setn, handle val returns boolean return AttachedSetHasInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function GetAttachedSetSize takes handle h, string setn returns integer return GetStoredInteger(cs_cache,I2S(CS_H2I(h))+";"+setn,"n") endfunction //============================================================================================================ function AttachedSetRemInt takes handle h, string setn, integer int returns nothing local string k=I2S(CS_H2I(h))+";"+setn local integer n local integer x local integer y if HaveStoredInteger(cs_cache,k,"Pos"+I2S(int)) then set x=GetStoredInteger(cs_cache,k,"Pos"+I2S(int)) set n=GetStoredInteger(cs_cache,k,"n") if x!=n then set y=GetStoredInteger(cs_cache,k,I2S(n)) call StoreInteger(cs_cache,k,I2S(x),y) call StoreInteger(cs_cache,k,"Pos"+I2S(y),x) endif call FlushStoredInteger(cs_cache,k,"Pos"+I2S(int)) call FlushStoredInteger(cs_cache,k,I2S(n)) call StoreInteger(cs_cache,k,"n",n-1) endif endfunction function AttachedSetRemObject takes handle h, string setn, handle val returns nothing call AttachedSetRemInt(h,setn,CS_H2I(val)) endfunction //============================================================================================================ function FromSetElement takes string setn, integer index returns string set argpass_set=setn set argpass_seti=I2S(index) return "" endfunction //============================================================================================================ function ClearAttachedSet takes handle h, string setn returns nothing call FlushStoredMission(cs_cache,I2S(CS_H2I(h))+";"+setn) endfunction //============================================================================================================ function CleanAttachedVars takes handle h returns nothing local string k=I2S(CS_H2I(h)) local integer n=GetStoredInteger(cs_cache,k,"#totalsets") local integer i=1 loop exitwhen i>n call FlushStoredMission(cs_cache,k+";"+GetStoredString(cs_cache,k,"#setName;"+I2S(i))) set i=i+1 endloop call FlushStoredMission(cs_cache, k ) endfunction function CleanAttachedVars_NoSets takes handle h returns nothing call FlushStoredMission(cs_cache,I2S(CS_H2I(h))) endfunction //! define CleanAttachedVars_NoSets(h) FlushStoredMission(cs_cache,I2S(CS_H2I(h))) //============================================================================================= // Tables // // Tables are lame, the real name would be hash tables, they are just abbreviated usage // of gamecache natives with the addition that you can also Copy the values of a table to // another one, but don't expect it to be automatic, it must use a FieldData object to know // which fields and of wich types to copy, Copying a table to another, with a lot of Fields, // should surelly be lag friendly. // // The other thing about tables is that I can say that the Attached variables of a handle work // inside a table and GetAttachmentTable which is just return bug and I2S , works to allow you // to manipulate a handle's attached variables through a table. // // NewTable and DestroyTable were created to allow to create tables in the fly, but you can // simply use strings for tables, but place the table names should be between "("")" for example // "(mytable)" to avoid conflicts with other caster system stuff. // function NewTableIndex takes nothing returns integer local integer loc=cs_freeindexes[0] local integer i if (loc!=0) then set i=GetPairX(loc) set cs_freeindexes[0]=GetPairY(loc) call DestroyPair(loc) return i endif set i=cs_array1[147]+1 set cs_array1[147]=i return i endfunction function NewTable takes nothing returns string local integer loc=cs_freeindexes[0] local integer i if (loc!=0) then set i=GetPairX(loc) set cs_freeindexes[0]=GetPairY(loc) call DestroyPair(loc) return I2S(i) endif set i=cs_array1[147]+1 set cs_array1[147]=i return I2S(i) endfunction function GetAttachmentTable takes handle h returns string return I2S(CS_H2I(h)) endfunction //! define GetAttachmentTable(h) I2S(CS_H2I(h)) //============================================================================================================ function DestroyTable takes string table returns nothing local integer i=S2I(table) local integer n call FlushStoredMission(cs_cache,table) if ((i>100) and (i<1000000)) then //All right, more than 1000000 tables is just wrong. if (i==cs_array1[147]) then set cs_array1[147]=cs_array1[147]-1 else set cs_freeindexes[0]= NewPair(i,cs_freeindexes[0]) endif endif endfunction //============================================================================================================ function ClearTable takes string table returns nothing call FlushStoredMission(cs_cache,table) endfunction //============================================================================================================ function SetTableInt takes string table, string field, integer val returns nothing if (val==0) then call FlushStoredInteger(cs_cache,table,field) else call StoreInteger(cs_cache,table,field,val) endif endfunction function GetTableInt takes string table, string field returns integer return GetStoredInteger(cs_cache,table,field) endfunction //! define GetTableInt(table,field) GetStoredInteger(cs_cache,table,field) //============================================================================================================ function SetTableReal takes string table, string field, real val returns nothing if (val==0) then call FlushStoredReal(cs_cache,table,field) else call StoreReal(cs_cache,table,field,val) endif endfunction function GetTableReal takes string table, string field returns real return GetStoredReal(cs_cache,table,field) endfunction //! define GetTableReal(table,field) GetStoredReal(cs_cache,table,field) //============================================================================================================ function SetTableBoolean takes string table, string field, boolean val returns nothing if (not(val)) then call FlushStoredBoolean(cs_cache,table,field) else call StoreBoolean(cs_cache,table,field,val) endif endfunction function GetTableBoolean takes string table, string field returns boolean return GetStoredBoolean(cs_cache,table,field) endfunction //! define GetTableBoolean(table,field) GetStoredBoolean(cs_cache,table,field) //============================================================================================================ function SetTableString takes string table, string field, string val returns nothing if (val=="") or (val==null) then call FlushStoredString(cs_cache,table,field) else call StoreString(cs_cache,table,field,val) endif endfunction function GetTableString takes string table, string field returns string return GetStoredString(cs_cache,table,field) endfunction //! define GetTableString(table,field) GetStoredString(cs_cache,table,field) //============================================================================================================ // You may ask why am I using thousands of functions instead of multi-use return bug exploiters? Well, // these make the thing much easier to read (in my opinion) and it is also better in performance since we // have less function calls (H2U(GetTableObject("table","unit"))) would be worse than GetTableUnit that is // quite direct. // function SetTableObject takes string table, string field, handle val returns nothing if (val==null) then call FlushStoredInteger(cs_cache,table,field) else call StoreInteger(cs_cache,table,field,CS_H2I(val)) endif endfunction function GetTableObject takes string table, string field returns handle return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableWidget takes string table, string field returns widget return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableRect takes string table, string field returns rect return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableRegion takes string table, string field returns region return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTimerDialog takes string table, string field returns timerdialog return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableUnit takes string table, string field returns unit return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableItem takes string table, string field returns item return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableEffect takes string table, string field returns effect return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableDestructable takes string table, string field returns destructable return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTrigger takes string table, string field returns trigger return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTimer takes string table, string field returns timer return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableGroup takes string table, string field returns group return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableTriggerAction takes string table, string field returns triggeraction return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableLightning takes string table, string field returns lightning return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableImage takes string table, string field returns image return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableUbersplat takes string table, string field returns ubersplat return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableSound takes string table, string field returns sound return GetStoredInteger(cs_cache,table,field) return null endfunction function GetTableLoc takes string table, string field returns location return GetStoredInteger(cs_cache,table,field) return null endfunction //============================================================================================================ // Returns true if the fiel contains a value different from 0, false, null, or "" (depending on the type) // it is worthless to use this with boolean, since it would be the same as reading the boolean value // function HaveSetField takes string table, string field, integer fieldType returns boolean if (fieldType == bj_GAMECACHE_BOOLEAN) then return HaveStoredBoolean(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_INTEGER) then return HaveStoredInteger(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_REAL) then return HaveStoredReal(cs_cache,table,field) elseif (fieldType == bj_GAMECACHE_STRING) then return HaveStoredString(cs_cache,table,field) endif return false endfunction //============================================================================================================ // Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type // it is supposed to copy. // function CopyTable takes integer FieldData, string sourceTable, string destTable returns nothing local integer i=1 local string k=I2S(FieldData) local string k2 local string k3 local integer n=GetStoredInteger(cs_cache,k,"N") local integer t loop exitwhen (i>n) set k2=I2S(i) set t=GetStoredInteger(cs_cache,k,k2) set k3=GetStoredString(cs_cache,k,k2) if (t==bj_GAMECACHE_BOOLEAN) then if (HaveStoredBoolean(cs_cache,sourceTable,k3)) then call StoreBoolean(cs_cache,destTable,k3,GetStoredBoolean(cs_cache,sourceTable,k3)) else call FlushStoredBoolean(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_INTEGER) then if (HaveStoredInteger(cs_cache,sourceTable,k3)) then call StoreInteger(cs_cache,destTable,k3,GetStoredInteger(cs_cache,sourceTable,k3)) else call FlushStoredInteger(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_REAL) then if (HaveStoredReal(cs_cache,sourceTable,k3)) then call StoreReal(cs_cache,destTable,k3,GetStoredReal(cs_cache,sourceTable,k3)) else call FlushStoredReal(cs_cache,destTable,k3) endif elseif (t==bj_GAMECACHE_STRING) then if (HaveStoredString(cs_cache,sourceTable,k3)) then call StoreString(cs_cache,destTable,k3,GetStoredString(cs_cache,sourceTable,k3)) else call FlushStoredString(cs_cache,destTable,k3) endif endif set i=i+1 endloop endfunction //============================================================================================= // FieldData inherits from Table, was just designed to be used by CopyTable. // function FieldData_Create takes nothing returns integer return NewTableIndex() endfunction //! define FieldData_Create NewTableIndex //============================================================================================================ // valueType uses the same integer variables from blizzard.j : // bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING // function FieldData_AddField takes integer fielddata, string field, integer valueType returns nothing local string k=I2S(fielddata) local integer n=GetStoredInteger(cs_cache,k,"N")+1 local string k2=I2S(n) call StoreString(cs_cache,k,k2,field) call StoreInteger(cs_cache,k,k2,valueType) call StoreInteger(cs_cache,k,"N",n) endfunction //============================================================================================= // Destroys Field Data function FieldData_Destroy takes integer fielddata returns nothing call DestroyTable(I2S(fielddata)) endfunction //! define FieldData_Destroy(fielddata) DestroyTable(I2S(fielddata)) //============================================================================================= // Pools // // A better name for pools would be sets, but by the time I made them I couldn't think of that // name, besides the word set is already a JASS syntax word so it would have been problematic. // // Another naming failure is that values of a pool are called "items" but that conflicts with // the word item that points to wc3 items, Pools can only store integer values, but if you want // you can go and use the return bug on them. // function CreatePool takes nothing returns integer local integer i=NewArray(34,false) call SetArrayInt(i,0,0) return i endfunction function ClearPool takes integer poolid returns nothing call SetArrayInt(poolid,0,0) //[0:integer:n] call FlushStoredMission(cs_cache,I2S(-poolid)) endfunction function DestroyPool takes integer poolid returns nothing call DestroyArray(poolid) endfunction //! define DestroyPool(p) DestroyArray(p) function PoolAddItem takes integer poolid, integer value returns nothing local integer n local string k=I2S(-poolid) local string vk="#"+I2S(value) if not HaveStoredInteger(cs_cache,k,vk) then set n=GetArrayInt(poolid,0)+1 //[0:integer:N] call StoreInteger(cs_cache,k,vk,n) if (n>33) then call StoreInteger(cs_cache,k,I2S(n),value) else call SetArrayInt(poolid,n,value) endif call SetArrayInt(poolid,0,n) //[0:integer:N] endif endfunction function PoolRemoveItem takes integer poolid, integer value returns nothing local string k=I2S(-poolid) local string vk="#"+I2S(value) local integer p=GetStoredInteger(cs_cache,k,vk) local integer n if (p!=0) then set n=GetArrayInt(poolid,0) //[0:integer:N] call FlushStoredInteger( cs_cache, k, vk) if (n>p) then if (n>33) then set vk=I2S(n) set value=GetStoredInteger(cs_cache,k,vk) call FlushStoredInteger(cs_cache,k,vk) else set value=GetArrayInt(poolid,n) endif call StoreInteger(cs_cache,k,"#"+I2S(value),p) if (p>33) then call StoreInteger(cs_cache,k,I2S(p),value) else call SetArrayInt(poolid,p,value) endif elseif (p>33) then call FlushStoredInteger(cs_cache,k,I2S(p)) endif call SetArrayInt( poolid,0,n - 1) //[0:integer:N] endif endfunction //=================================================================================== function PoolGetItem takes integer poolid, integer itemn returns integer if (itemn>33) then return GetStoredInteger( cs_cache, I2S(-poolid), I2S(itemn)) endif return GetArrayInt(poolid,itemn) endfunction //=================================================================================== function CountItemsInPool takes integer poolid returns integer return GetArrayInt(poolid,0) //[0:integer:N] endfunction //! define CountItemsInPool(p) GetArrayInt(p,0) //=================================================================================== // Removed : GetEnumPoolItem , ForPool and ForPool2 they are much worse than just // using CountItemsInPool and PoolGetItem to iterate the pool // //=================================================================================== function GetFirstOfPool takes integer poolid returns integer return GetArrayInt(poolid,1) //[1 is just the first of the pool] endfunction //! define GetFirstOfPool(p) GetArrayInt(p,1) //=================================================================================== function PoolPickRandomItem takes integer poolid returns integer local integer p=GetRandomInt( 1, GetArrayInt(poolid,0) ) if (p>33) then return GetStoredInteger( cs_cache, I2S(-poolid), I2S(p)) endif return GetArrayInt(poolid,p) endfunction //=================================================================================== function GetItemPositionInPool takes integer poolid, integer it returns integer return GetStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) endfunction //! define GetItemPositionInPool(p,i) GetStoredInteger( cs_cache, I2S(- (p) ), "#"+I2S(i)) //=================================================================================== function IsItemInPool takes integer poolid, integer it returns boolean return(HaveStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) ) endfunction //! define IsItemInPool(p,i) HaveStoredInteger( cs_cache, I2S(- (p) ), "#"+I2S(i)) //=================================================================================== // This had to be optimized for speed, if it was just a loop using the above functions // that would have been too slow to be worth keeping. That's a bad thing about JASS // it is such an slow language that code reusability always has the cost of speed // function PoolAddPool takes integer sourcepoolid, integer destpoolid returns nothing local integer a=1 local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N] local integer dn=GetArrayInt( destpoolid,0) //[0:integer:N] local string sk=I2S(-sourcepoolid) local string k=I2S(-destpoolid) local integer v local string vk loop exitwhen (a>n) if (a>33) then set v=GetStoredInteger(cs_cache,sk,I2S(a)) else set v=GetArrayInt(sourcepoolid,a) endif set vk="#"+I2S(v) if not HaveStoredInteger(cs_cache,k,vk) then set dn=dn+1 call StoreInteger(cs_cache,k,vk,dn) if (dn>33) then call StoreInteger(cs_cache,k,I2S(dn),v) else call SetArrayInt(destpoolid,dn,v) endif endif set a=a+1 endloop call SetArrayInt(destpoolid,0,dn) //[0:integer:N] endfunction //============================================================================================= // Oh darn, After making PoolAddPool I don't feel like writting this one // All right I am at least make the get code // function PoolRemovePool takes integer sourcepoolid, integer destpoolid returns nothing local integer a=1 local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N] local integer v local string sk=I2S(-sourcepoolid) loop exitwhen a>n if (a>33) then set v=GetStoredInteger(cs_cache,sk,I2S(a) ) else set v=GetArrayInt(sourcepoolid,a) endif call PoolRemoveItem( destpoolid, v) set a=a+1 endloop endfunction //=================================================================================== // Adds a tokenized string to a pool, // Example: PoolAddS(udg_p, "1;2;3;4") will add to the udg_p pool : 1,2,3 and 4 // function PoolAddS takes integer poolid, string s returns nothing local integer i=0 local integer st local string c set s=s+";" set st=0 loop set c=SubString(s, i, i+1) exitwhen (c == "") or (c == null) if (c == ";") then call PoolAddItem( poolid, S2I(SubString(s, st, i)) ) set st=i+1 endif set i=i+1 endloop endfunction //=================================================================================== // Converts a tokenized string into a pool, // Example: S2Pool( "1;2;3;4") will return a pool that has 1,2,3 and 4 inside // function S2Pool takes string s returns integer local integer spool= CreatePool() call PoolAddS(spool,s) return spool endfunction //=================================================================================== // Does the opposite of S2Pool, debugging is a good use for this function. // function Pool2S takes integer P returns string local integer N=CountItemsInPool(P) local integer i local string s if (N>=1) then set s=I2S(PoolGetItem(P,1) ) set i=2 else return "" endif loop exitwhen (i>N) set s=s+";"+I2S(PoolGetItem(P,i)) set i=i+1 endloop return s endfunction //============================================================================================================= // Fixes a lame bug by blizzard related to the custom script section (The condition of the if statement might // actually be true. // function Pool_Percent takes nothing returns string if ("%"=="") then return "%%" endif return "%" endfunction function Pool_SetupCharMap takes nothing returns nothing local string cm=".................................!.#$"+Pool_Percent()+"&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................." local integer i=0 local string c if HaveStoredInteger(cs_cache,"charmap_upper","A") then return endif loop set c=SubString(cm,i,i+1) exitwhen (c==null) or (c=="") if (c!=".") then if c==StringCase(c,true) then call StoreInteger(cs_cache,"charmap_upper",c,i) else call StoreInteger(cs_cache,"charmap_lower",c,i) endif endif set i=i+1 endloop endfunction function Pool_Rawcode2Int takes string s returns integer local string c local integer i=0 local integer r=0 loop exitwhen i>3 set c=SubString(s,i,i+1) set r=r*256 if c==StringCase(c,true) then set r=r+GetStoredInteger(cs_cache,"charmap_upper",c) else set r=r+GetStoredInteger(cs_cache,"charmap_lower",c) endif set i=i+1 endloop return r endfunction function PoolAddRawcodes_thread takes nothing returns nothing //Threaded because I don't want it to halt execution for no reason // local string s=bj_lastPlayedMusic local integer poolid=bj_groupEnumTypeId local string c local integer i=0 local integer st=0 set s=s+";" loop set c=SubString(s, i, i+1) exitwhen (c == "") or (c == null) if c == ";" then call PoolAddItem(poolid, Pool_Rawcode2Int(SubString(s,st,i) )) set st=i+1 endif set i=i+1 endloop endfunction //===================================================================================================================== // Adds a string of tokenized rawcodes to a pool // Example: PoolAddRawcodes(udg_p,"A000;A001") will add 'A000' and 'A001' to the pool // // (Saves some lines, but is not as good efficiency wise) // function PoolAddRawcodes takes integer poolid, string s returns nothing local string b=bj_lastPlayedMusic set bj_groupEnumTypeId=poolid set bj_lastPlayedMusic=s call ExecuteFunc("PoolAddRawcodes_thread") set bj_lastPlayedMusic=b endfunction //=================================================================================================================== // Converts a tokenized string of rawcodes into a pool, // Example: Rawcodes2Pool( "A000;A001;AHbz;S000") will return a pool that has 'A000,'A001','AHbx' and 'S000' inside // // (Saves some lines, but is not as good efficiency wise) // function Rawcodes2Pool takes string s returns integer local integer spool= CreatePool() call PoolAddRawcodes(spool,s) return spool endfunction //=================================================================================================================== // A subproduct of the Pool's Rawcode support is that we can easily have this function so I am including it even if // it has nothing to do with data storage. // // takes "Aloc" and converts it into 'Aloc' // it is different to the Pool_Rawcode2Int function in that it is safe to use it when it is the first CSCache // function ever used. But it is a little slower (wc3mapoptimizer should make it as fast though) // function CS_Rawcode2Int takes string s returns integer local string c local integer i=0 local integer r=0 loop exitwhen i>3 set c=SubString(s,i,i+1) set r=r*256 if c==StringCase(c,true) then set r=r+GetStoredInteger(cs_cache,"charmap_upper",c) else set r=r+GetStoredInteger(cs_cache,"charmap_lower",c) endif set i=i+1 endloop return r endfunction function CSCache takes nothing returns gamecache return cs_cache //Left for compat. endfunction endlibrary //Forced by WE function InitTrig_CSCache takes nothing returns nothing endfunction |
| 09-05-2007, 10:29 PM | #9 |
Unfortuneately, I still get errors... If the jump template is enabled I still get the redeclared error. If I turn it off, I still get ONE instance of: JASS:return GetStoredInteger(CSCache() , I2S(CS_H2I(h)) , label) //Undeclared Function CSCache |
| 09-06-2007, 01:01 PM | #10 |
perhaps the unit u IS redeclared you should post the code for the jump template. can't you just manually change that CSCache() to cs_cache ? |
| 09-07-2007, 12:08 AM | #11 |
JASS://************************************************************************************************* //* //* Jump Template //* ¯¯¯¯¯¯¯¯¯¯¯¯¯ //* Requires: //* -A triggerer ability ( Point targetable please, //* was kind of specially designed for blink) //* -The Caster System //* -The Alternative Spell Templates System //* -This Trigger //* //* Art: //* - The Ability's Caster Art is attached to the unit while jumping and uses the second caster //* art as attachment point //* - If "UseOtherModel" is 1 , the Ability's Caster Art becomes the missile effect of the jump //* - The ability's effect art is played on impace //* - The ability's target art is used on targets. //* //************************************************************************************************* //=========================================================================== function JumpTemplateSetup takes nothing returns nothing local integer D //An integer variable we use later to save the Damage Options so we give them to the templates local integer s //An integer variable we use later to save the rawcodes of spells to save some time //=================================================================================================== // Template Info: // // Template Name Id = "JumpTemplate" // // Everything you need for a jump spell is here, it controls the jump effect and the things that // happen on the impact. // // // real "speed" The jump speed // real "arc" The jump arc // integer "UseOtherModel" If this option is 1, the template will use another model for the jump, // the behaviour of the jump is different and uses extra options: // (In this case the Caster Model is the model used) // // integer "OModelColor" The vertex color of the OtherModel (when UseOtherModel is 1) // It is in 0xAARRGGBB form // real "OModelScale" The scale of the Other Model // real "z1" The Launch height of the Other Model // real "z2" The Impact height of the Other Model // // (Last 4 options are only considered when UseOtherModel is 1 // // string "JumpAnim" This is considered when UseOtherModel is 0, and is the jump animation // string "EndAnim" The Animation after the jump // // * If you use numbers between quotes for the animations, they will play them as indexes // Example: "1" will make it play the animation indexed with 1 of the model // // real "AnimSpeed" The animation speed during the jump, "UseOtherModel" ignores this // (This is a factor) // // Next options are used on the impact: // // real "area" The Area of effect of the impact // integer "MaxTargets" Maximum number of targets affected by the impact // (only damage, periodic damage and Target spells consider this) // real "Damage" The damage done to targets // // real "PDmg" Periodic damage done to targets // real "PDmgPeriod" The Period of the Periodic Damage // real "PDmgDur" The duration of the Periodic Damage // // integer "Spell" The Spell to cast // integer "SpellKind" If it is 1, it is a unit targetable spell // integer "FromCenter" If it is 1, the casters will be spawned from the impact point // this is mostly an eye candy option when the spell to cast is unit // targetable and has a projectile or lightning effects. // integer "OrderId" The OrderId of the spell to cast // real "RecDelay" The recycle delay of the spell to cast // real "SpellHeight" The caster's height when casting the spell to cast // // integer "DamageOptions" Caster System Damage Options in saveable form, used to determine which units // can be affected by damage and targeteable spells, if the damage factor is 0 // The unit is not affected by the target spells nor damage, otherwise the value is // only important for damage. //=================================================================================================== // Jump template Defaults: // call SetTemplateDefaultInt( "JumpTemplate","MaxTargets",100) //Default max targets is 100 call SetTemplateDefaultReal( "JumpTemplate","speed" ,800) //Default speed is 800 call SetTemplateDefaultReal( "JumpTemplate","arc" ,0.25) //Default arc os 0.25 call SetTemplateDefaultInt( "JumpTemplate","OModelColor",0xFFFFFFFF) //Default other model's color is 255-255-255-255 call SetTemplateDefaultReal("JumpTemplate","OModelScale",1) //Default other model's scale is 1 call SetTemplateDefaultReal("JumpTemplate","z1",60) //Default other model's launch height is 60 call SetTemplateDefaultReal("JumpTemplate","z2",60) //Default other model's impact height is 60 call SetTemplateDefaultString("JumpTemplate","JumpAnim","attack slam") //Default jump animation is attack slam call SetTemplateDefaultString("JumpTemplate","EndAnim" ,"stand") //Default end animation is stand call SetTemplateDefaultReal( "JumpTemplate","AnimSpeed",1) //Default Animation Speed is 1 //=================================================================================================== // Earth Crush ('A02D') // set s=SetSpellTemplate('A02D',"JumpTemplate") //(Earth Crush doesn't need damage options) call SetAbilityDataInt(s ,"UseOtherModel",0,1) //Use another model call SetAbilityDataReal(s,"OModelScale" ,0,1.75) //Its scale is 1.75 call SetAbilityDataInt(s,"Spell" ,0,'A02E') //Spell to cast is A02E (Earth crush war stomp) call SetAbilityDataInt(s,"OrderId",0,OrderId("stomp")) //Its orderid is stomp call SetAbilityDataString(s,"EndAnim",0,"birth") //Play birth animation when jump ends //=================================================================================================== // Jet ('A02F') // set s=SetSpellTemplate('A02F',"JumpTemplate") //(Earth Crush doesn't need damage options) call SetAbilityDataReal(s, "speed", 1, 900) call SetAbilityDataReal(s, "speed", 2,1000) call SetAbilityDataReal(s, "speed", 3,1100) call SetAbilityDataReal(s, "arc", 0,0.5) call SetAbilityDataReal(s, "AnimSpeed", 0,4) //Double Animation Speed! call SetAbilityDataString(s,"JumpAnim",0,"3") //Play Animation index 3 //=================================================================================================== // Ability Preloading // // Next is unrelated to the templates system, just avoids the first time cast lag, here you // should preload any ability used as auxiliar ability for the template, just to avoid first // time cast lag. // call PreloadAbility('A02E') endfunction //=========================================================================== function JumpTemplate_OtherMissile takes player ow, string fx, integer s,integer l, location loc, location tar returns nothing local integer rgb=GetAbilityDataInt(s,l,"OModelColor") local integer Y=rgb+IntegerTertiaryOp(rgb<0,0x80000000,0) local integer Z local integer r local integer g local integer b set Z=Y/0x100 set b=Y-(Z*0x100) set Y=Z/0x100 set g=Z-(Y*0x100) set Z=Y/0x100 set r=Y-(Z*0x100) if (rgb<0) then set Z=Z+128 endif call ProjectileLaunchExLoc( ow, fx , GetAbilityDataReal(s,l,"OModelScale"), r,g,b,Z, GetAbilityDataReal(s,l,"speed"), GetAbilityDataReal(s,l,"arc"), loc, GetAbilityDataReal(s,l,"z1"), tar, GetAbilityDataReal(s,l,"z2") ) endfunction function JumpTemplate_Impact takes integer s, integer l, unit u, location loc returns nothing local unit u=GetTriggerUnit() //redeclared error here local player ow=GetOwningPlayer(u) local unit p local real fc local integer t=0 local integer ab=GetAbilityDataInt(s,l,"Spell") local real rec local string ord local real z1 local integer dop local group g=CreateGroup() local real nx=GetLocationX(loc) local real ny=GetLocationY(loc) local real dmg=GetAbilityDataReal(s,l,"Damage") local real dmgps=GetAbilityDataReal(s,l,"PDmg") local real period local real dur local integer i local integer mx=GetAbilityDataInt(s,l,"MaxTargets") local string fx=GetAbilityEffectById(s,EFFECT_TYPE_EFFECT,0) local string fxt=GetAbilityEffectById(s,EFFECT_TYPE_TARGET,0) local string fxta=GetAbilityEffectById(s,EFFECT_TYPE_TARGET,1) local boolean scf=(GetAbilityDataInt(s,l,"FromCenter")==1 ) local real area=GetAbilityDataReal(s,l,"area") if (ab!=0) then set t=GetAbilityDataInt(s,l,"SpellKind") set rec=GetAbilityDataReal(s,l,"RecDelay") set ord=I2S(GetAbilityDataInt(s,l,"OrderId")) set z1=GetAbilityDataReal(s,l,"SpellHeight") endif if (dmgps!=0) then set period=GetAbilityDataReal(s,l,"PDmgPeriod") set dur=GetAbilityDataReal(s,l,"PDmgDur") endif if ((fx!="") and (fx!=null)) then call DestroyEffect(AddSpecialEffect(fx,nx,ny)) endif set dop=LoadDamageOptions(GetAbilityDataInt(s,l,"DamageOptions")) if (((t==1) and (ab!=0)) or (dmg!=0) or (dmgps!=0)) then call GroupClear(g) call GroupEnumUnitsInRange(g,nx,ny,area ,null) endif if ((t==0) and (ab!=0)) then call CasterCastAbilityPointEx(ow,nx,ny,z1,ab,l,ord,nx,ny,rec) endif if (IsDamageOptionIncluded(dop,DamageTrees())) then call DamageTreesInCircle(nx,ny,area) endif set i=0 loop set p=FirstOfGroup(g) exitwhen ((p==null) or (i>=mx)) call GroupRemoveUnit(g,p) set fc=GetDamageFactorByOptions(u,p,dop) if (fc!=0) then if (dmg!=0) then call UnitDamageTarget(u,p,dmg*fc,true,false,null,null,null) endif if (dmgps!=0) then call UnitDamageUnitTimed(u,dmgps*fc,period,dur,p,fxt,fxta,null,null) elseif ((fxt!="") and (fxt!=null)) then call DestroyEffect(AddSpecialEffectTarget(fxt,p,fxta)) endif if ((ab!=0) and (t==1)) then if not(scf) then set nx=GetUnitX(p) set ny=GetUnitY(p) endif call CasterCastAbilityEx(ow,nx,ny,z1,ab,l,ord,p,rec) endif set i=i+1 endif endloop set ow=null set u=null set p=null set loc=null endfunction function JumpTemplate_AnimPlay takes unit u, string anim returns nothing local integer i=S2I(anim) if ((i>0) or (anim=="0")) then call SetUnitAnimationByIndex(u,i) else call SetUnitAnimation(u,anim) endif endfunction function JumpTemplate_PrepareUnit_X takes nothing returns nothing local timer t=GetExpiredTimer() local string k=GetAttachmentTable(t) local unit u=GetTableUnit(k,"u") local integer s=GetTableInt(k,"s") local integer l=GetTableInt(k,"l") call SetUnitTimeScale(u,GetAbilityDataReal(s,l,"AnimSpeed")) call JumpTemplate_AnimPlay(u,GetAbilityDataString(s,l,"JumpAnim")) call SetUnitPosition(u,GetTableReal(k,"x"),GetTableReal(k,"y")) call ShowUnit(u,true) call CS_KillTimer(t) set u=null set t=null endfunction function JumpTemplate_PrepareUnit takes unit u, real x, real y, integer s, integer l returns nothing local timer t=CreateTimer() local string k=GetAttachmentTable(t) call SetTableObject(k,"u",u) call SetTableReal(k,"x",x) call SetTableReal(k,"y",y) call SetTableInt(k,"s",s) call SetTableInt(k,"l",l) call TimerStart(t,0,false,function JumpTemplate_PrepareUnit_X) set t=null endfunction function JumpTemplate takes nothing returns nothing local unit u=GetTriggerUnit() local integer s=GetSpellAbilityId() local integer l=GetUnitAbilityLevel(u,s) local location target=GetSpellTargetLoc() local location loc=GetUnitLoc(u) local boolean sel=false local boolean mode= (GetAbilityDataInt(s,l,"UseOtherModel")==1) local string fx=GetAbilityEffectById(s,EFFECT_TYPE_CASTER,0) local real fh=GetUnitFlyHeight(u) local effect ffx set sel=IsUnitSelected(u, GetOwningPlayer(u) ) if mode then call ShowUnit(u, false) call JumpTemplate_OtherMissile(GetOwningPlayer(u),fx,s,l,loc,target) call SetUnitPosition(u,GetLocationX(target),GetLocationY(target)) call ShowUnit(u, true) else set ffx=AddSpecialEffectTarget(fx,u,GetAbilityEffectById(s,EFFECT_TYPE_CASTER,1)) call UnitAddAbility(u,ChangeableFlyingHeightAllowerId()) call UnitRemoveAbility(u,ChangeableFlyingHeightAllowerId()) call ShowUnit(u,false) call PauseUnit(u,true) call JumpTemplate_PrepareUnit(u,GetUnitX(u),GetUnitY(u),s,l) //Allows abilities like blink work with this correctly call UnitMoveToAsProjectileAnySpeed(u,GetAbilityDataReal(s,l,"speed"),GetAbilityDataReal(s,l,"arc") , GetLocationX(target),GetLocationY(target),null,fh) call SetUnitPosition(u,GetLocationX(target),GetLocationY(target)) call SetUnitTimeScale(u,1) call PauseUnit(u,false) call DestroyEffect(ffx) set ffx=null endif call SetUnitFlyHeight(u,fh,0) if (GetWidgetLife(u)>=1) then call JumpTemplate_Impact(s,l,u,target) call JumpTemplate_AnimPlay(u,GetAbilityDataString(s,l,"EndAnim") ) call QueueUnitAnimation(u,"stand") if sel then call SelectUnitAddForPlayer( u, GetOwningPlayer(u) ) endif endif call RemoveLocation(loc) call RemoveLocation(target) set u=null set loc=null set target=null endfunction //=========================================================================== function InitTrig_Jump_Template takes nothing returns nothing call ExecuteFunc("JumpTemplateSetup") //Must use ExecuteFunc to prevent the Map init thread from getting too long and crash. endfunction The spell works fine in your map, not sure whats wrong. |
| 09-07-2007, 02:43 AM | #12 |
Like I thought the code of the jump template is wrong. the thing is that Jasshelper + PJass make a much more strict compiler than WE's so things that could compile before (yet are totally wrong) cannot compile again: JASS://************************************************************************************************* //* //* Jump Template //* ¯¯¯¯¯¯¯¯¯¯¯¯¯ //* Requires: //* -A triggerer ability ( Point targetable please, //* was kind of specially designed for blink) //* -The Caster System //* -The Alternative Spell Templates System //* -This Trigger //* //* Art: //* - The Ability's Caster Art is attached to the unit while jumping and uses the second caster //* art as attachment point //* - If "UseOtherModel" is 1 , the Ability's Caster Art becomes the missile effect of the jump //* - The ability's effect art is played on impace //* - The ability's target art is used on targets. //* //************************************************************************************************* //=========================================================================== function JumpTemplateSetup takes nothing returns nothing local integer D //An integer variable we use later to save the Damage Options so we give them to the templates local integer s //An integer variable we use later to save the rawcodes of spells to save some time //=================================================================================================== // Template Info: // // Template Name Id = "JumpTemplate" // // Everything you need for a jump spell is here, it controls the jump effect and the things that // happen on the impact. // // // real "speed" The jump speed // real "arc" The jump arc // integer "UseOtherModel" If this option is 1, the template will use another model for the jump, // the behaviour of the jump is different and uses extra options: // (In this case the Caster Model is the model used) // // integer "OModelColor" The vertex color of the OtherModel (when UseOtherModel is 1) // It is in 0xAARRGGBB form // real "OModelScale" The scale of the Other Model // real "z1" The Launch height of the Other Model // real "z2" The Impact height of the Other Model // // (Last 4 options are only considered when UseOtherModel is 1 // // string "JumpAnim" This is considered when UseOtherModel is 0, and is the jump animation // string "EndAnim" The Animation after the jump // // * If you use numbers between quotes for the animations, they will play them as indexes // Example: "1" will make it play the animation indexed with 1 of the model // // real "AnimSpeed" The animation speed during the jump, "UseOtherModel" ignores this // (This is a factor) // // Next options are used on the impact: // // real "area" The Area of effect of the impact // integer "MaxTargets" Maximum number of targets affected by the impact // (only damage, periodic damage and Target spells consider this) // real "Damage" The damage done to targets // // real "PDmg" Periodic damage done to targets // real "PDmgPeriod" The Period of the Periodic Damage // real "PDmgDur" The duration of the Periodic Damage // // integer "Spell" The Spell to cast // integer "SpellKind" If it is 1, it is a unit targetable spell // integer "FromCenter" If it is 1, the casters will be spawned from the impact point // this is mostly an eye candy option when the spell to cast is unit // targetable and has a projectile or lightning effects. // integer "OrderId" The OrderId of the spell to cast // real "RecDelay" The recycle delay of the spell to cast // real "SpellHeight" The caster's height when casting the spell to cast // // integer "DamageOptions" Caster System Damage Options in saveable form, used to determine which units // can be affected by damage and targeteable spells, if the damage factor is 0 // The unit is not affected by the target spells nor damage, otherwise the value is // only important for damage. //=================================================================================================== // Jump template Defaults: // call SetTemplateDefaultInt( "JumpTemplate","MaxTargets",100) //Default max targets is 100 call SetTemplateDefaultReal( "JumpTemplate","speed" ,800) //Default speed is 800 call SetTemplateDefaultReal( "JumpTemplate","arc" ,0.25) //Default arc os 0.25 call SetTemplateDefaultInt( "JumpTemplate","OModelColor",0xFFFFFFFF) //Default other model's color is 255-255-255-255 call SetTemplateDefaultReal("JumpTemplate","OModelScale",1) //Default other model's scale is 1 call SetTemplateDefaultReal("JumpTemplate","z1",60) //Default other model's launch height is 60 call SetTemplateDefaultReal("JumpTemplate","z2",60) //Default other model's impact height is 60 call SetTemplateDefaultString("JumpTemplate","JumpAnim","attack slam") //Default jump animation is attack slam call SetTemplateDefaultString("JumpTemplate","EndAnim" ,"stand") //Default end animation is stand call SetTemplateDefaultReal( "JumpTemplate","AnimSpeed",1) //Default Animation Speed is 1 //=================================================================================================== // Earth Crush ('A02D') // set s=SetSpellTemplate('A02D',"JumpTemplate") //(Earth Crush doesn't need damage options) call SetAbilityDataInt(s ,"UseOtherModel",0,1) //Use another model call SetAbilityDataReal(s,"OModelScale" ,0,1.75) //Its scale is 1.75 call SetAbilityDataInt(s,"Spell" ,0,'A02E') //Spell to cast is A02E (Earth crush war stomp) call SetAbilityDataInt(s,"OrderId",0,OrderId("stomp")) //Its orderid is stomp call SetAbilityDataString(s,"EndAnim",0,"birth") //Play birth animation when jump ends //=================================================================================================== // Jet ('A02F') // set s=SetSpellTemplate('A02F',"JumpTemplate") //(Earth Crush doesn't need damage options) call SetAbilityDataReal(s, "speed", 1, 900) call SetAbilityDataReal(s, "speed", 2,1000) call SetAbilityDataReal(s, "speed", 3,1100) call SetAbilityDataReal(s, "arc", 0,0.5) call SetAbilityDataReal(s, "AnimSpeed", 0,4) //Double Animation Speed! call SetAbilityDataString(s,"JumpAnim",0,"3") //Play Animation index 3 //=================================================================================================== // Ability Preloading // // Next is unrelated to the templates system, just avoids the first time cast lag, here you // should preload any ability used as auxiliar ability for the template, just to avoid first // time cast lag. // call PreloadAbility('A02E') endfunction //=========================================================================== function JumpTemplate_OtherMissile takes player ow, string fx, integer s,integer l, location loc, location tar returns nothing local integer rgb=GetAbilityDataInt(s,l,"OModelColor") local integer Y=rgb+IntegerTertiaryOp(rgb<0,0x80000000,0) local integer Z local integer r local integer g local integer b set Z=Y/0x100 set b=Y-(Z*0x100) set Y=Z/0x100 set g=Z-(Y*0x100) set Z=Y/0x100 set r=Y-(Z*0x100) if (rgb<0) then set Z=Z+128 endif call ProjectileLaunchExLoc( ow, fx , GetAbilityDataReal(s,l,"OModelScale"), r,g,b,Z, GetAbilityDataReal(s,l,"speed"), GetAbilityDataReal(s,l,"arc"), loc, GetAbilityDataReal(s,l,"z1"), tar, GetAbilityDataReal(s,l,"z2") ) endfunction function JumpTemplate_Impact takes integer s, integer l, unit u, location loc returns nothing local player ow=GetOwningPlayer(u) local unit p local real fc local integer t=0 local integer ab=GetAbilityDataInt(s,l,"Spell") local real rec local string ord local real z1 local integer dop local group g=CreateGroup() local real nx=GetLocationX(loc) local real ny=GetLocationY(loc) local real dmg=GetAbilityDataReal(s,l,"Damage") local real dmgps=GetAbilityDataReal(s,l,"PDmg") local real period local real dur local integer i local integer mx=GetAbilityDataInt(s,l,"MaxTargets") local string fx=GetAbilityEffectById(s,EFFECT_TYPE_EFFECT,0) local string fxt=GetAbilityEffectById(s,EFFECT_TYPE_TARGET,0) local string fxta=GetAbilityEffectById(s,EFFECT_TYPE_TARGET,1) local boolean scf=(GetAbilityDataInt(s,l,"FromCenter")==1 ) local real area=GetAbilityDataReal(s,l,"area") if (ab!=0) then set t=GetAbilityDataInt(s,l,"SpellKind") set rec=GetAbilityDataReal(s,l,"RecDelay") set ord=I2S(GetAbilityDataInt(s,l,"OrderId")) set z1=GetAbilityDataReal(s,l,"SpellHeight") endif if (dmgps!=0) then set period=GetAbilityDataReal(s,l,"PDmgPeriod") set dur=GetAbilityDataReal(s,l,"PDmgDur") endif if ((fx!="") and (fx!=null)) then call DestroyEffect(AddSpecialEffect(fx,nx,ny)) endif set dop=LoadDamageOptions(GetAbilityDataInt(s,l,"DamageOptions")) if (((t==1) and (ab!=0)) or (dmg!=0) or (dmgps!=0)) then call GroupClear(g) call GroupEnumUnitsInRange(g,nx,ny,area ,null) endif if ((t==0) and (ab!=0)) then call CasterCastAbilityPointEx(ow,nx,ny,z1,ab,l,ord,nx,ny,rec) endif if (IsDamageOptionIncluded(dop,DamageTrees())) then call DamageTreesInCircle(nx,ny,area) endif set i=0 loop set p=FirstOfGroup(g) exitwhen ((p==null) or (i>=mx)) call GroupRemoveUnit(g,p) set fc=GetDamageFactorByOptions(u,p,dop) if (fc!=0) then if (dmg!=0) then call UnitDamageTarget(u,p,dmg*fc,true,false,null,null,null) endif if (dmgps!=0) then call UnitDamageUnitTimed(u,dmgps*fc,period,dur,p,fxt,fxta,null,null) elseif ((fxt!="") and (fxt!=null)) then call DestroyEffect(AddSpecialEffectTarget(fxt,p,fxta)) endif if ((ab!=0) and (t==1)) then if not(scf) then set nx=GetUnitX(p) set ny=GetUnitY(p) endif call CasterCastAbilityEx(ow,nx,ny,z1,ab,l,ord,p,rec) endif set i=i+1 endif endloop set ow=null set u=null set p=null set loc=null endfunction function JumpTemplate_AnimPlay takes unit u, string anim returns nothing local integer i=S2I(anim) if ((i>0) or (anim=="0")) then call SetUnitAnimationByIndex(u,i) else call SetUnitAnimation(u,anim) endif endfunction function JumpTemplate_PrepareUnit_X takes nothing returns nothing local timer t=GetExpiredTimer() local string k=GetAttachmentTable(t) local unit u=GetTableUnit(k,"u") local integer s=GetTableInt(k,"s") local integer l=GetTableInt(k,"l") call SetUnitTimeScale(u,GetAbilityDataReal(s,l,"AnimSpeed")) call JumpTemplate_AnimPlay(u,GetAbilityDataString(s,l,"JumpAnim")) call SetUnitPosition(u,GetTableReal(k,"x"),GetTableReal(k,"y")) call ShowUnit(u,true) call CS_KillTimer(t) set u=null set t=null endfunction function JumpTemplate_PrepareUnit takes unit u, real x, real y, integer s, integer l returns nothing local timer t=CreateTimer() local string k=GetAttachmentTable(t) call SetTableObject(k,"u",u) call SetTableReal(k,"x",x) call SetTableReal(k,"y",y) call SetTableInt(k,"s",s) call SetTableInt(k,"l",l) call TimerStart(t,0,false,function JumpTemplate_PrepareUnit_X) set t=null endfunction function JumpTemplate takes nothing returns nothing local unit u=GetTriggerUnit() local integer s=GetSpellAbilityId() local integer l=GetUnitAbilityLevel(u,s) local location target=GetSpellTargetLoc() local location loc=GetUnitLoc(u) local boolean sel=false local boolean mode= (GetAbilityDataInt(s,l,"UseOtherModel")==1) local string fx=GetAbilityEffectById(s,EFFECT_TYPE_CASTER,0) local real fh=GetUnitFlyHeight(u) local effect ffx set sel=IsUnitSelected(u, GetOwningPlayer(u) ) if mode then call ShowUnit(u, false) call JumpTemplate_OtherMissile(GetOwningPlayer(u),fx,s,l,loc,target) call SetUnitPosition(u,GetLocationX(target),GetLocationY(target)) call ShowUnit(u, true) else set ffx=AddSpecialEffectTarget(fx,u,GetAbilityEffectById(s,EFFECT_TYPE_CASTER,1)) call UnitAddAbility(u,ChangeableFlyingHeightAllowerId()) call UnitRemoveAbility(u,ChangeableFlyingHeightAllowerId()) call ShowUnit(u,false) call PauseUnit(u,true) call JumpTemplate_PrepareUnit(u,GetUnitX(u),GetUnitY(u),s,l) //Allows abilities like blink work with this correctly call UnitMoveToAsProjectileAnySpeed(u,GetAbilityDataReal(s,l,"speed"),GetAbilityDataReal(s,l,"arc") , GetLocationX(target),GetLocationY(target),null,fh) call SetUnitPosition(u,GetLocationX(target),GetLocationY(target)) call SetUnitTimeScale(u,1) call PauseUnit(u,false) call DestroyEffect(ffx) set ffx=null endif call SetUnitFlyHeight(u,fh,0) if (GetWidgetLife(u)>=1) then call JumpTemplate_Impact(s,l,u,target) call JumpTemplate_AnimPlay(u,GetAbilityDataString(s,l,"EndAnim") ) call QueueUnitAnimation(u,"stand") if sel then call SelectUnitAddForPlayer( u, GetOwningPlayer(u) ) endif endif call RemoveLocation(loc) call RemoveLocation(target) set u=null set loc=null set target=null endfunction //=========================================================================== function InitTrig_Jump_Template takes nothing returns nothing call ExecuteFunc("JumpTemplateSetup") //Must use ExecuteFunc to prevent the Map init thread from getting too long and crash. endfunction |
| 09-07-2007, 03:35 AM | #13 |
Thanks! Everything is now saving properly. If I experience trouble with any of the abilities, I will let you know. |
