Warcraft 3 documentation
vJASS & Zinc Documentation
For the latest documentation about how it works vJASS and Zinc language layers for Warcraft III, please follow these links:
Jasshelper documentation - Zinc documentation - WC3 Optimizer documentation

Faux HandleVars & CSCache No New Posts Codes & Snippets

Started by
moyack

0 Members and 1 Guest are viewing this topic.

Faux HandleVars & CSCache
on: December 09, 2010, 09:01:10 AM
Category: Execution, Variables
Language: vJASS
Download Demo Map

This is the closest you could reproduce Handle Vars' functionality and interface in (currently westfall) patch 1.24, requires jasshelper 0.9.H.2 and patch 1.24 or later.

Are intended so implementing these handle vars in your map should be able to replace Handle Vars functionality, however, in some odd cases in which you do very odd stuff it won't work (will raise compiler errors), those cases should be rare.

Faux Handle Vars do not have the I2H-related issues that plagued original handle vars, should also be mildly faster (I still recommend AgentVars for a better speed improvement, or even better, structs). However, I do not recommend these functions for anything other than porting old code to patch 1.24. It is because this interface is very leak-friendly (these leaks are also very common in code that uses handle vars, and are almost by-design) Although the leaks weren't a big issue for most maps using Handle vars (not even DOTA) they are still undesirable...

Faux CSCache works the same, except in some cases they might not work 100% well because of how in CSCache you were allowed to use inline gamecache calls and other retardedness... do notice that Faux CSCache will leak memory like ... well, like something that leaks a lot of memory...

CSCache has worked to make spell factory and also some other spell maps work again (once you also move CS to 16.0)
Due to blizzard's failed failedness, You may find some cases like:

Code: jass
  1.     call AttachObject( meh, "...", #TriggerAddAction(t, function ff)# )
  2.  
These lines will cause a syntax error, why? Because blizzard for some INCREDIBLY STUPID reason didn't make triggeraction extend agent in common.j

The fix for that would be something like:
Code: jass
  1.     call AttachObject( meh, "...", null )
  2.     call TriggerAddAction(t, function ff)
  3.  


Differences between these handle vars and the original ones
They are called handle vars and have function names like SetHandleHandle just for the reason of compatibility, in reality, you can only use these functions to attach stuff to objects of the agent type. SetHandleHandle is only able to attach agents. I.E you cannot use SetHandleHandle to attach a lightning effect, would have to use SetHandleLightning instead) Since GetHandleHandle is basically impossible (even one that returns agent) it has been removed.

Faux Handle Vars
Code: jass
  1. /*******************************************************************************************
  2.  Faux Handle Vars
  3.  ----------------
  4.     Do not use these functions for new stuff, it is just not the right thing to do...
  5.  
  6.     The intention of Faux Handle Vars is to be a patch fix for a map's migration to
  7.   patch 1.24 This library might not cover all uses of handle vars, some of them are just
  8.   impossible with the new rules set in patches 1.23b and 1.24, but they should work for
  9.   most of the cases....
  10.  
  11.     All of them but the SetHandle*** ones are inline friendly. I follow the interface
  12.   in official Kattana's handle vars from wc3jass.com, if your handle vars functions
  13.   look different, then you were not using handle vars but another thing...
  14.  
  15. *******************************************************************************************/
  16.  
  17. //==========================================================================================
  18. library HandleVars initializer init
  19.  
  20.  globals
  21.     private hashtable ht
  22.  endglobals
  23.  
  24.     // too bad the Handle vars' old functionality forces me to make these things
  25.     // inline-unfriendly
  26.     function SetHandleHandle takes agent subject,  string label, agent value returns nothing
  27.         if(value==null) then
  28.             call RemoveSavedHandle( ht, GetHandleId(subject), StringHash(label))
  29.         else
  30.             call SaveAgentHandle( ht, GetHandleId(subject), StringHash(label), value)
  31.         endif
  32.     endfunction
  33.  
  34.     function SetHandleInt takes agent subject, string label, integer value returns nothing
  35.         if value==0 then
  36.             call RemoveSavedInteger(ht, GetHandleId(subject), StringHash(label))
  37.         else
  38.             call SaveInteger(ht, GetHandleId(subject), StringHash(label), value)
  39.         endif       
  40.     endfunction
  41.  
  42.     function SetHandleBoolean takes agent subject, string label, boolean value returns nothing
  43.         if (value == false) then
  44.             call RemoveSavedBoolean(ht, GetHandleId(subject), StringHash(label))
  45.         else
  46.             call SaveBoolean(ht, GetHandleId(subject), StringHash(label), value)
  47.         endif
  48.     endfunction
  49.  
  50.     function SetHandleReal takes agent subject, string label, real value returns nothing
  51.         if (value == 0.0) then
  52.             call RemoveSavedReal(ht, GetHandleId(subject), StringHash(label))
  53.         else
  54.             call SaveReal(ht, GetHandleId(subject), StringHash(label), value)
  55.         endif
  56.     endfunction
  57.  
  58.     function SetHandleString takes agent subject, string label, string value returns nothing
  59.         if ((value=="") or (value==null)) then
  60.             call RemoveSavedString(ht, GetHandleId(subject), StringHash(label))
  61.         else
  62.             call SaveStr(ht, GetHandleId(subject), StringHash(label), value) //yay for blizz' consistent naming scheme...
  63.         endif
  64.     endfunction
  65.  
  66.     function GetHandleHandle takes agent subject, string label returns agent
  67.         debug call BJDebugMsg("[debug] What the heck? Why would you call HandleHandle I guess this was caused by a search and replace mistake")
  68.         return null
  69.     endfunction
  70.  
  71.     // these are inline friendly, ok, maybe they aren't because jasshelper does not recognize
  72.     // GetHandleId as non-state changing. But they will be once I fix jasshelper...
  73.  
  74.     function GetHandleInt takes agent subject, string label returns integer
  75.         return LoadInteger(ht, GetHandleId(subject), StringHash(label))
  76.     endfunction
  77.  
  78.     function GetHandleBoolean takes agent subject, string label returns boolean
  79.         return LoadBoolean(ht, GetHandleId(subject), StringHash(label))
  80.     endfunction
  81.  
  82.     function GetHandleString takes agent subject, string label returns string
  83.         return LoadStr(ht, GetHandleId(subject), StringHash(label))
  84.     endfunction
  85.  
  86.     function GetHandleReal takes agent subject, string label returns real
  87.         return LoadReal(ht, GetHandleId(subject), StringHash(label))
  88.     endfunction
  89.  
  90.     // got bored so I now use a textmacro...
  91.     //! textmacro FAUX_HANDLE_VARS_GetHandleHandle takes NAME, TYPE
  92.          function SetHandle$NAME$ takes agent subject,  string label, $TYPE$ value returns nothing
  93.              if(value==null) then
  94.                 call RemoveSavedHandle( ht, GetHandleId(subject), StringHash(label))
  95.              else
  96.                 call Save$NAME$Handle( ht, GetHandleId(subject), StringHash(label), value)
  97.              endif
  98.          endfunction
  99.  
  100.          function GetHandle$NAME$ takes agent subject, string label returns $TYPE$
  101.              return Load$NAME$Handle( ht, GetHandleId(subject), StringHash(label))
  102.          endfunction
  103.     //! endtextmacro
  104.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Player","player")
  105.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Widget","widget")
  106.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Destructable","destructable")
  107.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Item","item")
  108.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Unit","unit")
  109.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Ability","ability")
  110.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Timer","timer")
  111.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Trigger","trigger")
  112.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TriggerCondition","triggercondition")
  113.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TriggerAction","triggeraction")
  114.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TriggerEvent","event")
  115.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Force","force")
  116.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Group","group")
  117.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Location","location")
  118.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Rect","rect")
  119.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("BooleanExpr","boolexpr")
  120.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Sound","sound")
  121.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Effect","effect")
  122.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("UnitPool","unitpool")
  123.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("ItemPool","itempool")
  124.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Quest","quest")
  125.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("QuestItem","questitem")
  126.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("DefeatCondition","defeatcondition")
  127.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TimerDialog","timerdialog")
  128.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Leaderboard","leaderboard")
  129.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Multiboard","multiboard")
  130.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("MultiboardItem","multiboarditem")
  131.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Trackable","trackable")
  132.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Dialog","dialog")
  133.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Button","button")
  134.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("TextTag","texttag")
  135.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Lightning","lightning")
  136.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Image","image")
  137.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Ubersplat","ubersplat")
  138.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Region","region")
  139.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("FogState","fogstate")
  140.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("FogModifier","fogmodifier")
  141.     //! runtextmacro FAUX_HANDLE_VARS_GetHandleHandle("Hashtable","hashtable")
  142.  
  143.  
  144.     function FlushHandleVars takes agent subject returns nothing
  145.         call FlushChildHashtable(ht, GetHandleId(subject))
  146.     endfunction
  147.     function FlushHandleLocals takes agent subject returns nothing
  148.         call FlushHandleVars(subject)
  149.     endfunction
  150.  
  151.  
  152.     private function init takes nothing returns nothing
  153.         set ht=InitHashtable()
  154.     endfunction
  155.  
  156. endlibrary
  157.  

Faux CSCache
Code: jass
  1. /*******************************************************************************************
  2.  Faux CSCache AttachVars
  3.  ----------------
  4.     Do not use these functions for new stuff, it is just not the right thing to do...
  5.  
  6.     The intention of Faux CSCache  is to be a patch fix for a map's migration to
  7.   patch 1.24 This library might not cover all uses of handle vars, some of them are just
  8.   impossible with the new rules set in patches 1.23b and 1.24, but they should work for
  9.   most of the cases....
  10.  
  11. *******************************************************************************************/
  12.  
  13. //==========================================================================================
  14. library CSCache initializer init requires CSSafeCache
  15.  
  16.  globals
  17.     private hashtable ht
  18.  endglobals
  19.  
  20.  
  21.     // too bad the Handle vars' old functionality forces me to make these things
  22.     // inline-unfriendly
  23.     function SetTableObject takes string subject,  string label, agent value returns nothing
  24.         if(value==null) then
  25.             call RemoveSavedHandle( ht, StringHash(subject), StringHash(label))
  26.         else
  27.             call SaveAgentHandle( ht, StringHash(subject), StringHash(label), value)
  28.         endif
  29.     endfunction
  30.  
  31.  
  32.  
  33.  
  34.     function GetTableHandle takes string subject, string label returns agent
  35.         debug call BJDebugMsg("[debug] What the heck? Why would you call HandleHandle I guess this was caused by a search and replace mistake")
  36.         return null
  37.     endfunction
  38.  
  39.     // these are inline friendly, ok, maybe they aren't because jasshelper does not recognize
  40.     // GetHandleId as non-state changing. But they will be once I fix jasshelper...
  41.  
  42.  
  43.  
  44.     // got bored so I now use a textmacro...
  45.     //! textmacro FAUX_HANDLE_VARS_GetTableHandle takes NAME, TYPE
  46.          function SetTable$NAME$ takes string subject,  string label, $TYPE$ value returns nothing
  47.              if(value==null) then
  48.                 call RemoveSavedHandle( ht, StringHash(subject), StringHash(label))
  49.              else
  50.                 call Save$NAME$Handle( ht, StringHash(subject), StringHash(label), value)
  51.              endif
  52.          endfunction
  53.  
  54.          function GetTable$NAME$ takes string subject, string label returns $TYPE$
  55.              return Load$NAME$Handle( ht, StringHash(subject), StringHash(label))
  56.          endfunction
  57.     //! endtextmacro
  58.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Player","player")
  59.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Widget","widget")
  60.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Destructable","destructable")
  61.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Item","item")
  62.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Unit","unit")
  63.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Ability","ability")
  64.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Timer","timer")
  65.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Trigger","trigger")
  66.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TriggerCondition","triggercondition")
  67.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TriggerAction","triggeraction")
  68.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TriggerEvent","event")
  69.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Force","force")
  70.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Group","group")
  71.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Location","location")
  72.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Rect","rect")
  73.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("BooleanExpr","boolexpr")
  74.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Sound","sound")
  75.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Effect","effect")
  76.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("UnitPool","unitpool")
  77.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("ItemPool","itempool")
  78.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Quest","quest")
  79.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("QuestItem","questitem")
  80.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("DefeatCondition","defeatcondition")
  81.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TimerDialog","timerdialog")
  82.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Leaderboard","leaderboard")
  83.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Multiboard","multiboard")
  84.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("MultiboardItem","multiboarditem")
  85.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Trackable","trackable")
  86.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Dialog","dialog")
  87.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Button","button")
  88.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("TextTag","texttag")
  89.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Lightning","lightning")
  90.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Image","image")
  91.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Ubersplat","ubersplat")
  92.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Region","region")
  93.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("FogState","fogstate")
  94.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("FogModifier","fogmodifier")
  95.     //! runtextmacro FAUX_HANDLE_VARS_GetTableHandle("Hashtable","hashtable")
  96.  
  97.     function CS_KillTrigger takes trigger t returns nothing
  98.     // let em leak
  99.     endfunction
  100.  
  101.     // too bad the Handle vars' old functionality forces me to make these things
  102.     // inline-unfriendly
  103.     function AttachObject takes agent subject,  string label, agent value returns nothing
  104.         call SetTableObject( GetAttachmentTable(subject) , label, value)
  105.     endfunction
  106.  
  107.  
  108.  
  109.  
  110.     function GetAttachedHandle takes agent subject, string label returns agent
  111.         debug call BJDebugMsg("[debug] What the heck? Why would you call HandleHandle I guess this was caused by a search and replace mistake")
  112.         return null
  113.     endfunction
  114.  
  115.     // these are inline friendly, ok, maybe they aren't because jasshelper does not recognize
  116.     // GetHandleId as non-state changing. But they will be once I fix jasshelper...
  117.  
  118.  
  119.  
  120.     // got bored so I now use a textmacro...
  121.     //! textmacro FAUX_HANDLE_VARS_GetAttachedHandle takes NAME, TYPE
  122.          function Attach$NAME$ takes agent subject,  string label, $TYPE$ value returns nothing
  123.              call SetTable$NAME$( GetAttachmentTable(subject), label, value)
  124.          endfunction
  125.  
  126.          function GetAttached$NAME$ takes agent subject, string label returns $TYPE$
  127.              return GetTable$NAME$( GetAttachmentTable(subject), label)
  128.          endfunction
  129.     //! endtextmacro
  130.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Player","player")
  131.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Widget","widget")
  132.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Destructable","destructable")
  133.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Item","item")
  134.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Unit","unit")
  135.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Ability","ability")
  136.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Timer","timer")
  137.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Trigger","trigger")
  138.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TriggerCondition","triggercondition")
  139.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TriggerAction","triggeraction")
  140.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TriggerEvent","event")
  141.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Force","force")
  142.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Group","group")
  143.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Location","location")
  144.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Rect","rect")
  145.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("BooleanExpr","boolexpr")
  146.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Sound","sound")
  147.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Effect","effect")
  148.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("UnitPool","unitpool")
  149.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("ItemPool","itempool")
  150.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Quest","quest")
  151.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("QuestItem","questitem")
  152.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("DefeatCondition","defeatcondition")
  153.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TimerDialog","timerdialog")
  154.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Leaderboard","leaderboard")
  155.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Multiboard","multiboard")
  156.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("MultiboardItem","multiboarditem")
  157.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Trackable","trackable")
  158.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Dialog","dialog")
  159.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Button","button")
  160.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("TextTag","texttag")
  161.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Lightning","lightning")
  162.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Image","image")
  163.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Ubersplat","ubersplat")
  164.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Region","region")
  165.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("FogState","fogstate")
  166.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("FogModifier","fogmodifier")
  167.     //! runtextmacro FAUX_HANDLE_VARS_GetAttachedHandle("Hashtable","hashtable")
  168.    
  169.    
  170.     private function init takes nothing returns nothing
  171.         set ht=InitHashtable()
  172.     endfunction
  173.  
  174. endlibrary
  175.  
  176.  


Pyrogasm recommendations
For anyone attempting to use the Faux CSCache system:

You will need two additional libraries from Vex's original CasterSystem. They are CSSafeCache and CSData. Their code is below and all 3 libraries are in the attached map to show how they should be implemented.

CSData
Code: jass
  1. library CSData initializer init
  2.  
  3.     //****************************************************************************************************
  4.     // CSData 16.0
  5.     // ¯¯¯¯¯¯¯¯¯¯¯
  6.     // CSDatas are like UserData in units and items, they now use a hashtable instead of big arrays,
  7.     // should be faster and safer
  8.     //
  9.     // Notice that for public spells or systems to be distributed you should only use these
  10.     // for private objects (those who the mapper would never have access to) If you are making something
  11.     // for your map you can use them wherever you want.
  12.     //
  13.     // Best to be used in conjunction to CSArrays so you just specify an array id for a handle.
  14.     //
  15.     // DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag,
  16.     //                                        -any 'argument' handle (like playerstate, damagetype, etc)
  17.     //
  18.     //****************************************************************************************************
  19.  
  20.     //====================================================================================================
  21.     globals
  22.         private constant integer MAX_HANDLE_ID_COUNT = 408000
  23.         // values lower than 8191: very fast, but very unsafe.
  24.         // values bigger than 8191: not that fast, the bigger the number is the slower the function gets
  25.         // Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
  26.         // as the rather inflated value of 408000
  27.     endglobals
  28.  
  29.     //=================================================================================================
  30.     // a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems, it then stayed that
  31.     // instead of changing to a private or public function since many outside spells use it.
  32.     //
  33.     function CS_H2I takes handle h returns integer //For compat
  34.         return GetHandleId(h)                      //
  35.     endfunction                                    //
  36.  
  37.     //==================================================================================================
  38.     globals
  39.         private hashtable ht
  40.     endglobals
  41.  
  42.     //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
  43.     function SetCSData takes handle h, integer v returns nothing
  44.         call SaveInteger(ht , 0, GetHandleId(h) , v)
  45.     endfunction
  46.  
  47.     function GetCSData takes handle h returns integer
  48.         return LoadInteger( ht, 0, GetHandleId(h) )
  49.     endfunction
  50.  
  51.     private function init takes nothing returns nothing
  52.         set ht = InitHashtable()
  53.     endfunction
  54.  
  55. endlibrary

CSSafeCache
Code: jass
  1. library CSSafeCache initializer init requires CSData
  2.     //*************************************************************************************************
  3.     //*                                                                                               *
  4.     //* CSSafeCache 15.3                       [url]http://wc3campaigns.net/vexorian[/url]                       *
  5.     //* ¯¯¯¯¯¯¯                                                                                       *
  6.     //*    CSCache is evil now, use just CSSafeCache when possible as it now contains all functions   *
  7.     //* that do not use I2H or similar functions that are considered to cause unstability in the map  *
  8.     //*                                                                                               *
  9.     //*    CSCache has been deprecated, and is now unusuable since it can't be ported to patch 1.23b  *
  10.     //* Migration from CSCache to CSSafeCache+structs should be easy                                  *
  11.     //*                                                                                               *
  12.     //* However, for old compatibility, CSSafeCache needs to stick to using gamecache, which is not   *
  13.     //* as good as hashtable (it is slower and may be vulnerable to Sync attacks) I recommend         *
  14.     //* switching from CSSafeCache to hashtable or Table                                              *
  15.     //*                                                                                               *
  16.     //*************************************************************************************************
  17.  
  18.     //=================================================================================================
  19.     // CSSafeCache globals:
  20.     //
  21.     globals
  22.  
  23.         gamecache     cs_cache   = null
  24.         integer array cs_array1
  25.         integer array cs_array3
  26.         integer array cs_array2
  27.         private integer array cs_freeindexes
  28.         private integer array cs_pairx
  29.         private integer array cs_pairy
  30.         private integer array cs_freepairs
  31.  
  32.     endglobals
  33.  
  34.     private function init takes nothing returns nothing
  35.     // CSSafeCache initializer :
  36.         call FlushGameCache(InitGameCache("cscache"))
  37.         set cs_cache=InitGameCache("cscache")
  38.         call ExecuteFunc("InitArrayIndexes")
  39.         call ExecuteFunc("Pool_SetupCharMap")
  40.     endfunction
  41.  
  42.  
  43.     //=================================================================================================================
  44.     // CS Pairs
  45.     // ¯¯¯¯¯¯¯¯
  46.     // This is a sub system to assist csarrays, you can use them but CSArrays of size 2 have the same functionality
  47.     // although cspairs are be faster their space is limited and will start using gamecache if abused
  48.     //
  49.     function NewPair takes integer x, integer y returns integer
  50.      local integer i
  51.      
  52.        if (cs_freepairs[0]==0) then
  53.            set cs_freepairs[8190]=cs_freepairs[8190]+1
  54.            set i= cs_freepairs[8190]
  55.        else
  56.            set i= cs_freepairs[cs_freepairs[0]]
  57.            set cs_freepairs[0]=cs_freepairs[0]-1
  58.        endif
  59.        if (i>=8189) then //because we can only recycle up to 8189 (free pairs array uses indexes 0 and 8190 for other purposes)
  60.            call StoreInteger(cs_cache,"pairx",I2S(i),x)
  61.            call StoreInteger(cs_cache,"pairy",I2S(i),y)
  62.        else
  63.            set cs_pairx[i]=x
  64.            set cs_pairy[i]=y
  65.  
  66.        endif
  67.      return i
  68.     endfunction
  69.  
  70.     function DestroyPair takes integer id returns nothing
  71.         if (id>=8189) then
  72.             call FlushStoredInteger(cs_cache,"pairx",I2S(id))
  73.             call FlushStoredInteger(cs_cache,"pairy",I2S(id))
  74.         else
  75.             set cs_freepairs[0]=cs_freepairs[0]+1
  76.             set cs_freepairs[cs_freepairs[0]] = id
  77.         endif
  78.     endfunction
  79.  
  80.     function SetPairXY takes integer id, integer x, integer y returns nothing
  81.         if (id>=8189) then
  82.             call StoreInteger(cs_cache,"pairx",I2S(id),x)
  83.             call StoreInteger(cs_cache,"pairy",I2S(id),y)
  84.  
  85.         else
  86.             set cs_pairx[id]=x
  87.             set cs_pairy[id]=y
  88.         endif
  89.     endfunction
  90.  
  91.     function SetPairX takes integer id, integer x returns nothing
  92.         if (id>=8189) then
  93.             call StoreInteger(cs_cache,"pairx",I2S(id),x)
  94.         else
  95.             set cs_pairx[id]=x
  96.         endif
  97.     endfunction
  98.  
  99.     function SetPairY takes integer id, integer y returns nothing
  100.         if (id>=8189) then
  101.             call StoreInteger(cs_cache,"pairy",I2S(id),y)
  102.         else
  103.             set cs_pairy[id]=y
  104.         endif
  105.     endfunction
  106.  
  107.     function GetPairX takes integer id returns integer
  108.         if (id>=8189) then
  109.             return GetStoredInteger(cs_cache,"pairy",I2S(id))
  110.         endif
  111.      return cs_pairx[id]
  112.     endfunction
  113.     function GetPairY takes integer id returns integer
  114.         if (id>=8189) then
  115.             return GetStoredInteger(cs_cache,"pairx",I2S(id))
  116.         endif
  117.      return cs_pairy[id]
  118.     endfunction
  119.  
  120.  
  121.  
  122.  
  123.  
  124.     //=================================================================================================================
  125.     // CS Dynamic Arrays
  126.     // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  127.     // Thanks: Pipedream, Peppar
  128.     //
  129.     // We can now create arrays in game! , also pass them as arguments or return values!
  130.     // a 1 length array is a pointer!
  131.     //
  132.     function Array_TryFree takes nothing returns nothing
  133.      local integer i
  134.      local integer N=cs_array1[0]
  135.      local integer k
  136.      local boolean cleaned=false
  137.  
  138.      local integer loc
  139.  
  140.      local integer q
  141.      local integer r
  142.        
  143.  
  144.  
  145.             set i=cs_array1[146]
  146.             if (i>144) then
  147.                 call TimerStart(GetExpiredTimer(),60.,false,function Array_TryFree)
  148.                 return
  149.             endif
  150.  
  151.             set loc=cs_freeindexes[i]
  152.             set q=0
  153.             loop
  154.                 exitwhen (loc==0)
  155.           // we could just have used:
  156.                     //set k=GetPairX(loc)
  157.                     //set r=GetPairY(loc) But it is slower than direct usage:
  158.  
  159.                 if (loc>=8192) then
  160.               set k=GetStoredInteger(cs_cache,"pairx",I2S(loc))
  161.               set r=GetStoredInteger(cs_cache,"pairy",I2S(loc))
  162.           else
  163.               set k=cs_pairx[loc]
  164.               set r=cs_pairy[loc]
  165.           endif
  166.  
  167.                 if (k+i-1==N) then
  168.  
  169.  
  170.                     //we found one we can remove from the list
  171.  
  172.                     set cleaned=true
  173.                     //decrement N
  174.                    
  175.                     set N=k-2
  176.  
  177.                     //Remove from the list:
  178.                     if (q==null) then
  179.                         //That was the first, update the array as well
  180.                         set cs_freeindexes[i]=r
  181.                     else
  182.                         //Update the next of the previous one
  183.                         //We could use : call SetPairY(q,,r) but it is slower
  184.                   if (q>=8189) then
  185.                       call StoreInteger(cs_cache,"pairy",I2S(q),r)
  186.                         else
  187.                       set cs_pairy[q]=r
  188.                   endif
  189.  
  190.  
  191.                     endif
  192.                     if (r==null) then
  193.                         //This was the last one, update it in the array as well
  194.                         set cs_freeindexes[i+4096]=q
  195.                     endif
  196.                    
  197.                     call DestroyPair(loc)
  198.                     set loc=q
  199.                 endif
  200.                 set q=loc
  201.                 set loc=r
  202.             endloop
  203.            
  204.             if (cleaned) then
  205.                 set cs_array1[0]=N
  206.                 set cs_array1[146]=1
  207.             else
  208.                 set cs_array1[146]=cs_array1[i+1]
  209.             endif
  210.      call TimerStart(GetExpiredTimer(),0.2,false,function Array_TryFree)
  211.  
  212.     endfunction
  213.  
  214.     function InitArrayIndexes2 takes nothing returns nothing
  215.      local integer i=0
  216.         loop
  217.             exitwhen (i==8191)
  218.             set cs_pairx[i]=777
  219.             set cs_pairy[i]=777
  220.             set i=i+1
  221.         endloop
  222.      
  223.     endfunction
  224.  
  225.  
  226.     function InitArrayIndexes takes nothing returns nothing
  227.      local integer i=0
  228.      local integer a=1
  229.      local integer b=1
  230.      local integer c
  231.  
  232.  
  233.         //By placing 777 there instead of 0 it is easier to recognize non correctly initialized bugs
  234.         loop
  235.             exitwhen (i== 8191)
  236.             set cs_array1[i]=777
  237.             set cs_array2[i]=777
  238.             set cs_array3[i]=777
  239.             //set cs_pairx[i]=777
  240.             //set cs_pairy[i]=777
  241.             set i=i+1
  242.         endloop
  243.         call ExecuteFunc("InitArrayIndexes2")
  244.  
  245.  
  246.         set cs_freeindexes[0]=0 //The stack for the table indexes.
  247.         set cs_freepairs[0]=0
  248.         set cs_freepairs[8190]=0
  249.         set i=1
  250.         loop
  251.             set c=a+b
  252.             set a=b
  253.             set b=c
  254.             exitwhen (b>144) //max size is 144
  255.             set cs_freeindexes[b]=0 //the first of the list
  256.             set cs_freeindexes[b+4096]=0 //the last of the list
  257.             loop
  258.                 exitwhen (i>b)
  259.                 set cs_array1[i]=b
  260.                 set i=i+1
  261.             endloop
  262.            
  263.         endloop
  264.         set cs_array1[i]=b //i is 145
  265.         set cs_array1[146]=1
  266.         set cs_array1[147]=101 //initial table index is 101
  267.         set cs_array1[0]=147
  268.         //index 0: Last used index
  269.         // 1 to 145 : Fibonacci sequence
  270.         // 146 : last check
  271.         // 147 : Table indexes check
  272.        
  273.         //This has a good chance to compress the thing when necesary
  274.         call TimerStart(CreateTimer(),60.,false,function Array_TryFree)
  275.  
  276.     endfunction
  277.  
  278.     //=============================================================================================
  279.     // Create an array of size, max size is 144, if doinit is true it will put a bunch of zeros
  280.     // in the indexes
  281.     //
  282.     function NewArray takes integer size, boolean doinit returns integer
  283.      local integer i
  284.      local integer rsize=cs_array1[size]
  285.      local integer loc
  286.  
  287.         set loc=cs_freeindexes[rsize]
  288.         if (loc!=0) then
  289.  
  290.             set cs_freeindexes[rsize]= GetPairY(loc)
  291.             if (cs_freeindexes[rsize]==0) then
  292.                 set cs_freeindexes[4096+rsize]=0
  293.             endif
  294.             set i=GetPairX(loc)
  295.             call DestroyPair(loc)
  296.  
  297.             if (i==0) then
  298.                 //this code was probably a good idea when we used locations for the free indexes list, now we use pairs which should not ever
  299.                 //do this unless someone modiffied the pair array incorrectly
  300.            
  301.                 call BJDebugMsg("Caster System: Unexpected error (5): corrupt stack, attempt to recover "+I2S(rsize))
  302.                 // recovering involves forgetting about the stack which got corrupted and start again from zero, it will leak
  303.                 // and probably get slow due to usage of gamecache but it is better than the problems that a corrupt stack might cause
  304.                 set cs_freeindexes[rsize]=0
  305.                 set cs_freeindexes[4096+rsize]=0
  306.                
  307.                
  308.                 return NewArray(size,doinit)
  309.             endif
  310.  
  311.         else
  312.            
  313.             //sz  i   i+1   i+2
  314.             //[ ][   ][    ][   ]
  315.        
  316.             set i=cs_array1[0]+2
  317.             set cs_array1[0]=i+rsize-1
  318.  
  319.         endif
  320.  
  321.         //It used to store size in the index equal to the array's id
  322.         // but that required the get/set functions to increment 1 in every index
  323.         // calculation. Instead, making size the previous index to the array works
  324.         if (i<=8191) then
  325.             set cs_array1[i-1]=size
  326.         elseif (i<=16382) then
  327.             set cs_array2[i-8192]=size
  328.         else
  329.             call StoreInteger(cs_cache,I2S(-i),"size",size)
  330.         endif
  331.  
  332.        
  333.         if (not doinit) then
  334.             return i
  335.         endif
  336.        
  337.         //    3
  338.         //[i][i+1][i+2]
  339.  
  340.         set size=i+size-1
  341.         if (size>=16382) then
  342.             set size=16381
  343.         endif
  344.         loop
  345.             exitwhen (size<i) or (size<8191)
  346.             set cs_array2[size-8191]=0
  347.             set size=size-1
  348.         endloop
  349.         loop
  350.             exitwhen (size<i)
  351.             set cs_array1[size]=0
  352.             set size=size-1
  353.         endloop
  354.        
  355.         //call DisplayTextToPlayer(GetLocalPlayer(),0,0,I2S(i))
  356.  
  357.      return i
  358.     endfunction
  359.  
  360.  
  361.     //===============================================================================================================
  362.     // Remember to destroy arrays when you no longer need them, else new arrays will get slower after a bunch of
  363.     // arrays are active
  364.     //
  365.     function DestroyArray takes integer id returns nothing
  366.      local integer L
  367.      local integer loc
  368.     // local string k=I2S(-id)
  369.      local integer lstpace
  370.  
  371.         if (id<=8191) then
  372.             set L=cs_array1[cs_array1[id-1]]
  373.         elseif (id<=16382) then
  374.             set L=cs_array1[cs_array2[id-8191]]
  375.         else
  376.             set L=cs_array1[GetStoredInteger(cs_cache,I2S(-id),"size")]
  377.             //No way you are gonna call DestroyArray without calling
  378.            //NewArray first, so we can use the gamecache variable directly instead
  379.  
  380.         endif
  381.         set lstpace=id+L-1
  382.        call FlushStoredMission(cs_cache,I2S(-id))
  383.      
  384.        if (lstpace>16382) then
  385.        
  386.            if (lstpace==cs_array1[0]) then
  387.                //We just destroyed the array that happens to be at the end of the heap.
  388.                //Just get it back
  389.                set cs_array1[0]=id-2
  390.                set cs_array1[146]=1
  391.            else
  392.                //Add to the last
  393.                set loc=cs_freeindexes[L+4096]
  394.                if (loc==0) then
  395.                    set loc=NewPair(id,0)
  396.                    set cs_freeindexes[L]=loc
  397.                    set cs_freeindexes[L+4096]=loc
  398.                else
  399.                    set cs_freeindexes[L+4096]=  NewPair(id,0)
  400.                    //we could just use: call SetPairY(loc, cs_freeindexes[L+4096] ) //but that's slower
  401.                    if (loc>=8189) then
  402.                  call StoreInteger(cs_cache,"pairy",I2S(loc), cs_freeindexes[L+4096] )
  403.                    else
  404.                        set cs_pairy[loc]=cs_freeindexes[L+4096]                 
  405.                    endif
  406.  
  407.                endif
  408.  
  409.  
  410.            endif
  411.  
  412.        elseif (lstpace==cs_array1[0]) then
  413.                //We just destroyed the array that happens to be at the end of the heap.
  414.                //Just get it back
  415.                set cs_array1[0]=id-2
  416.                set cs_array1[146]=1
  417.        else
  418.            set loc=cs_freeindexes[L]
  419.            set cs_freeindexes[L]=NewPair(id,loc)
  420.  
  421.            if (loc==0) then
  422.                set cs_freeindexes[L+4096]=cs_freeindexes[L]
  423.            endif
  424.  
  425.        endif
  426.  
  427.     endfunction
  428.  
  429.     //================================================================================================================
  430.     // Int Set/Get array usage prototypes.
  431.     //
  432.     // These are the actual functions, the rest are just the result of copy paste, if these functions are updated
  433.     // the other ones should be updated as well (They are just return bugged variations)
  434.     //
  435.     function SetArrayInt takes integer id, integer index, integer val returns nothing
  436.         set index=id+index
  437.         if (index<8191) then
  438.             set cs_array1[index]=val
  439.         elseif (index<16382) then   
  440.             set cs_array2[index-8191]=val
  441.         else
  442.             call StoreInteger(cs_cache,I2S(-id),I2S(index),val)
  443.         endif
  444.     endfunction
  445.     function GetArrayInt takes integer id, integer index returns integer
  446.         set index=id+index
  447.         if (index<8191) then
  448.             return cs_array1[index]
  449.         elseif (index<16382) then   
  450.             return cs_array2[index-8191]
  451.         endif
  452.      return GetStoredInteger(cs_cache,I2S(-id),I2S(index))
  453.     endfunction
  454.  
  455.  
  456.     //================================================================================================================
  457.     // String Set/Get array
  458.     //
  459.     // Due String related return bug issues, these are forced to use gamecache
  460.     //
  461.     function SetArrayString takes integer id, integer index, string val returns nothing
  462.         call StoreString(cs_cache,I2S(-id),I2S(index),val)
  463.     endfunction
  464.     function GetArrayString takes integer id, integer index returns string
  465.      return GetStoredString(cs_cache,I2S(-id),I2S(index))
  466.     endfunction
  467.  
  468.     //(Boolean is not needed)
  469.  
  470.     //==========================================================================================================================
  471.     // Returns the size of an array (the specified by player one, not the actual size of it) should be useful.
  472.     //
  473.     function GetArraySize takes integer id returns integer
  474.         if (id<=8191) then
  475.             return cs_array1[id-1]
  476.         elseif (id<=16382) then
  477.             return cs_array2[id-8192]
  478.         endif
  479.      return GetStoredInteger(cs_cache,I2S(-id),"size")
  480.     endfunction
  481.  
  482.  
  483.     //===========================================================================================================================
  484.     // Returns an array that is an exact copy of the given array
  485.     //
  486.     function CloneArray takes integer id returns integer
  487.      local integer sz
  488.      local integer i
  489.      local integer sz2
  490.      local integer x
  491.      local integer y
  492.  
  493.         if (id<=8191) then
  494.             set sz=cs_array1[id-1]
  495.         elseif (id<=16382) then
  496.             set sz=cs_array2[id-8192]
  497.         else
  498.             set sz=GetStoredInteger(cs_cache,I2S(-id),"size")
  499.             //No way you are gonna call DestroyArray without calling
  500.            //NewArray first, so we can use the gamecache variable directly instead
  501.  
  502.         endif
  503.  
  504.         set i=NewArray(sz,false)
  505.        
  506.         set sz2=i+sz-1
  507.         set sz=id+sz-1
  508.         set x=i
  509.         set y=id
  510.         loop
  511.             exitwhen ((y>sz) or (y>=8191) or (x>=8191))
  512.             set cs_array1[x]=cs_array1[y]
  513.             set y=y+1
  514.             set x=x+1
  515.         endloop
  516.         loop
  517.             exitwhen ((y>sz) or (y>=8191) or (x>=16382))
  518.             set cs_array2[x-8191]=cs_array1[y]
  519.             set y=y+1
  520.             set x=x+1
  521.         endloop
  522.         loop
  523.             exitwhen ((y>sz) or (y>=8191))
  524.             call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array1[y])
  525.             set x=y+1
  526.             set y=y+1
  527.         endloop
  528.         //...
  529.         loop
  530.             exitwhen ((y>sz) or (y>=16382) or (x>=8191))
  531.             set cs_array1[x]=cs_array2[y-8191]
  532.             set y=y+1
  533.             set x=x+1
  534.         endloop
  535.         loop
  536.             exitwhen ((y>sz) or (y>=16382) or (x>=16382))
  537.             set cs_array2[x-8191]=cs_array2[y-8191]
  538.             set y=y+1
  539.             set x=x+1
  540.         endloop
  541.         loop
  542.             exitwhen ((y>sz) or (y>=16382))
  543.             call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array2[y-8191])
  544.             set y=y+1
  545.             set x=x+1
  546.         endloop
  547.         //...
  548.         loop
  549.             exitwhen ((y>sz) or (x>=8191))
  550.             set cs_array1[x]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))
  551.             set y=y+1
  552.             set x=x+1
  553.         endloop
  554.         loop
  555.             exitwhen ((y>sz) or (x>=16382))
  556.             set cs_array2[x-8191]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))
  557.             set y=y+1
  558.             set x=x+1
  559.         endloop
  560.         loop
  561.             exitwhen (y>sz)
  562.             call StoreInteger(cs_cache,I2S(-i),I2S(x-i),GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)))
  563.             set y=y+1
  564.             set x=x+1
  565.         endloop
  566.        
  567.      return i
  568.     endfunction
  569.  
  570.     //==================================================================================================
  571.     // Attachable vars : Attacheable variables are what most other people call Handle Variables, they
  572.     // allow to relate data with any handle, using a label, and its value, the stuff auto flushes if
  573.     // the value is 0, false, "", or null .
  574.     //
  575.     // Differences between Attacheable variables and "Local Handle Variables" :
  576.     // - The names of the functions
  577.     // - The name of the function group does not cause confusion, it is difficult to say:
  578.     //   "you should set local handle variables to null at the end of a function" since
  579.     //   it sounds as if you were talking about the "Local Handle Variables"
  580.     // - And can work together with Tables.
  581.     //
  582.     // Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!)
  583.     //
  584.     //
  585.     // Although locations and dynamic arrays are faster than gamecache, gamecache still keeps the flexibility
  586.     // Best thing to do in my opinion is to combine these options. By combining you can acquire gamecache
  587.     // flexibility and arrays/locs speed to solve a problem
  588.     //
  589.  
  590.     //============================================================================================================
  591.     // For integers
  592.     //
  593.     function AttachInt takes handle h, string label, integer x returns nothing
  594.         if x==0 then
  595.             call FlushStoredInteger(cs_cache,I2S(GetHandleId(h)),label)
  596.         else
  597.             call StoreInteger(cs_cache,I2S(GetHandleId(h)),label,x)
  598.         endif
  599.     endfunction
  600.     function GetAttachedInt takes handle h, string label returns integer
  601.         return GetStoredInteger(cs_cache, I2S(GetHandleId(h)), label)
  602.     endfunction
  603.  
  604.     //=============================================================================================================
  605.     function AttachReal takes handle h, string label, real x returns nothing
  606.          if x==0 then
  607.             call FlushStoredReal(cs_cache,I2S(GetHandleId(h)),label)
  608.         else
  609.             call StoreReal(cs_cache,I2S(GetHandleId(h)),label,x)
  610.         endif
  611.     endfunction
  612.     function GetAttachedReal takes handle h, string label returns real
  613.         return GetStoredReal(cs_cache,I2S(GetHandleId(h)),label)
  614.     endfunction
  615.  
  616.     //=============================================================================================================
  617.     function AttachBoolean takes handle h, string label, boolean x returns nothing
  618.         if not x then
  619.             call FlushStoredBoolean(cs_cache,I2S(GetHandleId(h)),label)
  620.         else
  621.             call StoreBoolean(cs_cache,I2S(GetHandleId(h)),label,x)
  622.         endif
  623.     endfunction
  624.     function GetAttachedBoolean takes handle h, string label returns boolean
  625.         return GetStoredBoolean(cs_cache,I2S(GetHandleId(h)),label)
  626.     endfunction
  627.  
  628.     //=============================================================================================================
  629.     function AttachString takes handle h, string label, string x returns nothing
  630.         if ((x=="") or (x==null)) then
  631.             call FlushStoredString(cs_cache,I2S(GetHandleId(h)),label)
  632.         else
  633.             call StoreString(cs_cache,I2S(GetHandleId(h)),label,x)
  634.         endif
  635.     endfunction
  636.     function GetAttachedString takes handle h, string label returns string
  637.         return GetStoredString(cs_cache,I2S(GetHandleId(h)),label)
  638.     endfunction
  639.  
  640.     //============================================================================================================
  641.     function CleanAttachedVars takes handle h returns nothing
  642.         call FlushStoredMission(cs_cache,I2S(GetHandleId(h)))
  643.     endfunction
  644.  
  645.     //============================================================================================================
  646.     // Left for compat
  647.     function CleanAttachedVars_NoSets takes handle h returns nothing
  648.         call FlushStoredMission(cs_cache,I2S(GetHandleId(h)))
  649.     endfunction
  650.  
  651.  
  652.     //=============================================================================================
  653.     // Tables
  654.     //
  655.     // Tables are lame, the real name would be hash tables, they are just abbreviated usage
  656.     // of gamecache natives with the addition that you can also Copy the values of a table to
  657.     // another one, but don't expect it to be automatic, it must use a FieldData object to know
  658.     // which fields and of wich types to copy, Copying a table to another, with a lot of Fields,
  659.     // should surelly be lag friendly.
  660.     //
  661.     // The other thing about tables is that I can say that the Attached variables of a handle work
  662.     // inside a table and GetAttachmentTable which is just return bug and I2S , works to allow you
  663.     // to manipulate a handle's attached variables through a table.
  664.     //
  665.     // NewTable and DestroyTable were created to allow to create tables in the fly, but you can
  666.     // simply use strings for tables, but place the table names should be between "("")" for example
  667.     // "(mytable)" to avoid conflicts with other caster system stuff.
  668.     //
  669.     function NewTableIndex takes nothing returns integer
  670.      local integer loc=cs_freeindexes[0]
  671.      local integer i
  672.         if (loc!=0) then
  673.             set i=GetPairX(loc)
  674.             set cs_freeindexes[0]=GetPairY(loc)
  675.             call DestroyPair(loc)
  676.  
  677.             return i
  678.         endif
  679.         set i=cs_array1[147]+1
  680.         set cs_array1[147]=i
  681.  
  682.      return i
  683.     endfunction
  684.     function NewTable takes nothing returns string
  685.      local integer loc=cs_freeindexes[0]
  686.      local integer i
  687.         if (loc!=0) then
  688.             set i=GetPairX(loc)
  689.             set cs_freeindexes[0]=GetPairY(loc)
  690.             call DestroyPair(loc)
  691.  
  692.             return I2S(i)
  693.         endif
  694.         set i=cs_array1[147]+1
  695.         set cs_array1[147]=i
  696.  
  697.      return I2S(i)
  698.     endfunction
  699.     function GetAttachmentTable takes handle h returns string
  700.         return I2S(GetHandleId(h))
  701.     endfunction
  702.  
  703.     //============================================================================================================
  704.     function DestroyTable takes string table returns nothing
  705.      local integer i=S2I(table)
  706.      local integer n
  707.          call FlushStoredMission(cs_cache,table)
  708.          if ((i>100) and (i<1000000)) then //All right, more than 1000000 tables is just wrong.
  709.              if (i==cs_array1[147]) then
  710.                  set cs_array1[147]=cs_array1[147]-1
  711.              else
  712.                  set cs_freeindexes[0]=  NewPair(i,cs_freeindexes[0])
  713.              endif
  714.          endif
  715.  
  716.     endfunction
  717.  
  718.     //============================================================================================================
  719.     function ClearTable takes string table returns nothing
  720.          call FlushStoredMission(cs_cache,table)
  721.     endfunction
  722.  
  723.  
  724.     //============================================================================================================
  725.     function SetTableInt takes string table, string field, integer val returns nothing
  726.         if (val==0) then
  727.             call FlushStoredInteger(cs_cache,table,field)
  728.         else
  729.             call StoreInteger(cs_cache,table,field,val)
  730.         endif
  731.     endfunction
  732.     function GetTableInt takes string table, string field returns integer
  733.         return GetStoredInteger(cs_cache,table,field)
  734.     endfunction
  735.  
  736.     //============================================================================================================
  737.     function SetTableReal takes string table, string field, real val returns nothing
  738.         if (val==0) then
  739.             call FlushStoredReal(cs_cache,table,field)
  740.         else
  741.             call StoreReal(cs_cache,table,field,val)
  742.         endif
  743.     endfunction
  744.     function GetTableReal takes string table, string field returns real
  745.         return GetStoredReal(cs_cache,table,field)
  746.     endfunction
  747.  
  748.     //============================================================================================================
  749.     function SetTableBoolean takes string table, string field, boolean val returns nothing
  750.         if (not(val)) then
  751.             call FlushStoredBoolean(cs_cache,table,field)
  752.         else
  753.             call StoreBoolean(cs_cache,table,field,val)
  754.         endif
  755.     endfunction
  756.     function GetTableBoolean takes string table, string field returns boolean
  757.         return GetStoredBoolean(cs_cache,table,field)
  758.     endfunction
  759.  
  760.     //============================================================================================================
  761.     function SetTableString takes string table, string field, string val returns nothing
  762.         if (val=="") or (val==null) then
  763.             call FlushStoredString(cs_cache,table,field)
  764.         else
  765.             call StoreString(cs_cache,table,field,val)
  766.         endif
  767.     endfunction
  768.     function GetTableString takes string table, string field returns string
  769.         return GetStoredString(cs_cache,table,field)
  770.     endfunction
  771.  
  772.     //============================================================================================================
  773.     // Returns true if the fiel contains a value different from 0, false,  null, or "" (depending on the type)
  774.     // it is worthless to use this with boolean, since it would be the same as reading the boolean value
  775.     //
  776.     function HaveSetField takes string table, string field, integer fieldType returns boolean
  777.         if (fieldType == bj_GAMECACHE_BOOLEAN) then
  778.             return HaveStoredBoolean(cs_cache,table,field)
  779.         elseif (fieldType == bj_GAMECACHE_INTEGER) then
  780.             return HaveStoredInteger(cs_cache,table,field)
  781.         elseif (fieldType == bj_GAMECACHE_REAL) then
  782.             return HaveStoredReal(cs_cache,table,field)
  783.         elseif (fieldType == bj_GAMECACHE_STRING) then
  784.             return HaveStoredString(cs_cache,table,field)
  785.         endif
  786.      return false
  787.     endfunction
  788.  
  789.     //============================================================================================================
  790.     // Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type
  791.     // it is supposed to copy.
  792.     //
  793.     function CopyTable takes integer FieldData, string sourceTable, string destTable returns nothing
  794.      local integer i=1
  795.      local string k=I2S(FieldData)
  796.      local string k2
  797.      local string k3
  798.      local integer n=GetStoredInteger(cs_cache,k,"N")
  799.      local integer t
  800.         loop
  801.             exitwhen (i>n)
  802.             set k2=I2S(i)
  803.             set t=GetStoredInteger(cs_cache,k,k2)
  804.             set k3=GetStoredString(cs_cache,k,k2)
  805.             if (t==bj_GAMECACHE_BOOLEAN) then
  806.                 if (HaveStoredBoolean(cs_cache,sourceTable,k3)) then
  807.                     call StoreBoolean(cs_cache,destTable,k3,GetStoredBoolean(cs_cache,sourceTable,k3))
  808.                 else
  809.                     call FlushStoredBoolean(cs_cache,destTable,k3)
  810.                 endif
  811.             elseif (t==bj_GAMECACHE_INTEGER) then
  812.                 if (HaveStoredInteger(cs_cache,sourceTable,k3)) then
  813.                     call StoreInteger(cs_cache,destTable,k3,GetStoredInteger(cs_cache,sourceTable,k3))
  814.                 else
  815.                     call FlushStoredInteger(cs_cache,destTable,k3)
  816.                 endif
  817.             elseif (t==bj_GAMECACHE_REAL) then
  818.                 if (HaveStoredReal(cs_cache,sourceTable,k3)) then
  819.                     call StoreReal(cs_cache,destTable,k3,GetStoredReal(cs_cache,sourceTable,k3))
  820.                 else
  821.                     call FlushStoredReal(cs_cache,destTable,k3)
  822.                 endif
  823.             elseif (t==bj_GAMECACHE_STRING) then
  824.                 if (HaveStoredString(cs_cache,sourceTable,k3)) then
  825.                     call StoreString(cs_cache,destTable,k3,GetStoredString(cs_cache,sourceTable,k3))
  826.                 else
  827.                     call FlushStoredString(cs_cache,destTable,k3)
  828.                 endif
  829.             endif
  830.             set i=i+1
  831.         endloop
  832.  
  833.  
  834.     endfunction
  835.  
  836.     //=============================================================================================
  837.     // FieldData inherits from Table, was just designed to be used by CopyTable.
  838.     //
  839.     function FieldData_Create takes nothing returns integer
  840.         return NewTableIndex()
  841.     endfunction
  842.  
  843.  
  844.     //============================================================================================================
  845.     // valueType uses the same integer variables from blizzard.j :
  846.     // bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING
  847.     //
  848.     function FieldData_AddField takes integer fielddata, string field, integer valueType returns nothing
  849.      local string k=I2S(fielddata)
  850.      local integer n=GetStoredInteger(cs_cache,k,"N")+1
  851.      local string k2=I2S(n)
  852.  
  853.         call StoreString(cs_cache,k,k2,field)
  854.         call StoreInteger(cs_cache,k,k2,valueType)
  855.         call StoreInteger(cs_cache,k,"N",n)
  856.  
  857.     endfunction
  858.  
  859.     //=============================================================================================
  860.     // Destroys Field Data
  861.     function FieldData_Destroy takes integer fielddata returns nothing
  862.         call DestroyTable(I2S(fielddata))
  863.     endfunction
  864.  
  865.     //=============================================================================================
  866.     // Pools
  867.     //
  868.     // A better name for pools would be sets, but by the time I made them I couldn't think of that
  869.     // name, besides the word set is already a JASS syntax word so it would have been problematic.
  870.     //
  871.     // Another naming failure is that values of a pool are called "items" but that conflicts with
  872.     // the word item that points to wc3 items, Pools can only store integer values, but if you want
  873.     // you can go and use the return bug on them.
  874.     //
  875.  
  876.     function CreatePool takes nothing returns integer
  877.      local integer i=NewArray(34,false)
  878.         call SetArrayInt(i,0,0)
  879.      return i
  880.     endfunction
  881.  
  882.     function ClearPool takes integer poolid returns nothing
  883.         call SetArrayInt(poolid,0,0) //[0:integer:n]
  884.         call FlushStoredMission(cs_cache,I2S(-poolid))
  885.     endfunction
  886.  
  887.     function DestroyPool takes integer poolid returns nothing
  888.         call DestroyArray(poolid)
  889.     endfunction
  890.  
  891.  
  892.     function PoolAddItem takes integer poolid, integer value returns nothing
  893.      local integer n
  894.      local string k=I2S(-poolid)
  895.      local string vk="#"+I2S(value)
  896.         if not HaveStoredInteger(cs_cache,k,vk) then
  897.             set n=GetArrayInt(poolid,0)+1 //[0:integer:N]
  898.             call StoreInteger(cs_cache,k,vk,n)
  899.             if (n>33) then
  900.                 call StoreInteger(cs_cache,k,I2S(n),value)
  901.             else
  902.                 call SetArrayInt(poolid,n,value)
  903.             endif
  904.             call SetArrayInt(poolid,0,n) //[0:integer:N]
  905.         endif
  906.     endfunction
  907.  
  908.  
  909.  
  910.     function PoolRemoveItem takes integer poolid, integer value returns nothing
  911.      local string k=I2S(-poolid)
  912.      local string vk="#"+I2S(value)
  913.  
  914.      local integer p=GetStoredInteger(cs_cache,k,vk)
  915.      local integer n
  916.  
  917.         if (p!=0) then
  918.             set n=GetArrayInt(poolid,0) //[0:integer:N]
  919.             call FlushStoredInteger( cs_cache, k, vk)
  920.            
  921.             if (n>p) then
  922.            
  923.                 if (n>33) then
  924.                     set vk=I2S(n)
  925.                     set value=GetStoredInteger(cs_cache,k,vk)
  926.                     call FlushStoredInteger(cs_cache,k,vk)
  927.                 else
  928.                     set value=GetArrayInt(poolid,n)
  929.                 endif
  930.                 call StoreInteger(cs_cache,k,"#"+I2S(value),p)
  931.                 if (p>33) then
  932.                     call StoreInteger(cs_cache,k,I2S(p),value)
  933.                 else
  934.                     call SetArrayInt(poolid,p,value)
  935.                 endif
  936.             elseif (p>33) then
  937.                 call FlushStoredInteger(cs_cache,k,I2S(p))
  938.             endif
  939.             call SetArrayInt( poolid,0,n - 1) //[0:integer:N]
  940.         endif
  941.     endfunction
  942.  
  943.     //===================================================================================
  944.     function PoolGetItem takes integer poolid, integer itemn returns integer
  945.         if (itemn>33) then
  946.             return GetStoredInteger( cs_cache, I2S(-poolid), I2S(itemn))
  947.         endif
  948.      return GetArrayInt(poolid,itemn)
  949.     endfunction
  950.  
  951.     //===================================================================================
  952.     function CountItemsInPool takes integer poolid returns integer
  953.      return GetArrayInt(poolid,0) //[0:integer:N]
  954.     endfunction
  955.  
  956.  
  957.     //===================================================================================
  958.     // Removed : GetEnumPoolItem , ForPool and ForPool2 they are much worse than just
  959.     // using CountItemsInPool and PoolGetItem to iterate the pool
  960.     //
  961.  
  962.     //===================================================================================
  963.     function GetFirstOfPool takes integer poolid returns integer
  964.         return GetArrayInt(poolid,1) //[1 is just the first of the pool]
  965.     endfunction
  966.  
  967.  
  968.     //===================================================================================
  969.     function PoolPickRandomItem takes integer poolid returns integer
  970.      local integer p=GetRandomInt(  1, GetArrayInt(poolid,0) )
  971.         if (p>33) then
  972.             return GetStoredInteger( cs_cache, I2S(-poolid), I2S(p))
  973.         endif
  974.      return GetArrayInt(poolid,p)
  975.     endfunction
  976.  
  977.     //===================================================================================
  978.     function GetItemPositionInPool takes integer poolid, integer it returns integer
  979.         return GetStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it))
  980.     endfunction
  981.  
  982.     //===================================================================================
  983.     function IsItemInPool takes integer poolid, integer it returns boolean
  984.         return(HaveStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) )
  985.     endfunction
  986.  
  987.     //===================================================================================
  988.     // This had to be optimized for speed, if it was just a loop using the above functions
  989.     // that would have been too slow to be worth keeping. That's a bad thing about JASS
  990.     // it is such an slow language that code reusability always has the cost of speed
  991.     //
  992.     function PoolAddPool takes integer sourcepoolid, integer destpoolid returns nothing
  993.      local integer a=1
  994.      local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N]
  995.      local integer dn=GetArrayInt( destpoolid,0) //[0:integer:N]
  996.      local string sk=I2S(-sourcepoolid)
  997.  
  998.      local string k=I2S(-destpoolid)
  999.      local integer v
  1000.      local string vk
  1001.  
  1002.         loop
  1003.             exitwhen (a>n)
  1004.             if (a>33) then
  1005.                 set v=GetStoredInteger(cs_cache,sk,I2S(a))
  1006.             else
  1007.                 set v=GetArrayInt(sourcepoolid,a)
  1008.             endif
  1009.             set vk="#"+I2S(v)
  1010.             if not HaveStoredInteger(cs_cache,k,vk) then
  1011.                 set dn=dn+1
  1012.                 call StoreInteger(cs_cache,k,vk,dn)
  1013.                 if (dn>33) then
  1014.                     call StoreInteger(cs_cache,k,I2S(dn),v)
  1015.                 else
  1016.                     call SetArrayInt(destpoolid,dn,v)
  1017.                 endif
  1018.             endif
  1019.             set a=a+1
  1020.         endloop
  1021.         call SetArrayInt(destpoolid,0,dn) //[0:integer:N]
  1022.     endfunction
  1023.  
  1024.     //=============================================================================================
  1025.     // Oh darn, After making PoolAddPool I don't feel like writting this one
  1026.     // All right I am at least make the get code
  1027.     //
  1028.     function PoolRemovePool takes integer sourcepoolid, integer destpoolid returns nothing
  1029.      local integer a=1
  1030.      local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N]
  1031.      local integer v
  1032.      local string sk=I2S(-sourcepoolid)
  1033.         loop
  1034.             exitwhen a>n
  1035.             if (a>33) then
  1036.                 set v=GetStoredInteger(cs_cache,sk,I2S(a) )
  1037.             else
  1038.                 set v=GetArrayInt(sourcepoolid,a)
  1039.             endif
  1040.             call PoolRemoveItem( destpoolid, v)
  1041.             set a=a+1
  1042.         endloop
  1043.     endfunction
  1044.  
  1045.     //===================================================================================
  1046.     // Adds a tokenized string to a pool,
  1047.     //  Example: PoolAddS(udg_p, "1;2;3;4") will add to the udg_p pool : 1,2,3 and 4
  1048.     //
  1049.     function PoolAddS takes integer poolid, string s returns nothing
  1050.      local integer i=0
  1051.      local integer st
  1052.      local string c
  1053.         set s=s+";"
  1054.         set st=0
  1055.         loop
  1056.             set c=SubString(s, i, i+1)
  1057.             exitwhen (c == "") or (c == null)
  1058.             if (c == ";") then
  1059.                 call PoolAddItem( poolid, S2I(SubString(s, st, i)) )
  1060.                 set st=i+1
  1061.             endif
  1062.             set i=i+1
  1063.         endloop
  1064.     endfunction
  1065.  
  1066.     //===================================================================================
  1067.     // Converts a tokenized string into a pool,
  1068.     //  Example: S2Pool( "1;2;3;4") will return a pool that has 1,2,3 and 4 inside
  1069.     //
  1070.     function S2Pool takes string s returns integer
  1071.      local integer spool= CreatePool()
  1072.         call PoolAddS(spool,s)
  1073.      return spool
  1074.     endfunction
  1075.  
  1076.     //===================================================================================
  1077.     // Does the opposite of S2Pool, debugging is a good use for this function.
  1078.     //
  1079.     function Pool2S takes integer P returns string
  1080.      local integer N=CountItemsInPool(P)
  1081.      local integer i
  1082.      local string s
  1083.         if (N>=1) then
  1084.             set s=I2S(PoolGetItem(P,1) )
  1085.             set i=2
  1086.         else
  1087.             return ""
  1088.         endif
  1089.         loop
  1090.             exitwhen (i>N)
  1091.             set s=s+";"+I2S(PoolGetItem(P,i))
  1092.             set i=i+1
  1093.         endloop
  1094.     return s
  1095.     endfunction
  1096.  
  1097.     //=============================================================================================================
  1098.     // Fixes a lame bug by blizzard related to the custom script section (The condition of the if statement might
  1099.     // actually be true.
  1100.     //
  1101.     function Pool_Percent takes nothing returns string
  1102.        if ("%"=="") then
  1103.            return "%%"
  1104.        endif
  1105.      return "%"
  1106.     endfunction
  1107.  
  1108.     function Pool_SetupCharMap takes nothing returns nothing
  1109.      local string cm=".................................!.#$"+Pool_Percent()+"&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~..."
  1110.      local integer i=0
  1111.      local string c
  1112.         if HaveStoredInteger(cs_cache,"charmap_upper","A") then
  1113.             return
  1114.         endif
  1115.         loop
  1116.             set c=SubString(cm,i,i+1)
  1117.             exitwhen (c==null) or (c=="")
  1118.             if (c!=".") then
  1119.                 if c==StringCase(c,true) then
  1120.                     call StoreInteger(cs_cache,"charmap_upper",c,i)
  1121.                 else
  1122.                     call StoreInteger(cs_cache,"charmap_lower",c,i)
  1123.                 endif
  1124.                
  1125.             endif
  1126.             set i=i+1
  1127.         endloop
  1128.  
  1129.     endfunction
  1130.  
  1131.  
  1132.     function Pool_Rawcode2Int takes string s returns integer
  1133.      local string c
  1134.      local integer i=0
  1135.      local integer r=0
  1136.         loop
  1137.             exitwhen i>3
  1138.             set c=SubString(s,i,i+1)
  1139.             set r=r*256
  1140.             if c==StringCase(c,true) then
  1141.                 set r=r+GetStoredInteger(cs_cache,"charmap_upper",c)
  1142.             else
  1143.                 set r=r+GetStoredInteger(cs_cache,"charmap_lower",c)
  1144.             endif
  1145.            
  1146.             set i=i+1
  1147.         endloop
  1148.      return r
  1149.     endfunction
  1150.  
  1151.     function PoolAddRawcodes_thread takes nothing returns nothing
  1152.     //Threaded because I don't want it to halt execution for no reason
  1153.     //
  1154.      local string s=bj_lastPlayedMusic
  1155.      local integer poolid=bj_groupEnumTypeId
  1156.      local string c
  1157.      local integer i=0
  1158.      local integer st=0
  1159.         set s=s+";"
  1160.         loop
  1161.             set c=SubString(s, i, i+1)
  1162.             exitwhen (c == "") or (c == null)
  1163.             if c == ";" then
  1164.                 call PoolAddItem(poolid, Pool_Rawcode2Int(SubString(s,st,i) ))
  1165.                 set st=i+1
  1166.             endif
  1167.             set i=i+1
  1168.         endloop
  1169.  
  1170.     endfunction
  1171.  
  1172.     //=====================================================================================================================
  1173.     // Adds a string of tokenized rawcodes to a pool
  1174.     //  Example: PoolAddRawcodes(udg_p,"A000;A001")  will add 'A000' and 'A001' to the pool
  1175.     //
  1176.     // (Saves some lines, but is not as good efficiency wise)
  1177.     //
  1178.     function PoolAddRawcodes takes integer poolid, string s returns nothing
  1179.      local string b=bj_lastPlayedMusic
  1180.         set bj_groupEnumTypeId=poolid
  1181.         set bj_lastPlayedMusic=s
  1182.         call ExecuteFunc("PoolAddRawcodes_thread")
  1183.         set bj_lastPlayedMusic=b
  1184.     endfunction
  1185.  
  1186.     //===================================================================================================================
  1187.     // Converts a tokenized string of rawcodes into a pool,
  1188.     //  Example: Rawcodes2Pool( "A000;A001;AHbz;S000") will return a pool that has 'A000,'A001','AHbx' and 'S000' inside
  1189.     //
  1190.     // (Saves some lines, but is not as good efficiency wise)
  1191.     //
  1192.     function Rawcodes2Pool takes string s returns integer
  1193.      local integer spool= CreatePool()
  1194.         call PoolAddRawcodes(spool,s)
  1195.      return spool
  1196.     endfunction
  1197.  
  1198.     //===================================================================================================================
  1199.     // A subproduct of the Pool's Rawcode support is that we can easily have this function so I am including it even if
  1200.     // it has nothing to do with data storage.
  1201.     //
  1202.     // takes "Aloc" and converts it into 'Aloc'
  1203.     // it is different to the Pool_Rawcode2Int function in that it is safe to use it when it is the first CSCache
  1204.     // function ever used. But it is a little slower (wc3mapoptimizer should make it as fast though)
  1205.     //
  1206.     function CS_Rawcode2Int takes string s returns integer
  1207.      local string c
  1208.      local integer i=0
  1209.      local integer r=0
  1210.         loop
  1211.             exitwhen i>3
  1212.             set c=SubString(s,i,i+1)
  1213.             set r=r*256
  1214.             if c==StringCase(c,true) then
  1215.                 set r=r+GetStoredInteger(cs_cache,"charmap_upper",c)
  1216.             else
  1217.                 set r=r+GetStoredInteger(cs_cache,"charmap_lower",c)
  1218.             endif
  1219.            
  1220.             set i=i+1
  1221.         endloop
  1222.      return r
  1223.     endfunction
  1224.  
  1225.  
  1226. endlibrary
« Last Edit: December 23, 2017, 07:23:36 PM by moyack »



 

Vivir aprendiendo.co - A place for learning stuff, in Spanish   Chaos Realm - The world of Game modders and wc3 addicts   Diplo, a gaming community   Power of Corruption, an altered melee featuring Naga and Demon. Play it now!!!   WC3JASS.com - The JASS Vault + vJASS and Zinc   Jetcraft - A Starcraft II mod   WormTastic Clan (wTc)   Warcraft RESOURCES Reforged: Modelos, mapas, proyectos y mas...