//##Begin of CS Gamecache engine 13.6 http://wc3campaigns.net/vexorian ##
//=================================================================================================
// 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
//==================================================================================================
// 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
function Location_ObjectLoc takes handle x , location y returns location
return Location(CS_h2r(x),CS_h2r(y))
endfunction
function Location_LocLoc takes handle x , location y returns location
return Location(CS_h2r(x),CS_h2r(y))
endfunction
function Location_RealLoc takes real x , location y returns location
return Location(x,CS_h2r(y))
endfunction
//====================================================================================================
// Combined assigments
//
function SetLocation_IntLoc takes location loc, integer x , location y returns nothing
call MoveLocation(loc,CS_i2r(x),CS_h2r(y))
endfunction
function SetLocation_ObjectLoc takes location loc, handle x , location y returns nothing
call MoveLocation(loc,CS_h2r(x),CS_h2r(y))
endfunction
function SetLocation_LocLoc takes location loc, handle x , location y returns nothing //Funny name
call MoveLocation(loc,CS_h2r(x),CS_h2r(y))
endfunction
function SetLocation_RealLoc takes location loc, real x , location y returns nothing
call MoveLocation(loc,x,CS_h2r(y))
endfunction
//===================================================================================================
// 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
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.
//
//=================================================================================================
// Main Gamecache handler
//
function CSCache takes nothing returns gamecache
if udg_cscache==null then
call FlushGameCache(InitGameCache("cscache"))
set udg_cscache=InitGameCache("cscache")
call StoreInteger(udg_cscache,"misc","TableMaxReleasedIndex",100)
call ExecuteFunc("InitArrayIndexes")
endif
return udg_cscache
endfunction
//=================================================================================================================
// CS Dynamic Arrays
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Thanks: Pipedream, Peppar
//
// We can now create arrays in game!
//
function Array_TryFree takes nothing returns nothing
local integer i
local integer N=udg_csarray1[0]
local integer k
local boolean cleaned=false
local location loc
local location q
local location r
set i=udg_csarray1[146]
if (i>144) then
call TimerStart(GetExpiredTimer(),60.,false,function Array_TryFree)
return
endif
set loc=udg_csfreeindexes[i]
set q=null
loop
exitwhen (loc==null)
set k=CS_r2i(GetLocationX(loc))
set r=CS_ly(loc)
if (k+i==N) then
//we found one we can remove from the list
set cleaned=true
//decrement N
set N=k-1
set udg_csarray1[0]=N
//Remove from the list:
if (q==null) then
//That was the first, update the array as well
set udg_csfreeindexes[i]=r
else
//Update the next of the previous one
call MoveLocation(q,GetLocationX(q),CS_h2r(r))
endif
if (r==null) then
//This was the last one, update it in the array as well
set udg_csfreeindexes[i+4096]=q
endif
call RemoveLocation(loc)
set loc=q
endif
set q=loc
set loc=r
endloop
if (cleaned) then
set udg_csarray1[146]=1
else
set udg_csarray1[146]=udg_csarray1[i+1]
endif
call TimerStart(GetExpiredTimer(),0.2,false,function Array_TryFree)
endfunction
function InitArrayIndexes takes nothing returns nothing
local integer i=0
local integer a=1
local integer b=1
local integer c
loop
exitwhen (i==8192)
set udg_csarray1[i]=0
set udg_csarray2[i]=0
set i=i+1
endloop
set udg_csfreeindexes[0]=null //The stack for the table indexes.
set i=1
loop
exitwhen (a>144) //max size is 144
set c=a+b
set a=b
set b=c
set udg_csfreeindexes[b]=null //the first of the list
set udg_csfreeindexes[b+4096]=null //the last of the list
loop
exitwhen (i>b)
set udg_csarray1[i]=b
set i=i+1
endloop
endloop
set udg_csarray1[i]=c //i is 145
set udg_csarray1[146]=1
set udg_csarray1[147]=0
set udg_csarray1[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 gamecache g=CSCache()
local integer i
local integer rsize=udg_csarray1[size]
local location loc
set g=null
set loc=udg_csfreeindexes[rsize]
if (loc!=null) then
set udg_csfreeindexes[rsize]=CS_ly(udg_csfreeindexes[rsize])
if (udg_csfreeindexes[rsize]==null) then
set udg_csfreeindexes[4096+rsize]=null
endif
set i=CS_r2i(GetLocationX(loc))
call RemoveLocation(loc)
set loc=null
else
set i=udg_csarray1[0]+1
set udg_csarray1[0]=i+rsize
endif
if (i<8192) then
set udg_csarray1[i]=size
elseif (i<16384) then
set udg_csarray2[i-8192]=size
else
//using gamecache not to simulate an array but as a table should work well here.
call StoreInteger(CSCache(),"arrayinfo"+I2S(i),I2S(i),size)
//yes, it would leak even more strings. But it makes cleaning easier. (see later)
endif
if (not doinit) then
return i
endif
// 2
//[i][i+1][i+2]
set size=i+size
if (size>=16384) then
set size=16383
endif
loop
exitwhen (size<=i) or (size<8192)
set udg_csarray2[size-8192]=0
set size=size-1
endloop
loop
exitwhen (size<=i)
set udg_csarray1[size]=0
set size=size-1
endloop
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 location loc
if (id<8192) then
set L=udg_csarray1[udg_csarray1[id]]
elseif (id<16384) then
set L=udg_csarray1[udg_csarray2[id-8192]]
else
set L=udg_csarray1[GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(id))]
endif
call FlushStoredMission(CSCache(),"arrayinfo"+I2S(id)) // Just in case string indexes were used
if (id+L>=16384) then
if (id+L==udg_csarray1[0]) then
//We just destroyed the array that happens to be at the end of the heap.
//Just get it back
set udg_csarray1[0]=id-1
set udg_csarray1[146]=1
else
//Add to the last
set loc=udg_csfreeindexes[L+4096]
if (loc==null) then
set loc=Location(CS_i2r(id),CS_h2r(null))
set udg_csfreeindexes[L]=loc
set udg_csfreeindexes[L+4096]=loc
else
set udg_csfreeindexes[L+4096]=Location(CS_i2r(id),CS_h2r(null))
call MoveLocation(loc,GetLocationX(loc),CS_h2r(udg_csfreeindexes[L+4096]) )
endif
set loc=null
endif
elseif (id+L==udg_csarray1[0]) then
//We just destroyed the array that happens to be at the end of the heap.
//Just get it back
set udg_csarray1[0]=id-1
set udg_csarray1[146]=1
else
set loc=udg_csfreeindexes[L]
set udg_csfreeindexes[L]=Location(CS_i2r(id),CS_h2r(loc))
if (loc==null) then
set udg_csfreeindexes[L+4096]=udg_csfreeindexes[L]
else
set loc=null
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+1
if (index<8192) then
set udg_csarray1[index]=val
elseif (index<16384) then
set udg_csarray2[index-8192]=val
else
call StoreInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index),val)
endif
endfunction
function GetArrayInt takes integer id, integer index returns integer
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+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
set index=id+index+1
call StoreString(CSCache(),"arrayinfo"+I2S(id),I2S(index),val)
endfunction
function GetArrayString takes integer id, integer index returns string
set index=id+index+1
return GetStoredString(CSCache(),"arrayinfo"+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+1
if (index<8192) then
set udg_csarray1[index]=CS_r2i(val)
elseif (index<16384) then
set udg_csarray2[index-8192]=CS_r2i(val)
else
call StoreInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index),CS_r2i(val))
endif
endfunction
function GetArrayReal takes integer id, integer index returns real
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+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+1
if (index<8192) then
set udg_csarray1[index]=CS_H2I(val)
elseif (index<16384) then
set udg_csarray2[index-8192]=CS_H2I(val)
else
call StoreInteger(CSCache(),"arrayinfo"+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+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayWidget takes integer id, integer index returns widget
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayTimer takes integer id, integer index returns timer
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayUnit takes integer id, integer index returns unit
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayLoc takes integer id, integer index returns location
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayTrigger takes integer id, integer index returns trigger
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayTriggerAction takes integer id, integer index returns triggeraction
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayGroup takes integer id, integer index returns group
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayEffect takes integer id, integer index returns effect
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayItem takes integer id, integer index returns item
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(index))
return null
endfunction
function GetArrayLightning takes integer id, integer index returns lightning
set index=id+index+1
if (index<8192) then
return udg_csarray1[index]
elseif (index<16384) then
return udg_csarray2[index-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+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<8192) then
return udg_csarray1[id]
elseif (id<16384) then
return udg_csarray2[id-8192]
endif
return GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(id))
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<8192) then
set sz=udg_csarray1[id]
elseif (id<16384) then
set sz=udg_csarray2[id-8192]
else
set sz=GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(id))
endif
set i=NewArray(i,false)
set sz2=i+sz
set sz=id+sz
set x=i+1
set y=id+1
loop
exitwhen ((y>sz) or (y>=8192) or (x>=8192))
set udg_csarray1[x]=udg_csarray1[y]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=8192) or (x>=16384))
set udg_csarray2[x-8192]=udg_csarray1[y]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=8192))
call StoreInteger(CSCache(),"arrayinfo"+I2S(i),I2S(x),udg_csarray1[y])
set x=y+1
set y=y+1
endloop
//...
loop
exitwhen ((y>sz) or (y>=16384) or (x>=8192))
set udg_csarray1[x]=udg_csarray2[y-8192]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=16384) or (x>=16384))
set udg_csarray2[x-16384]=udg_csarray2[y-8192]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=16384))
call StoreInteger(CSCache(),"arrayinfo"+I2S(i),I2S(x),udg_csarray2[y-8192])
set y=y+1
set x=x+1
endloop
//...
loop
exitwhen ((y>sz) or (x>=8192))
set udg_csarray1[x]=GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(y))
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (x>=16384))
set udg_csarray2[x-16384]=GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(y))
set y=y+1
set x=x+1
endloop
loop
exitwhen (y>sz)
call StoreInteger(CSCache(),"arrayinfo"+I2S(i),I2S(x),GetStoredInteger(CSCache(),"arrayinfo"+I2S(id),I2S(y)))
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(CSCache(),I2S(CS_H2I(h)),label)
else
call StoreInteger(CSCache(),I2S(CS_H2I(h)),label,x)
endif
endfunction
function GetAttachedInt takes handle h, string label returns integer
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
endfunction
//=============================================================================================================
function AttachReal takes handle h, string label, real x returns nothing
if x==0 then
call FlushStoredReal(CSCache(),I2S(CS_H2I(h)),label)
else
call StoreReal(CSCache(),I2S(CS_H2I(h)),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
if not x then
call FlushStoredBoolean(CSCache(),I2S(CS_H2I(h)),label)
else
call StoreBoolean(CSCache(),I2S(CS_H2I(h)),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
if ((x=="") or (x==null)) then
call FlushStoredString(CSCache(),I2S(CS_H2I(h)),label)
else
call StoreString(CSCache(),I2S(CS_H2I(h)),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
if (x==null) then
call FlushStoredInteger(CSCache(),I2S(CS_H2I(h)),label)
else
call StoreInteger(CSCache(),I2S(CS_H2I(h)),label,CS_H2I(x))
endif
endfunction
function GetAttachedObject takes handle h, string label returns handle
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedWidget takes handle h, string label returns widget
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedRect takes handle h, string label returns rect
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedRegion takes handle h, string label returns region
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedTimerDialog takes handle h, string label returns timerdialog
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedUnit takes handle h, string label returns unit
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedItem takes handle h, string label returns item
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedEffect takes handle h, string label returns effect
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedDestructable takes handle h, string label returns destructable
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedTrigger takes handle h, string label returns trigger
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedTimer takes handle h, string label returns timer
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedGroup takes handle h, string label returns group
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedTriggerAction takes handle h, string label returns triggeraction
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedLightning takes handle h, string label returns lightning
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedImage takes handle h, string label returns image
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedUbersplat takes handle h, string label returns ubersplat
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedSound takes handle h, string label returns sound
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
function GetAttachedLoc takes handle h, string label returns location
return GetStoredInteger(CSCache(), I2S(CS_H2I(h)), label)
return null
endfunction
//============================================================================================================
function CleanAttachedVars takes handle h returns nothing
call FlushStoredMission(CSCache(),I2S(CS_H2I(h)))
endfunction
//============================================================================================================
// Left for compat
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 location loc=udg_csfreeindexes[0]
local integer i
if (loc!=null) then
set i=CS_r2i(GetLocationX(loc))
set udg_csfreeindexes[0]=CS_ly(loc)
call RemoveLocation(loc)
set loc=null
return i
endif
set i=udg_csarray1[147]+1
set udg_csarray1[147]=i
return i
endfunction
function NewTable takes nothing returns string
local location loc=udg_csfreeindexes[0]
local integer i
if (loc!=null) then
set i=CS_r2i(GetLocationX(loc))
set udg_csfreeindexes[0]=CS_ly(loc)
call RemoveLocation(loc)
set loc=null
return I2S(i)
endif
set i=udg_csarray1[147]+1
set udg_csarray1[147]=i
return I2S(i)
endfunction
function GetAttachmentTable takes handle h returns string
return I2S(CS_H2I(h))
endfunction
//============================================================================================================
function DestroyTable takes string table returns nothing
local integer i=S2I(table)
local integer n
call FlushStoredMission(CSCache(),table)
if ((i>100) and (i<1000000)) then //All right, more than 1000000 tables is just wrong.
if (i==udg_csarray1[147]) then
set udg_csarray1[147]=udg_csarray1[147]-1
else
set udg_csfreeindexes[0]=Location(CS_i2r(i),CS_h2r(udg_csfreeindexes[0]))
endif
endif
endfunction
//============================================================================================================
function ClearTable takes string table returns nothing
call FlushStoredMission(CSCache(),table)
endfunction
//============================================================================================================
function SetTableInt takes string table, string field, integer val returns nothing
if (val==0) then
call FlushStoredInteger(CSCache(),table,field)
else
call StoreInteger(CSCache(),table,field,val)
endif
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
if (val==0) then
call FlushStoredReal(CSCache(),table,field)
else
call StoreReal(CSCache(),table,field,val)
endif
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
if (not(val)) then
call FlushStoredBoolean(CSCache(),table,field)
else
call StoreBoolean(CSCache(),table,field,val)
endif
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
if (val=="") or (val==null) then
call FlushStoredString(CSCache(),table,field)
else
call StoreString(CSCache(),table,field,val)
endif
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
if (val==null) then
call FlushStoredInteger(CSCache(),table,field)
else
call StoreInteger(CSCache(),table,field,CS_H2I(val))
endif
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
function GetTableLoc takes string table, string field returns location
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 integer i=1
local string k=I2S(FieldData)
local string k2
local string k3
local integer n=GetStoredInteger(CSCache(),k,"N")
local integer t
loop
exitwhen (i>n)
set k2=I2S(i)
set t=GetStoredInteger(udg_cscache,k,k2)
set k3=GetStoredString(udg_cscache,k,k2)
if (t==bj_GAMECACHE_BOOLEAN) then
if (HaveStoredBoolean(udg_cscache,sourceTable,k3)) then
call StoreBoolean(udg_cscache,destTable,k3,GetStoredBoolean(udg_cscache,sourceTable,k3))
else
call FlushStoredBoolean(udg_cscache,destTable,k3)
endif
elseif (t==bj_GAMECACHE_INTEGER) then
if (HaveStoredInteger(udg_cscache,sourceTable,k3)) then
call StoreInteger(udg_cscache,destTable,k3,GetStoredInteger(udg_cscache,sourceTable,k3))
else
call FlushStoredInteger(udg_cscache,destTable,k3)
endif
elseif (t==bj_GAMECACHE_REAL) then
if (HaveStoredReal(udg_cscache,sourceTable,k3)) then
call StoreReal(udg_cscache,destTable,k3,GetStoredReal(udg_cscache,sourceTable,k3))
else
call FlushStoredReal(udg_cscache,destTable,k3)
endif
elseif (t==bj_GAMECACHE_STRING) then
if (HaveStoredString(udg_cscache,sourceTable,k3)) then
call StoreString(udg_cscache,destTable,k3,GetStoredString(udg_cscache,sourceTable,k3))
else
call FlushStoredString(udg_cscache,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
//============================================================================================================
// 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(CSCache(),k,"N")+1
local string k2=I2S(n)
call StoreString(udg_cscache,k,k2,field)
call StoreInteger(udg_cscache,k,k2,valueType)
call StoreInteger(udg_cscache,k,"N",n)
endfunction
//=============================================================================================
// Destroys Field Data
function FieldData_Destroy takes integer fielddata returns nothing
call DestroyTable(I2S(fielddata))
endfunction
//##End of CS Gamecache engine##
//##Start##
//Caster System 13.6 ( http://wc3campaigns.net/vexorian )
//====================================================================================================================================================================
constant function Caster_UnitId takes nothing returns integer
return 'e000' //// Caster Unit type rawcode (changes betwen maps, always use it inside '')
endfunction
constant function Caster_DefaultAttackType takes nothing returns attacktype
return ATTACK_TYPE_CHAOS // Default attack type used by the old functions and when you use 0 as DamageOptions
endfunction
constant function Caster_DefaultDamageType takes nothing returns damagetype
return DAMAGE_TYPE_UNIVERSAL // Default damage type used by the old functions and when you use 0 as DamageOptions
endfunction
constant function DamageTreeDetectorId takes nothing returns integer
return 'Aeat' /// The eat tree ability, don't need to change this rawcode unless you modiffied that ability in your map, in that case copy it, reset the copied one and use its rawcode here.
endfunction
constant function ChangeableFlyingHeightAllowerId takes nothing returns integer
return 'Amrf' /// Medivh's Crow form ability, don't need to change this rawcode unless you modiffied that ability in your map, in that case copy it, reset the copied one and use its rawcode here.
endfunction
constant function CS_MaxCollisionSize takes nothing returns real
return 55. //Maximum collision size in your map
endfunction
constant function CS_Cycle takes nothing returns real
return 0.04 // Cycle value for the projectile movement in seconds (Each 0.04 the projectiles get moved)
// 0.01 looks smooth but is lag friendly
// 0.1 looks horrible but is not laggy
// 0.04 is decent for the human eye and quite efficient.
// 0.05 would be an improvement in efficiency but probably doesn't look too well
endfunction
function CS_InventoryId takes nothing returns integer
return 'AInv' //Rawcode of any inventory ability, prefferably one with 6 slots
//Currently it is Inventory (Hero)
endfunction
//=================================================================================================
function CS_Rawcode2Real takes integer i returns real
return i
return 0.
endfunction
function CS_LoadRawcodeFromReal takes integer n returns integer
return udg_castervars[n]
return 0
endfunction
function CS_CopyGroup takes group g returns group
set bj_groupAddGroupDest=CreateGroup()
call ForGroup(g, function GroupAddGroupEnum)
return bj_groupAddGroupDest
endfunction
function CS_IsUnitVisible takes unit u, player p returns boolean
return IsUnitVisible(u,Player(bj_PLAYER_NEUTRAL_VICTIM)) or IsUnitVisible(u,p)
endfunction
constant function CS_RectLimitOffSet takes nothing returns real
return 50.0
endfunction
function CS_SafeX takes real x returns real
local rect r=bj_mapInitialPlayableArea
local real t=GetRectMinX(r)+CS_RectLimitOffSet()
if (x<t) then
set x=t
else
set t=GetRectMaxX(r)-CS_RectLimitOffSet()
if (x>t) then
set x=t
endif
endif
set r=null
return(x)
endfunction
function CS_SafeY takes real y returns real
local rect r=bj_mapInitialPlayableArea
local real t=GetRectMinY(r)+CS_RectLimitOffSet()
if (y<t) then
set y=t
else
set t=GetRectMaxY(r)-CS_RectLimitOffSet()
if (y>t) then
set y=t
endif
endif
set r=null
return(y)
endfunction
function CS_MoveUnit takes unit u, real x, real y returns boolean
local rect r=bj_mapInitialPlayableArea
local real t=GetRectMinX(r)+CS_RectLimitOffSet()
local boolean b=true
if (x<t) then
set x=t
set b=false
else
set t=GetRectMaxX(r)-CS_RectLimitOffSet()
if (x>t) then
set b=false
set x=t
endif
endif
set t=GetRectMinY(r)+CS_RectLimitOffSet()
if (y<t) then
set y=t
set b=false
else
set t=GetRectMaxY(r)-CS_RectLimitOffSet()
if (y>t) then
set y=t
set b=false
endif
endif
if (b) then
call SetUnitX(u, x)
call SetUnitY(u, y)
endif
set r=null
return b
endfunction
function CS_MoveUnitLoc takes unit u, location loc returns boolean
return CS_MoveUnit(u,GetLocationX(loc),GetLocationY(loc))
endfunction
//==================================================================================================
function CS_EnumUnitsInAOE_Filter takes nothing returns boolean
return IsUnitInRangeLoc(GetFilterUnit(), bj_enumDestructableCenter ,bj_enumDestructableRadius)
endfunction
//==================================================================================================
// Use this version when you only have coordinates of the point.
//
function CS_EnumUnitsInAOE takes group g, real x, real y, real area, boolexpr bx returns nothing
local boolexpr cond
local boolexpr aux=Condition(function CS_EnumUnitsInAOE_Filter)
if (bx==null) then
set cond=aux
else
set cond=And(aux,bx)
endif
set bj_enumDestructableCenter=Location(x,y)
set bj_enumDestructableRadius=area
call GroupEnumUnitsInRange(g,x,y,CS_MaxCollisionSize()+area,cond)
call DestroyBoolExpr(cond)
if (bx!=null) then
call DestroyBoolExpr(aux)
endif
call RemoveLocation(bj_enumDestructableCenter)
set aux=null
set cond=null
endfunction
//==================================================================================================
// Use this version whenever you already have a location for that point, to save some steps
//
function CS_EnumUnitsInAOELoc takes group g, location loc, real area, boolexpr bx returns nothing
local boolexpr cond
local boolexpr aux=Condition(function CS_EnumUnitsInAOE_Filter)
if (bx==null) then
set cond=aux
else
set cond=And(aux,bx)
endif
set bj_enumDestructableCenter=loc
set bj_enumDestructableRadius=area
call GroupEnumUnitsInRangeOfLoc(g,loc,CS_MaxCollisionSize()+area,cond)
call DestroyBoolExpr(cond)
if (bx!=null) then
call DestroyBoolExpr(aux)
endif
set aux=null
set cond=null
endfunction
//==================================================================================================
// Angle Calculations
//
// I decided to add them to the caster system, because I found myself using them everytime, I am
// trying to convert the caster system into a Spell Development Framework (hehe)
//
//=================================================================================================
// Returns the angle distance between angles a1 and a2 (For example: a1=30 , a2=60 , return= 30 )
//
function Angles_GetAngleDifference takes real a1, real a2 returns real
local real x
set a1=ModuloReal(a1,360)
set a2=ModuloReal(a2,360)
if a1>a2 then
set x=a1
set a1=a2
set a2=x
endif
set x=a2-360
if a2-a1 > a1-x then
set a2=x
endif
set x=a1-a2
if (x<0) then
return -x
endif
return x
endfunction
//=================================================================================================
// Returns the mid angle between a1 and a2 (For example: a1=30 , a2=60 , return= 45 )
//
function Angles_GetMidAngle takes real a1, real a2 returns real
local real x
set a1=ModuloReal(a1,360)
set a2=ModuloReal(a2,360)
if a1>a2 then
set x=a1
set a1=a2
set a2=x
endif
set x=a2-360
if a2-a1 > a1-x then
set a2=x
endif
return (a1+a2)/2
endfunction
//=================================================================================================
// Makes angle a1 advance i units towards angle a2 (For Example: a1=30, a2=60, i=10, return=40 )
//
function Angles_MoveAngleTowardsAngle takes real a1, real a2, real i returns real
local real x
set a1=ModuloReal(a1,360)
set a2=ModuloReal(a2,360)
if a1>a2 then
set x=a1-360
if a1-a2 > a2-x then
set a1=x
endif
else
set x=a2-360
if a2-a1 > a1-x then
set a2=x
endif
endif
if a1>a2 then
set x=a1-i
if x<=a2 then
return a2
endif
return x
endif
set x=a1+i
if x>=a2 then
return a2
endif
return x
endfunction
//=================================================================================================
// Returns true if the angle 'angle' is between 'angle1' and 'angle2'
//
function Angles_IsAngleBetweenAngles takes real angle, real angle1, real angle2 returns boolean
local real x
set angle=ModuloReal(angle,360)
set angle1=ModuloReal(angle1,360)
set angle2=ModuloReal(angle2,360)
if (angle1>angle2) then
set x=angle1
set angle1=angle2
set angle2=x
endif
if (angle2-angle1)>(angle1 - (angle2-360)) then
set angle2=angle2-360
if angle > 180 then
set angle=angle-360
endif
return angle>=angle2 and angle<=angle1
endif
return (angle>=angle1) and (angle<=angle2)
endfunction
//====================================================================================================================================================================
function CreateCaster takes real fac, real x , real y returns unit
local unit m
if (x!=0) then
set x=CS_SafeX(x)
endif
if (y!=0) then
set y=CS_SafeY(y)
endif
set m=CreateUnit( Player(15), Caster_UnitId(), x ,y ,fac)
call UnitAddAbility(m, 'Aloc')
call UnitAddAbility(m, ChangeableFlyingHeightAllowerId())
call UnitRemoveAbility(m, ChangeableFlyingHeightAllowerId())
set udg_currentcaster=m
set m=null
return udg_currentcaster
endfunction
function AddCasterFacing takes real fac returns unit
return CreateCaster(fac,0,0)
endfunction
function AddCaster takes nothing returns unit
return CreateCaster(0,0,0)
endfunction
//====================================================================================================================================================================
function CS_KillTrigger takes trigger t returns nothing
if (t!=null) then
call TriggerRemoveAction(t,GetAttachedTriggerAction(t,"ac"))
call CleanAttachedVars(t)
call DestroyTrigger(t)
endif
endfunction
function CS_KillTimer takes timer t returns nothing
if (t!=null) then
call PauseTimer(t)
call CleanAttachedVars(t)
call DestroyTimer(t)
endif
endfunction
//====================================================================================================================================================================
function CreateCasters takes integer n returns nothing
local integer a=0
local unit c
set udg_castervars[100]=-1
set udg_castervars[101]=-1
set udg_castervars[102]=-1
set udg_castervars[103]=-1
set udg_castervars[104]=-1
loop
exitwhen a>=n
set c=AddCaster()
call GroupAddUnit( udg_casters, c)
set a=a+1
endloop
set c=null
call RemoveLocation(udg_sourcehack)
set udg_sourcehack=null
endfunction
//====================================================================================================================================================================
function GetACaster takes nothing returns unit
set udg_currentcaster=FirstOfGroup( udg_casters)
if udg_currentcaster == null then
set udg_currentcaster=AddCaster()
endif
call GroupRemoveUnit( udg_casters,udg_currentcaster)
call SetUnitState( udg_currentcaster, UNIT_STATE_MANA, 1000)
return udg_currentcaster
endfunction
//====================================================================================================================================================================
function Caster_SetZAngle takes unit caster, real ang returns nothing
local real a=(ModuloReal(GetUnitFacing(caster),360)*bj_DEGTORAD)
local real x
set ang=ModuloReal(ang,360)
if ( ang == 90 ) then
set ang = 89
endif
if ( ang == 270 ) then
set ang = 271
endif
if (ang>90) and (ang<270) then
set x=-1
else
set x=1
endif
set ang=ang*bj_DEGTORAD
call SetUnitLookAt(caster,"Bone_Chest",caster, 10000.0*Cos(a)*Cos(ang), 10000.0*Sin(a)*Cos(ang), x*(10000.0*Tan(ang)+90.0) )
endfunction
//====================================================================================================================================================================
function Caster_SetZAngle2 takes unit caster, integer ang returns nothing
call SetUnitAnimationByIndex(caster,ang+90) //Thanks infrane!
endfunction
//====================================================================================================================================================================
function RecicleCaster takes unit caster returns nothing
if GetWidgetLife(caster)>=0.405 then
call ResetUnitLookAt(caster)
call SetUnitOwner( caster, Player(15), true)
call SetUnitVertexColor( caster, 255,255,255,255)
call SetUnitScale( caster, 1,1,1)
call SetUnitTimeScale( caster, 1)
call SetUnitMoveSpeed( caster, 522)
call SetUnitFlyHeight( caster, 0,0)
call UnitAddAbility(caster, 'Aloc')
call SetUnitTurnSpeed( caster, 0.6)
call GroupAddUnit( udg_casters, caster)
endif
endfunction
function CasterRecycleTimed_X takes nothing returns nothing
local timer t=GetExpiredTimer()
local string k=GetAttachmentTable(t)
local unit c=GetTableUnit(k,"c")
local integer a=GetTableInt(k,"a")
if (a!=0) then
call UnitRemoveAbility(c,a)
endif
call RecicleCaster(c)
call ClearTable(k)
call DestroyTimer(t)
set c=null
set t=null
endfunction
function CasterRecycleTimed takes unit caster, integer abi, real delay returns nothing
local timer t=CreateTimer()
local string k=GetAttachmentTable(t)
call SetTableObject(k,"c",caster)
if (abi!=0) then
call SetTableInt(k,"a",abi)
endif
call TimerStart(t,delay,false,function CasterRecycleTimed_X)
set t=null
endfunction
function CasterWaitForEndCast takes nothing returns nothing
local unit caster=udg_currentcaster
local integer abilid=udg_currentabi
local real delay=udg_castervars[0]
local boolean activeability=(udg_castervars[1]>0)
loop
exitwhen GetUnitCurrentOrder(caster) == 0
call TriggerSleepAction(0)
endloop
if (delay>0) then
if activeability then
call CasterRecycleTimed(caster,abilid,delay)
else
call UnitRemoveAbility( caster, abilid)
call CasterRecycleTimed(caster,0,delay)
endif
else
call UnitRemoveAbility( caster, abilid)
call RecicleCaster(caster)
endif
set caster=null
endfunction
function RecicleCasterAfterCastEx takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
set udg_castervars[0]=delaytime
set udg_castervars[1]=IntegerTertiaryOp(activeability,1,0)
set udg_currentabi=abilid
set udg_currentcaster=caster
call ExecuteFunc("CasterWaitForEndCast" )
endfunction
function RecicleCasterAfterCast takes unit caster, integer abilid returns nothing
call RecicleCasterAfterCastEx(caster,udg_delayhack,abilid,false)
endfunction
//====================================================================================================================================================================
function PreloadAbility takes integer abilid returns integer
local unit u=FirstOfGroup(udg_casters)
if u==null then
set u=GetACaster()
call UnitAddAbility(u, abilid)
call UnitRemoveAbility(u, abilid)
call RecicleCaster( u)
else
call UnitAddAbility(u, abilid)
call UnitRemoveAbility(u, abilid)
endif
set u=null
return abilid
endfunction
//====================================================================================================================================================================
function CasterCastAbilityEx takes player owner, real x, real y, real z, integer abilid, integer level, string order, widget target, real delay returns unit
local unit caster=GetACaster()
local boolean done=false
call SetUnitOwner( caster, owner, false)
call UnitAddAbility( caster, abilid)
call SetUnitAbilityLevel(caster,abilid,level)
call CS_MoveUnit( caster, x,y)
call SetUnitFlyHeight(caster,z,0)
if S2I(order) != 0 then
set done=IssueTargetOrderById( caster, S2I(order), target )
else
set done=IssueTargetOrder( caster, order, target )
endif
if (delay<=0) or not(done) then
call UnitRemoveAbility( caster, abilid)
call RecicleCaster( caster)
else
call RecicleCasterAfterCastEx(caster, delay, abilid, true)
endif
set udg_currentcaster=caster
set caster=null
return udg_currentcaster
endfunction
//====================================================================================================================================================================
function CasterCastAbilityExLoc takes player owner, location loc, real z, integer abilid, integer level, string order, widget target, real delay returns unit
return CasterCastAbilityEx(owner,GetLocationX(loc),GetLocationY(loc),z,abilid,level,order,target,delay)
endfunction
//====================================================================================================================================================================
function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, widget target, boolean instant returns unit
local real x
local real y
local real d
if udg_sourcehack!=null then
set x=GetLocationX(udg_sourcehack)
set y=GetLocationY(udg_sourcehack)
else
set x=GetWidgetX(target)
set y=GetWidgetY(target)
endif
if not(instant) then
set d=udg_delayhack+0.01
else
set d=0
endif
return CasterCastAbilityEx(owner,x,y,0,abilid,level,order,target,d)
endfunction
//====================================================================================================================================================================
function CasterCastAbility takes player owner, integer abilid, string order, widget target, boolean instant returns unit
return CasterCastAbilityLevel( owner, abilid, 1, order, target, instant )
endfunction
//====================================================================================================================================================================
function CasterCastAbilityPointEx takes player owner, real x1, real y1, real z1, integer abilid, integer level, string order, real x2, real y2, real delay returns unit
local unit caster=GetACaster()
call SetUnitOwner( caster, owner, false)
call UnitAddAbility( caster, abilid)
call SetUnitAbilityLevel(caster,abilid,level)
call CS_MoveUnit( caster, x1, y1)
call SetUnitFlyHeight(caster,z1,0)
if S2I(order) != 0 then
if not IssuePointOrderById( caster, S2I(order), x2,y2 ) then
call IssueImmediateOrderById( caster, S2I(order) )
endif
else
if not IssuePointOrder( caster, order, x2,y2 ) then
call IssueImmediateOrder( caster, order )
endif
endif
if (delay<=0) then
call UnitRemoveAbility( caster, abilid)
call RecicleCaster( caster)
else
call RecicleCasterAfterCastEx(caster, delay, abilid, true)
endif
set udg_currentcaster=caster
set caster=null
return udg_currentcaster
endfunction
//====================================================================================================================================================================
function CasterCastAbilityPointExLoc takes player owner, location loc1, real z1, integer abilid, integer level, string order, location loc2, real delay returns unit
return CasterCastAbilityPointEx(owner,GetLocationX(loc1),GetLocationY(loc1),z1,abilid,level,order,GetLocationX(loc2),GetLocationY(loc2),delay)
endfunction
//====================================================================================================================================================================
function CasterCastAbilityLevelPoint takes player owner, integer abilid, integer level, string order, real x, real y, boolean instant returns unit
local real sx
local real sy
local real d
if udg_sourcehack!=null then
set sx=GetLocationX(udg_sourcehack)
set sy=GetLocationY(udg_sourcehack)
else
set sx=x
set sy=y
endif
if instant then
set d=0
else
set d=udg_delayhack+0.01
endif
return CasterCastAbilityPointEx(owner,sx,sy,0,abilid,level,order,x,y,d)
endfunction
function CasterCastAbilityPoint takes player owner, integer abilid, string order, real x, real y, boolean instant returns unit
return CasterCastAbilityLevelPoint(owner,abilid,1,order,x,y,instant)
endfunction
function CasterCastAbilityPointLoc takes player owner, integer abilid, string order, location loc, boolean instant returns unit
return CasterCastAbilityLevelPoint( owner, abilid, 1,order, GetLocationX(loc), GetLocationY(loc), instant )
endfunction
function CasterCastAbilityLevelPointLoc takes player owner, integer abilid, integer level, string order, location loc, boolean instant returns unit
return CasterCastAbilityLevelPoint( owner, abilid, level,order, GetLocationX(loc), GetLocationY(loc), instant )
endfunction
//====================================================================================================================================================================
function CasterUseAbilityLevelStatic_Rec takes nothing returns nothing
local timer t=GetExpiredTimer()
local string k=GetAttachmentTable(t)
call RecicleCaster(GetTableUnit(k,"c"))
call ClearTable(k)
call DestroyTimer(t)
set t=null
endfunction
function CasterUseAbilityLevelStatic_X takes nothing returns nothing
local timer t=GetExpiredTimer()
local string k=GetAttachmentTable(t)
call DestroyEffect(GetTableEffect(k,"fx") )
call UnitRemoveAbility(GetTableUnit(k,"c"),GetTableInt(k,"a"))
call TimerStart(t,2,false, function CasterUseAbilityLevelStatic_Rec)
set t=null
endfunction
function CasterUseAbilityLevelStatic takes player owner, string modelpath, integer abilityid, integer level, real duration, real x, real y returns unit
local timer t=CreateTimer()
local string k=GetAttachmentTable(t)
local unit c=GetACaster()
call SetUnitPosition( c, x, y)
call SetTableObject(k,"fx", AddSpecialEffectTarget( modelpath, c,"origin" ))
call SetTableObject(k,"c",c)
call SetTableInt(k,"a",abilityid)
call TimerStart(t,duration,false,function CasterUseAbilityLevelStatic_X)
call SetUnitOwner(c, owner, true)
call UnitAddAbility(c, abilityid)
call SetUnitAbilityLevel(c, abilityid, level)
set udg_currentcaster=c
set t=null
set c=null
return udg_currentcaster
endfunction
function CasterUseAbilityStatic takes player owner, string modelpath, integer abilityid, real duration, real x, real y returns unit
return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,1,duration,x,y)
endfunction
function CasterUseAbilityStaticLoc takes player owner, string modelpath, integer abilityid, real duration, location loc returns unit
return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,1,duration, GetLocationX(loc), GetLocationY(loc))
endfunction
function CasterUseAbilityLevelStaticLoc takes player owner, string modelpath, integer abilityid, integer level,real duration, location loc returns unit
return CasterUseAbilityLevelStatic(owner,modelpath,abilityid,level,duration, GetLocationX(loc), GetLocationY(loc))
endfunction
//====================================================================================================================================================================
function CasterCastAbilityLevelGroup takes player owner, integer abilid, integer level,string order, group targetgroup, boolean instant returns nothing
local group affected
local unit tempunit
local unit caster=null
if bj_wantDestroyGroup then
set bj_wantDestroyGroup=false
set affected=targetgroup
else
set affected=CreateGroup()
call GroupAddGroup( targetgroup, affected)
endif
loop
set tempunit=FirstOfGroup(affected)
exitwhen tempunit == null
if instant then
if caster==null then
set caster=GetACaster()
call SetUnitOwner( caster, owner, false)
call UnitAddAbility( caster, abilid)
call SetUnitAbilityLevel( caster, abilid,level)
endif
if udg_sourcehack != null then
call CS_MoveUnit(caster,GetLocationX(udg_sourcehack),GetLocationY(udg_sourcehack))
else
call CS_MoveUnit( caster, GetUnitX(tempunit), GetUnitY(tempunit))
endif
if S2I(order) != 0 then
call IssueTargetOrderById( caster, S2I(order), tempunit )
else
call IssueTargetOrder( caster, order, tempunit )
endif
else
call CasterCastAbilityLevel( owner, abilid,level, order, tempunit, false)
endif
call GroupRemoveUnit(affected, tempunit)
endloop
if caster != null then
call UnitRemoveAbility( caster, abilid)
call RecicleCaster(caster)
endif
call DestroyGroup(affected)
set affected=null
set tempunit=null
set caster=null
endfunction
function CasterCastAbilityGroup takes player owner, integer abilid, string order, group targetgroup, boolean instant returns nothing
call CasterCastAbilityLevelGroup(owner,abilid,1,order,targetgroup,instant)
endfunction
//====================================================================================================================================================================
function CasterAOE_IsFilterEnemy takes nothing returns boolean
return IsUnitEnemy( GetFilterUnit(), bj_groupEnumOwningPlayer ) and not(IsUnitDeadBJ(GetFilterUnit()))
endfunction
function CasterAOE_IsFilterAlly takes nothing returns boolean
return IsUnitAlly( GetFilterUnit(), bj_groupEnumOwningPlayer ) and not(IsUnitDeadBJ(GetFilterUnit()))
endfunction
//====================================================================================================================================================================
function CasterCastAbilityLevelAOE takes player owner, integer abilid, integer level, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
local boolexpr b
local group aoe=CreateGroup()
set bj_groupEnumOwningPlayer=owner
if goodeffect then
set b=Condition(function CasterAOE_IsFilterAlly)
else
set b=Condition(function CasterAOE_IsFilterEnemy)
endif
call CS_EnumUnitsInAOE(aoe, x,y, radius, b)
set bj_wantDestroyGroup=true
call CasterCastAbilityLevelGroup( owner, abilid, level, order, aoe, instant)
call DestroyBoolExpr(b)
set b=null
set aoe=null
endfunction
function CasterCastAbilityAOE takes player owner, integer abilid, string order, real x, real y, real radius, boolean goodeffect, boolean instant returns nothing
call CasterCastAbilityLevelAOE(owner,abilid,1,order,x,y,radius,goodeffect,instant)
endfunction
function CasterCastAbilityAOELoc takes player owner, integer abilid, string order, location center, real radius, boolean goodeffect, boolean instant returns nothing
call CasterCastAbilityLevelAOE(owner, abilid,1, order, GetLocationX(center), GetLocationY(center), radius, goodeffect, instant)
endfunction
function CasterCastAbilityLevelAOELoc takes player owner, integer abilid, integer level, string order, location center, real radius, boolean goodeffect, boolean instant returns nothing
call CasterCastAbilityLevelAOE(owner, abilid,level, order, GetLocationX(center), GetLocationY(center), radius, goodeffect, instant)
endfunction
//====================================================================================================================================================================
function ResetSourceHack takes nothing returns nothing
call RemoveLocation(udg_sourcehack)
set udg_sourcehack=null
call DestroyTimer(GetExpiredTimer() )
endfunction
function CasterSetCastSource takes real x, real y returns nothing
set udg_sourcehack=Location(x,y)
call TimerStart(CreateTimer(),0,false,function ResetSourceHack)
endfunction
function CasterSetCastSourceLoc takes location loc returns nothing
call CasterSetCastSource( GetLocationX(loc), GetLocationY(loc) )
endfunction
function ResetDelayHack takes nothing returns nothing
set udg_delayhack=0
call DestroyTimer(GetExpiredTimer() )
endfunction
//====================================================================================================================================================================
function CasterSetRecycleDelay takes real Delay returns nothing
set udg_delayhack=Delay
call TimerStart(CreateTimer(),0,false,function ResetDelayHack)
endfunction
//====================================================================================================================================================================
function DamageTypes takes attacktype attT, damagetype dmgT returns integer
set udg_castervars[100] = CS_H2I(attT)
set udg_castervars[101] = CS_H2I(dmgT)
return 1
endfunction
function DamageException takes unittype Exception, real ExceptionFactor returns integer
set udg_castervars[102] = CS_H2I(Exception)
set udg_castervars[103] = ExceptionFactor
return 2
endfunction
function DamageOnlyTo takes unittype ThisUnitType returns integer
set udg_castervars[104] = CS_H2I(ThisUnitType)
return 4
endfunction
constant function DontDamageSelf takes nothing returns integer
return 8
endfunction
constant function DamageTrees takes nothing returns integer
return 16
endfunction
constant function DamageOnlyVisibles takes nothing returns integer
return 32
endfunction
function DamageOnlyEnemies takes nothing returns integer
set udg_castervars[105]=0
return 64
endfunction
function ForceDamageAllies takes nothing returns integer
set udg_castervars[105]=1
return 64
endfunction
function DamageOnlyAllies takes nothing returns integer
set udg_castervars[105]=2
return 64
endfunction
function DamageFactorAbility1 takes integer spellid, real factor returns integer
set udg_castervars[106]=CS_Rawcode2Real(spellid)
set udg_castervars[107]=factor
return 128
endfunction
function DamageFactorAbility2 takes integer spellid, real factor returns integer
set udg_castervars[108]=CS_Rawcode2Real(spellid)
set udg_castervars[109]=factor
return 256
endfunction
function DamageFactorAbility3 takes integer spellid, real factor returns integer
set udg_castervars[110]=CS_Rawcode2Real(spellid)
set udg_castervars[111]=factor
return 512
endfunction
function DamageIgnore takes unittype ThisUnitType returns integer
set udg_castervars[112] = CS_H2I(ThisUnitType)
return 1024
endfunction
function DamageAlliedFactor takes real fct returns integer
set udg_castervars[113] = fct
return 2048
endfunction
constant function ConsiderOnlyDeadUnits takes nothing returns integer
return 4096
endfunction
constant function IgnoreDeadState takes nothing returns integer
return 8192
endfunction
//===============================================================================================
function IsDamageOptionIncluded takes integer DamageOptions, integer whichDamageOption returns boolean
local integer i=8192
if (DamageOptions==0) then
return false
endif
loop
exitwhen (i<=whichDamageOption)
if (DamageOptions>=i) then
set DamageOptions=DamageOptions-i
endif
set i=i/2
endloop
return (DamageOptions>=whichDamageOption)
endfunction
//=================================================================================================
function GetDamageFactor takes unit u,attacktype a, damagetype d returns real
local real hp=GetWidgetLife(u)
local real mana=GetUnitState(u,UNIT_STATE_MANA)
local real r
local unit caster=GetACaster()
call UnitRemoveAbility(caster,'Aloc') //Otherwise the units would flee like crazy
call CS_MoveUnit(caster,GetUnitX(u),GetUnitY(u))
call SetUnitOwner(caster,GetOwningPlayer(u),false)
set r=hp
if (hp<1) then
call SetWidgetLife(u,1)
set r=1
endif
call UnitDamageTarget(caster,u,0.01,true,false,a,d,null)
call RecicleCaster(caster)
if (mana>GetUnitState(u,UNIT_STATE_MANA)) then
//Unit had mana shield, return 1 and restore mana too.
call SetUnitState(u,UNIT_STATE_MANA,mana)
set r=1
else
set r= (r-GetWidgetLife(u))*100
endif
call SetWidgetLife(u,hp)
set caster=null
return r
endfunction
//======================================================================================================
// Fix for the unit type bugs from blizzard, amphibious units aren't considered ground for some reason
// so this considers any non flying unit as ground.
//
// Also heroes are resistant too, so in case UNIT_TYPE_RESISTANT is used it will return true in case the
// unit is a hero too.
//
function CS_IsUnitType takes unit u, unittype ut returns boolean
if (ut==UNIT_TYPE_GROUND) then
return not(IsUnitType(u,UNIT_TYPE_FLYING))
elseif (ut==UNIT_TYPE_RESISTANT) then
return IsUnitType(u,ut) or IsUnitType(u,UNIT_TYPE_HERO)
endif
return IsUnitType(u,ut)
endfunction
function GetDamageFactorByOptions takes unit hurter, unit target, integer d returns real
local real r=1
if (d>=8192) then
set d=d-8192
elseif (d>=4096) then
if (GetWidgetLife(target)>0.405) then
return 0.0
endif
set d=d-4096
elseif (GetWidgetLife(target)<=0.405) then
return 0.0
endif
if d>=2048 then
if IsUnitAlly(target,GetOwningPlayer(hurter)) then
set r=r*udg_castervars[113]
endif
set d=d-2048
endif
if d>=1024 then
if CS_IsUnitType(target, ConvertUnitType(R2I(udg_castervars[112])) ) then
return 0.0
endif
set d=d-1024
endif
if d>=512 then
if GetUnitAbilityLevel(target,CS_LoadRawcodeFromReal(110))>0 then
set r=r*udg_castervars[111]
endif
set d=d-512
endif
if d>=256 then
if GetUnitAbilityLevel(target,CS_LoadRawcodeFromReal(108))>0 then
set r=r*udg_castervars[109]
endif
set d=d-256
endif
if d>=128 then
if GetUnitAbilityLevel(target,CS_LoadRawcodeFromReal(106))>0 then
set r=r*udg_castervars[107]
endif
set d=d-128
endif
if d>=64 then
if (udg_castervars[105]==0) and IsUnitAlly(target,GetOwningPlayer(hurter)) then
return 0.0
elseif (udg_castervars[105]==2) and IsUnitEnemy(target,GetOwningPlayer(hurter)) then
return 0.0
endif
set d=d-64
endif
if d>=32 then
set d=d-32
if not CS_IsUnitVisible(target,GetOwningPlayer(hurter)) then
return 0.0
endif
endif
if d>=16 then
set d=d-16
endif
if d>=8 then
set d=d-8
if hurter==target then
return 0.0
endif
endif
if d>=4 then
set d=d-4
if not CS_IsUnitType( target, ConvertUnitType(R2I(udg_castervars[104])) ) then
return 0.0
endif
endif
if d>=2 then
set d=d-2
if CS_IsUnitType( target, ConvertUnitType(R2I(udg_castervars[102])) ) then
set r=r*udg_castervars[103]
endif
endif
if d>=1 then
set d=d-1
set r=r*GetDamageFactor(target,ConvertAttackType(R2I(udg_castervars[100])),ConvertDamageType(R2I(udg_castervars[101])))
endif
return r
endfunction
//======================================================================================================================
// This used to be needed because in 1.17 UnitDamageTarget didn't consider the damagetype argument, this bug
// was fixed in 1.18, and we no longer need this function, left for compatibility.
//
function DamageUnitByTypes takes unit hurter, unit target, real dmg, attacktype attT, damagetype dmgT returns boolean
return UnitDamageTarget(hurter,target,dmg,true,false,attT,dmgT,null)
endfunction
//=============================================================================================================================
function DamageUnitByOptions takes unit hurter, unit target, real dmg, integer DamageOptions returns boolean
local real f=GetDamageFactorByOptions(hurter,target,DamageOptions)
if (f==0) then
return false
endif
return UnitDamageTarget(hurter,target,dmg*f,true,false,null,null,null)
endfunction
//=============================================================================================================================
function DamageUnit takes player hurter, real damage, unit victim returns boolean
local unit caster=GetACaster()
call UnitRemoveAbility(caster,'Aloc') //Otherwise the units would flee like crazy
call CS_MoveUnit(caster,GetUnitX(victim),GetUnitY(victim))
call SetUnitOwner(caster,hurter,false)
call DamageUnitByTypes(caster,victim,damage,Caster_DefaultAttackType(),Caster_DefaultDamageType())
call RecicleCaster(caster)
return GetWidgetLife(victim)<=0 // I thought UnitDamageTarget returned true when it killed the unit, but nope, it returns true when it was able to do the damage.
endfunction
//====================================================================================================================================================================
function UnitDamageUnitTimed_Child takes nothing returns nothing
local real damage = udg_castervars[0]
local real damageperiod= udg_castervars[2]
local effect fx=bj_lastCreatedEffect
local timer t=CreateTimer()
local unit hurter=udg_currenthurter
local real next=0
local integer i=0
local real c
local unit target=udg_currentcaster
local damagetype dmgT=ConvertDamageType(R2I(udg_castervars[4]))
local attacktype attT=ConvertAttackType(R2I(udg_castervars[3]))
call TimerStart(t, udg_castervars[1]-0.01, false,null)
loop
if TimerGetElapsed(t) >= next then
exitwhen not UnitDamageTarget(hurter, target, damage,true,false, attT, dmgT,null)
exitwhen IsUnitDeadBJ(target)
set i=i+1
set next=i*damageperiod
endif
exitwhen (TimerGetRemaining(t) <= 0) or IsUnitDeadBJ(target)
call TriggerSleepAction(0)
endloop
call DestroyEffect(fx)
call DestroyTimer(t)
set t=null
set fx=null
set dmgT=null
set attT=null
endfunction
function UnitDamageUnitTimed takes unit hurter, real damageps, real damageperiod, real duration, unit target, string modelpath, string attachPointName, attacktype attT, damagetype dmgT returns nothing
local unit c=udg_currentcaster
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, target,attachPointName )
set udg_currentcaster=target
set udg_castervars[0]=damageps
set udg_castervars[1]=duration
set udg_castervars[2]=damageperiod
set udg_castervars[3]=CS_H2I(attT)
set udg_castervars[4]=CS_H2I(dmgT)
set udg_currenthurter=hurter
call ExecuteFunc("UnitDamageUnitTimed_Child")
set udg_currentcaster=c
set c=null
endfunction
//=============================================================================================================
// Left for compatibility
//
function DamageUnitTimedEx_Child takes nothing returns nothing
local real damage = udg_castervars[0]
local real damageperiod= udg_castervars[2]
local effect fx=bj_lastCreatedEffect
local timer t=CreateTimer()
local integer id=udg_currentabi
local real next=0
local integer i=0
local real c
local unit target=udg_currentcaster
call TimerStart(t, udg_castervars[1]-0.01, false,null)
loop
if TimerGetElapsed(t) >= next then
exitwhen DamageUnit( Player(id), damage, target)
set i=i+1
set next=i*damageperiod
endif
exitwhen (TimerGetRemaining(t) <= 0) or IsUnitDeadBJ(target)
call TriggerSleepAction(0)
endloop
call DestroyEffect(fx)
call DestroyTimer(t)
set t=null
set fx=null
endfunction
function DamageUnitTimedEx takes player owner, real damageps, real damageperiod, real duration, unit target, string modelpath, string attachPointName returns nothing
local unit c=udg_currentcaster
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, target,attachPointName )
set udg_currentcaster=target
set udg_castervars[0]=damageps
set udg_castervars[1]=duration
set udg_castervars[2]=damageperiod
set udg_currentabi=GetPlayerId( owner )
call ExecuteFunc("DamageUnitTimedEx_Child")
set udg_currentcaster=c
set c=null
endfunction
function DamageUnitTimed takes player owner, real damageps, real duration, unit target, string modelpath, string attachPointName returns nothing
call DamageUnitTimedEx(owner , damageps, 1, duration, target, modelpath, attachPointName )
endfunction
//[
function SetDamageOptions_i takes integer k, integer DamageOptions returns nothing
local integer d=DamageOptions
call SetArrayInt(k,0,d) //[0=value]
if (d>=8192) then
set d=d-8192
endif
if (d>=4096) then
set d=d-4096
endif
if d>=2048 then
call SetArrayReal(k,14,udg_castervars[113]) //[14=allf]
set d=d-2048
endif
if d>=1024 then
call SetArrayInt(k,13,R2I(udg_castervars[112])) //[13=ign]
set d=d-1024
endif
if d>=512 then
call SetArrayInt(k,11,CS_LoadRawcodeFromReal(110)) //[11=ab3]
call SetArrayReal(k,12,udg_castervars[111]) //[12=fc3]
set d=d-512
endif
if d>=256 then
call SetArrayInt(k,9,CS_LoadRawcodeFromReal(110)) //[9=ab2]
call SetArrayReal(k,10,udg_castervars[111]) //[10=fc2]
set d=d-256
endif
if d>=128 then
call SetArrayInt(k,7,CS_LoadRawcodeFromReal(110)) //[7=ab1]
call SetArrayReal(k,8,udg_castervars[111]) //[8=fc1]
set d=d-128
endif
//[0 integer value][1 integer attT][2 integer dmgT][3 integer excp][4 real excf][5 integer only]
//[6 integer allied][7 integer ab1][8 real fc1][9 integer ab2][10 real fc2][11 integer ab3][12 real fc3]
//[13 integer ign][14 real allf]
if d >= 64 then
set d=d-64
call SetArrayInt(k,6,R2I(udg_castervars[105])) //[6=allied]
endif
if d >= 32 then
set d=d-32
endif
if d >= 16 then
set d=d-16
endif
if d >= 8 then
set d=d-8
endif
if d >= 4 then
call SetArrayInt(k,5,R2I(udg_castervars[104])) //[5=only]
set d=d-4
endif
if d >= 2 then
call SetArrayInt(k,3,R2I(udg_castervars[102])) //[3=excp]
call SetArrayReal(k,4,udg_castervars[103]) //[4=excf]
set d=d-2
endif
if d >= 1 then
call SetArrayInt(k,1,R2I(udg_castervars[100])) //[1=Attt]
call SetArrayInt(k,2,R2I(udg_castervars[101])) //[2=dmgT]
endif
endfunction
function SetDamageOptions takes integer id, integer DamageOptions returns nothing
call SetDamageOptions_i(id,DamageOptions)
endfunction
function CreateDamageOptions takes integer DamageOptions returns integer
local integer n =NewArray(15,false) //I am sure this won't access any non-initialized value
call SetDamageOptions_i(n,DamageOptions)
return n
endfunction
function DestroyDamageOptions takes integer id returns nothing
call DestroyArray(id)
endfunction
function LoadDamageOptions takes integer id returns integer
local gamecache g=CSCache()
local integer opt=GetArrayInt(id,0) //[0=value]
local integer v=opt
if v>=8192 then
set v=v-8192
endif
if v>=4096 then
set v=v-4096
endif
if v>=2048 then
set udg_castervars[113]=GetArrayReal(id,14) //[14=allf]
set v=v-2028
endif
if v>=1024 then
set udg_castervars[112]= GetArrayInt(id,13) //[13=ign]
set v=v-1024
endif
if v>=512 then
set udg_castervars[110]=CS_Rawcode2Real(GetArrayInt(id,11)) //[11=ab3]
set udg_castervars[111]=GetArrayReal(id,12) //[12=fc3]
set v=v-512
endif
if v>=256 then
set udg_castervars[108]=CS_Rawcode2Real(GetArrayInt(id,9)) //[9=ab2]
set udg_castervars[109]=GetArrayReal(id,10) //[10=fc2]
set v=v-256
endif
if v>=128 then
set udg_castervars[106]=CS_Rawcode2Real(GetArrayInt(id,7)) //[7=ab1]
set udg_castervars[107]=GetArrayReal(id,8) //[8=fc1]
set v=v-128
endif
if v >= 64 then
set v=v-64
set udg_castervars[105]= GetArrayInt(id,6) //[6==allied]
endif
if v >= 32 then
set v=v-32
endif
if v >= 16 then
set v=v-16
endif
if v >= 8 then
set v=v-8
endif
//[0 integer value][1 integer attT][2 integer dmgT][3 integer excp][4 real excf][5 integer only]
//[6 integer allied][7 integer ab1][8 real fc1][9 integer ab2][10 real fc2][11 integer ab3][12 real fc3]
//[13 integer ign][14 real allf]
if v >= 4 then
set udg_castervars[104]=GetArrayInt(id,5) //only
set v=v-4
endif
if v >= 2 then
set udg_castervars[102]=GetArrayInt(id,3) //excp
set udg_castervars[103]=GetArrayReal(id,4) //excf
set v=v-2
endif
if v >= 1 then
set udg_castervars[100]=GetArrayInt(id,1) //aTTt
set udg_castervars[101]=GetArrayInt(id,2) //dmgT
endif
set g=null
return opt
endfunction
//==================================================================================================
function IsDestructableTree_withcs takes destructable d returns boolean
local unit c=GetACaster()
local boolean b
local boolean i=IsDestructableInvulnerable(d)
local integer s=DamageTreeDetectorId()
if i then
call SetDestructableInvulnerable(d,false)
endif
call UnitAddAbility(c,s)
call CS_MoveUnit(c,GetWidgetX(d),GetWidgetY(d))
set b=(IssueTargetOrder(c,"eattree",d))
call UnitRemoveAbility(c,s)
call RecicleCaster(c)
set c=null
if i then
call SetDestructableInvulnerable(d,true)
endif
return b
endfunction
function IsDestructableTree takes destructable d returns boolean
local gamecache g=CSCache()
local string k=I2S(GetDestructableTypeId(d))
local boolean b
if HaveStoredBoolean(g,"trees",k) then
set b=GetStoredBoolean(g,"trees",k)
set g=null
return b
else
set b=IsDestructableTree_withcs(d)
call StoreBoolean(g,"trees",k,b)
endif
set g=null
return b
endfunction
//===============================================================================================
function DamageDestructablesInCircleEnum takes nothing returns nothing
local destructable d=GetEnumDestructable()
local unit u=udg_currentcaster
if (GetWidgetLife(d)>0) and not(IsDestructableInvulnerable(d)) and ((Pow(GetDestructableX(d)-udg_castervars[200],2)+Pow(GetDestructableY(d)-udg_castervars[201],2)) <= udg_castervars[202]) then
call SetWidgetLife(d,GetWidgetLife(d)-udg_castervars[203])
endif
set udg_currentcaster=u
set u=null
set d=null
endfunction
function DamageDestructablesInCircle takes real x, real y, real radius, real dmg returns nothing
local rect r=Rect(x - radius,y - radius,x + radius,y + radius)
set udg_castervars[200]=x
set udg_castervars[201]=y
set udg_castervars[202]=radius*radius
set udg_castervars[203]=dmg
call EnumDestructablesInRect(r,null,function DamageDestructablesInCircleEnum)
call RemoveRect(r)
set r=null
endfunction
function DamageDestructablesInCircleLoc takes location loc, real radius, real dmg returns nothing
call DamageDestructablesInCircle(GetLocationX(loc),GetLocationY(loc),radius,dmg)
endfunction
function DamageTreesInCircleEnum takes nothing returns nothing
local destructable d=GetEnumDestructable()
if (GetWidgetLife(d)>0) and not(IsDestructableInvulnerable(d)) and ((Pow(GetDestructableX(d)-udg_castervars[200],2)+Pow(GetDestructableY(d)-udg_castervars[201],2)) <= udg_castervars[202]) and (IsDestructableTree(d)) then
call KillDestructable(d)
endif
set d=null
endfunction
function DamageTreesInCircle takes real x, real y, real radius returns nothing
local rect r=Rect(x - radius,y - radius,x + radius,y + radius)
set udg_castervars[200]=x
set udg_castervars[201]=y
set udg_castervars[202]=radius*radius
call EnumDestructablesInRect(r,null,function DamageTreesInCircleEnum)
call RemoveRect(r)
set r=null
endfunction
function DamageTreesInCircleLoc takes location loc, real radius returns nothing
call DamageTreesInCircle(GetLocationX(loc),GetLocationY(loc),radius)
endfunction
function DamageUnitGroupEx takes unit hurter, real damage, group targetgroup, integer DamageOptions returns nothing
local group affected
local unit p
if bj_wantDestroyGroup then
set bj_wantDestroyGroup=false
set affected=targetgroup
else
set affected=CreateGroup()
call GroupAddGroup( targetgroup, affected)
endif
loop
set p=FirstOfGroup(affected)
exitwhen p==null
call DamageUnitByOptions(hurter,p,damage,DamageOptions)
call GroupRemoveUnit(affected,p)
endloop
call DestroyGroup(affected)
set affected=null
set p=null
endfunction
function DamageUnitsInAOEEx takes unit hurter, real damage, real x, real y, real radius, boolean affectallied, integer DamageOptions returns nothing
local boolexpr b=null
local group aoe=CreateGroup()
local integer d=DamageOptions
set bj_groupEnumOwningPlayer=GetOwningPlayer(hurter)
if d>=8192 then
set d=d-8192
endif
if d>=4096 then
set d=d-4096
endif
if d>=2048 then
set d=d-2048
endif
if d>=1024 then
set d=d-1024
endif
if d>=512 then
set d=d-512
endif
if d>=256 then
set d=d-256
endif
if d>=128 then
set d=d-128
endif
if d>=64 then
if (udg_castervars[105]==2) then
set b=Condition(function CasterAOE_IsFilterAlly)
elseif (udg_castervars[105]==1) then
else
set b=Condition(function CasterAOE_IsFilterEnemy)
endif
set d=d-64
elseif not(affectallied) then
set b=Condition(function CasterAOE_IsFilterEnemy)
endif
if d>=32 then
set d=d-32
endif
if d>=16 then
call DamageTreesInCircle(x,y,radius)
endif
call CS_EnumUnitsInAOE(aoe, x,y, radius, b)
set bj_wantDestroyGroup=true
call DamageUnitGroupEx( hurter, damage, aoe,DamageOptions)
call DestroyBoolExpr(b)
set b=null
set aoe=null
endfunction
function DamageUnitsInAOEExLoc takes unit hurter, real damage, location loc, real radius, boolean affectallied, integer DamageOptions returns nothing
call DamageUnitsInAOEEx(hurter,damage, GetLocationX(loc), GetLocationY(loc), radius, affectallied,DamageOptions)
endfunction
function DamageUnitGroup takes player hurter, real damage, group targetgroup returns nothing
local unit caster=GetACaster()
call UnitRemoveAbility(caster,'Aloc') //Otherwise the units would flee like crazy
call SetUnitOwner(caster,hurter,false)
call DamageUnitGroupEx(caster,damage,targetgroup,0)
call RecicleCaster(caster)
set caster=null
endfunction
//====================================================================================================================================================================
function DamageUnitsInAOE takes player hurter, real damage, real x, real y, real radius, boolean affectallied returns nothing
local unit caster=GetACaster()
call UnitRemoveAbility(caster,'Aloc') //Otherwise the units would flee like crazy
call SetUnitOwner(caster,hurter,false)
call DamageUnitsInAOEEx(caster,damage,x,y,radius,affectallied,0)
call RecicleCaster(caster)
set caster=null
endfunction
function DamageUnitsInAOELoc takes player hurter, real damage, location loc, real radius, boolean affectallied returns nothing
call DamageUnitsInAOE( hurter, damage, GetLocationX(loc), GetLocationY(loc), radius, affectallied)
endfunction
//====================================================================================================================================================================
function AddAreaDamagerForUnit_Child takes nothing returns nothing
local real D
local real damageps = udg_castervars[0]
local real area = udg_castervars[2]
local real damageperiod = udg_castervars[3]
local real excd=udg_castervars[8]
local boolean affectallies = (udg_castervars[4]>=1)
local boolean onlyallies = (udg_castervars[4]==2)
local boolean self = (udg_castervars[5]==1)
local unit hurter=udg_currenthurter
local unit fire = udg_currentcaster
local player owner = GetOwningPlayer(fire)
local timer t = CreateTimer()
local real next = 0
local integer a = 0
local group inrange = CreateGroup()
local string c
local string art=bj_lastPlayedMusic
local string attach=""
local unit picked
local boolean recicled=false
local unittype only=null
local unittype ign=null
local unittype exce=null
local attacktype attT
local damagetype dmgT
local boolean trees=(udg_castervars[11]==1)
local boolean inv=(udg_castervars[12]==1)
local integer a1=0
local integer a2=0
local integer a3=0
local real f1=udg_castervars[107]
local real f2=udg_castervars[109]
local real f3=udg_castervars[111]
local real allf=udg_castervars[113]
local effect array fx
local integer deadcond=R2I(udg_castervars[114])
local boolean deadeval=false
local integer fxn=0
set fx[0]=bj_lastCreatedEffect
if f1!=1 then
set a1=CS_LoadRawcodeFromReal(106)
endif
if f2!=1 then
set a2=CS_LoadRawcodeFromReal(108)
endif
if f3!=1 then
set a3=CS_LoadRawcodeFromReal(110)
endif
if udg_castervars[112]!=-1 then
set ign=ConvertUnitType(R2I(udg_castervars[112]))
endif
if udg_castervars[6]!=-1 then
set only=ConvertUnitType(R2I(udg_castervars[6]))
endif
if udg_castervars[7]!=-1 then
set exce=ConvertUnitType(R2I(udg_castervars[7]))
endif
if udg_castervars[9]!=-1 then
set attT=ConvertAttackType(R2I(udg_castervars[9]))
else
set attT=Caster_DefaultAttackType()
endif
if udg_castervars[10]!=-1 then
set dmgT=ConvertDamageType(R2I(udg_castervars[10]))
else
set dmgT=Caster_DefaultDamageType()
endif
loop
set c=SubString(art,a,a+1)
exitwhen c=="!" or c==""
set attach=attach+c
set a=a+1
endloop
set art=SubString(art,a+1,10000)
call TimerStart(t, udg_castervars[1]-0.01, false,null)
set a=0
loop
loop
exitwhen fxn<=0
call DestroyEffect(fx[fxn])
set fx[fxn]=null
set fxn=fxn-1
endloop
if IsUnitInGroup( fire, udg_casters) then
set recicled=true
call GroupRemoveUnit( udg_casters,fire)
endif
exitwhen recicled
if TimerGetElapsed(t) >= next then
set a=a+1
set next=a*damageperiod
call CS_EnumUnitsInAOE(inrange, GetUnitX(fire), GetUnitY(fire), area, null )
if trees then
call DamageTreesInCircle(GetUnitX(fire), GetUnitY(fire), area)
endif
loop
set picked=FirstOfGroup(inrange)
exitwhen picked==null
if (deadcond==0) then
set deadeval=(GetWidgetLife(picked)>0.405)
elseif(deadcond==1)then
set deadeval=(GetWidgetLife(picked)<=0.405)
else
set deadeval=true
endif
if (self or picked!=hurter) and not(IsUnitDeadBJ(picked)) and ( ((affectallies or onlyallies) and IsUnitAlly(picked, owner)) or (not(onlyallies) and IsUnitEnemy(picked, owner)) ) and (only==null or CS_IsUnitType(picked,only)) and (ign==null or not(CS_IsUnitType(picked,ign))) then
set D=damageps
if (allf!=1) and IsUnitAlly(picked, owner) then
set D=D*allf
endif
if (exce!=null) and CS_IsUnitType(picked,exce) then
set D=D*excd
endif
if inv and not(CS_IsUnitVisible(picked,owner)) then
set D=0
endif
if (a1!=0) and (GetUnitAbilityLevel(picked,a1)>0) then
set D=D*f1
endif
if (a2!=0) and (GetUnitAbilityLevel(picked,a2)>0) then
set D=D*f2
endif
if (a3!=0) and (GetUnitAbilityLevel(picked,a3)>0) then
set D=D*f3
endif
if D!=0 then
call DamageUnitByTypes(hurter,picked,D,attT,dmgT )
if (art!="") and (art!=null) then
set fxn=fxn+1
set fx[fxn]=AddSpecialEffectTarget(art,picked,attach)
endif
endif
endif
call GroupRemoveUnit(inrange,picked)
endloop
endif
exitwhen TimerGetRemaining(t)<=0
call TriggerSleepAction(0)
endloop
call DestroyGroup(inrange)
call DestroyEffect(fx[0])
call TriggerSleepAction(2)
call RecicleCaster(fire)
call DestroyTimer(t)
set inrange=null
set fire=null
set t=null
set owner=null
set fx[0]=null
set picked=null
set hurter=null
set only=null
set ign=null
set exce=null
set attT=null
set dmgT=null
endfunction
function AddAreaDamagerForUnit takes unit hurter, string modelpath, string targetart, string targetattach, real x, real y, real damage , real damageperiod, real duration, real area, boolean affectallies, integer DamageOptions returns unit
local string s=bj_lastPlayedMusic
local integer v=DamageOptions
set bj_lastPlayedMusic=targetattach+"!"+targetart
set udg_currentcaster=GetACaster()
call SetUnitPosition( udg_currentcaster, x, y)
set bj_lastCreatedEffect = AddSpecialEffectTarget( modelpath, udg_currentcaster,"origin" )
set udg_castervars[0]=damage
set udg_castervars[1]=duration
set udg_castervars[2]=area
set udg_castervars[3]=damageperiod
if(v>=8192)then
set udg_castervars[114]=2
set v=v-8192
elseif (v>=4096)then
set udg_castervars[114]=1
set v=v-4096
else
set udg_castervars[114]=0
endif
if v>=2048 then
set v=v-2048
else
set udg_castervars[113]=1
endif
if v >= 1024 then
set v=v-1024
else
set udg_castervars[112]=-1
endif
if v >= 512 then
set v=v-512
else
set udg_castervars[111]=0
endif
if v >= 256 then
set v=v-256
else
set udg_castervars[109]=0
endif
if v >= 128 then
set v=v-128
else
set udg_castervars[107]=0
endif
if v >= 64 then
set v=v-64
set udg_castervars[4]=udg_castervars[105]
else
set udg_castervars[4]=IntegerTertiaryOp(affectallies,1,0)
endif
if v >= 32 then
set udg_castervars[12]=1
set v=v-32
else
set udg_castervars[12]=0
endif
if v >= 16 then
set udg_castervars[11]=1
set v=v-16
else
set udg_castervars[11]=0
endif
if v >= 8 then
set udg_castervars[5]=0
set v=v-8
else
set udg_castervars[5]=1
endif
if v >= 4 then
set udg_castervars[6]=udg_castervars[104]
set v=v-4
else
set udg_castervars[6]=-1
endif
if v >= 2 then
set udg_castervars[7]=udg_castervars[102]
set udg_castervars[8]=damage*udg_castervars[103]
set v=v-2
else
set udg_castervars[7]=-1
set udg_castervars[8]=-1
endif
if v >= 1 then
set udg_castervars[9]=udg_castervars[100]
set udg_castervars[10]=udg_castervars[101]
else
set udg_castervars[9]=-1
set udg_castervars[10]=-1
endif
set udg_currenthurter=hurter
call SetUnitOwner( udg_currentcaster, GetOwningPlayer(hurter), true)
call ExecuteFunc("AddAreaDamagerForUnit_Child")
set bj_lastPlayedMusic=s
return udg_currentcaster
endfunction
function AddAreaDamagerForUnitLoc takes unit hurter, string modelpath, string targetart, string targetattach, location loc, real damage , real damageperiod, real duration, real area, boolean affectallies, integer DamageOptions returns unit
return AddAreaDamagerForUnit(hurter,modelpath,targetart,targetattach,GetLocationX(loc),GetLocationY(loc), damage , damageperiod, duration, area,affectallies, DamageOptions)
endfunction
function AddDamagingEffectEx takes player owner, string modelpath, string targetart, string targetattach, real x, real y, real damage , real damageperiod, real duration, real area, boolean affectallies returns unit
local string s=bj_lastPlayedMusic
set bj_lastPlayedMusic=targetattach+"!"+targetart
set udg_currentcaster=GetACaster()
call SetUnitPosition( udg_currentcaster, x, y)
set bj_lastCreatedEffect = AddSpecialEffectTarget( modelpath, udg_currentcaster,"origin" )
set udg_castervars[0]=damage
set udg_castervars[1]=duration
set udg_castervars[2]=area
set udg_castervars[3]=damageperiod
set udg_castervars[4]=IntegerTertiaryOp(affectallies,1,0)
set udg_castervars[5]=1
set udg_castervars[6]=-1
set udg_castervars[7]=-1
set udg_castervars[8]=-1
set udg_castervars[9]=-1
set udg_castervars[10]=-1
set udg_castervars[107]=0
set udg_castervars[109]=0
set udg_castervars[111]=0
set udg_castervars[112]=-1
set udg_castervars[113]=1
set udg_currenthurter=udg_currentcaster
call SetUnitOwner( udg_currentcaster, owner, true)
call ExecuteFunc("AddAreaDamagerForUnit_Child")
set bj_lastPlayedMusic=s
return udg_currentcaster
endfunction
function AddDamagingEffectExLoc takes player owner, string modelpath, string targetart, string targetattach, location loc, real damage , real damageperiod, real duration, real area, boolean affectallies returns unit
return AddDamagingEffectEx( owner, modelpath, targetart, targetattach, GetLocationX(loc), GetLocationY(loc), damage , damageperiod, duration, area, affectallies )
endfunction
function AddDamagingEffect takes player owner, string modelpath, real x, real y, real damageps , real duration, real area, boolean affectallies returns unit
return AddDamagingEffectEx( owner, modelpath, "", "", x, y, damageps , 1, duration, area, affectallies )
endfunction
function AddDamagingEffectLoc takes player owner, string modelpath, location loc, real damageps , real duration, real area, boolean affectallies returns unit
return AddDamagingEffectEx( owner, modelpath, "", "", GetLocationX(loc), GetLocationY(loc), damageps ,1, duration, area, affectallies)
endfunction
//============================================================================================================
function UnitMoveToAsProjectileAnySpeed_Move takes unit m, integer k returns boolean
local boolean tounit = (GetArrayInt(k,1)==1) //[1=unit]
local unit tg
local real x2
local real y2
local real z2
local real x1=GetUnitX(m)
local real y1=GetUnitY(m)
local real z1=GetUnitFlyHeight(m)
local real g
local real d
local real od
local real v
local real time
local integer n
local boolean done=false
local effect fx
if tounit then
set tg=GetArrayUnit(k,2) //[2=tg]
if (GetWidgetLife(tg)<=0.405) then
set tounit=false
call SetArrayInt(k,1,0) //[1=unit]
else
set x2=GetUnitX(tg)
set y2=GetUnitY(tg)
set z2=GetUnitFlyHeight(tg)+GetArrayReal(k,3) //[3=z2o]
set n=GetArrayInt(k,4) //[4=N]
set n=n+1
if (n==0) then
//Using the counter prevents us to save z2,x2,y2 too much times and saves speed
call SetArrayReal(k,5,z2) //[5=z2]
call SetArrayReal(k,6,x2) //[6=x2] // Backup stuff just in case
call SetArrayReal(k,7,y2) //[7=y2]
elseif (n==25) then
set n=0
endif
call SetArrayInt(k,4,n) //[4=N
endif
set tg=null
endif
if not(tounit) then
set z2=GetArrayReal(k,5) //[5=z2]
set x2=GetArrayReal(k,6) //[6=x2]
set y2=GetArrayReal(k,7) //[7=y2]
endif
set g=Atan2(y2-y1,x2-x1)
call SetUnitFacing(m,g*bj_RADTODEG)
set v=GetArrayReal(k,8) //[8=speed]
set d= v * CS_Cycle()
set od=SquareRoot(Pow(x1-x2,2) + Pow(y1-y2,2))
if( od <=d )then
call CS_MoveUnit(m , x2, y2 )
set done=true
else
call CS_MoveUnit(m , x1+d*Cos(g), y1+d*Sin(g) )
endif
set g=GetArrayReal(k,9) //[9=acel]
set time= od / v
set d=v
set v=(z2-z1+0.5*g*time*time)/time //z speed
if (GetUnitTypeId(m)==Caster_UnitId()) then
call SetUnitAnimationByIndex(m,R2I(Atan2(v,d)* bj_RADTODEG)+90) //Thanks infrane!
endif
call SetUnitFlyHeight(m,z1+v*CS_Cycle(),0)
set d=( Pow(GetUnitX(m)-x2,2) + Pow(GetUnitY(m)-y2,2) )
if (done or (d<=400)) then //So the actual distance is less than or equal to 20
set done=true
//[0 integer "type"][1 boolean "unit"][2 unit "tg"][3 real "z2o"][4 integer "N"][5 real "z2"][6 real "x2"][7 real "y2"]
//[8 real "speed"][9 real "acel"][10 boolean "done"][11 effect "fx"]
call SetArrayInt(k,10,1) //[10=done]
set fx=GetArrayEffect(k,11) //[11=fx]
if (fx!=null) then
call SetUnitAnimationByIndex(m,91)
call DestroyEffect(fx)
set fx=null
endif
endif
return done
endfunction
function CollisionMissile_Destroyer takes unit m, integer k, trigger T returns nothing
local effect fx=GetArrayEffect(k,17) //[17=fx]
call TriggerExecute(T)
if (fx!=null) then
call DestroyEffect(fx)
set fx=null
endif
call FlushStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)) )
call FlushStoredInteger(udg_cscache,"MOVEMENT_TABLES",I2S(CS_H2I(T)) )
if (GetArrayInt(k,19)==1) then //[19=new]
call ExplodeUnitBJ(m)
else
call RecicleCasterAfterCastEx(m,4,0,true)
endif
call TriggerRemoveAction(T,GetArrayTriggerAction(k,18)) //[18=triggeraction]
call DestroyArray(k)
call CleanAttachedVars(T)
call DestroyTrigger(T)
endfunction
function GetTriggerCollisionMissile takes nothing returns unit
return GetStoredInteger( CSCache(), I2S(CS_H2I(GetTriggeringTrigger())), "m" )
return null
endfunction
// [1 integer state][2 trigger T][3 real collision][4 real speed][5 real F][6 real aspeed][7 integer TType]
// [8 real Tx][9 real Ty][10 widget Tw][11 real F][12 real maxd][13 boolean pfx][14 real pfx_current][15 real pfx_dur]
// [17 fx][18 ac][19 boolean new]
function CollisionMissile_Move takes unit m, integer k returns boolean
local integer state=GetArrayInt(k,1)
local boolean done=(state==2)
local real d
local real F
local real asp
local real x
local real nx
local real y
local real ny
local integer tt
local widget wd
if not(done) then
if (state==1) then
// [T] [collision]
call TriggerRegisterUnitInRange(GetArrayTrigger(k,2),m,GetArrayReal(k,3),null)
call SetArrayInt(k,1,0) //[state]
endif
set d=GetArrayReal(k,4) * CS_Cycle() //speed
set F=GetArrayReal(k,5) //F
set asp=GetArrayReal(k,6) //aspeed
set x=GetUnitX(m)
set y=GetUnitY(m)
if (asp!=0) then
set tt=GetArrayInt(k,7) //"TType"
if (tt==1) or (tt==2) then
if (tt==1) then
set nx=GetArrayReal(k,8) //[Tx]
set ny=GetArrayReal(k,8) //[Ty]
else
set wd=GetArrayWidget(k,10) //[Tw]
if (GetWidgetLife(wd)<=0.405) then
call SetArrayInt(k,7,0) //TType
set nx=x+0.001
set ny=y+0.001
else
set nx=GetWidgetX(wd)
set ny=GetWidgetY(wd)
endif
set wd=null
endif
set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * CS_Cycle())
else
set F=F+ asp * CS_Cycle()
endif
call SetArrayReal(k,5,F) //[F]
call SetUnitFacing(m,F)
endif
set F=F*bj_DEGTORAD
set nx=x+d*Cos(F)
set ny=y+d*Sin(F)
set d=GetArrayReal(k,12)-d //[maxd]
call SetArrayReal(k,12,d) //[maxd]
set done=(d<=0)
if not(CS_MoveUnit(m,nx,ny)) then
call SetUnitX(m,x)
call SetUnitY(m,y)
set done=true
elseif (GetArrayInt(k,13)==1) then //[pfx]
set F=GetArrayReal(k,14)+CS_Cycle() //[14=pfx_current]
if (F>=GetArrayReal(k,15)) then //[15=pfx_dur]
call DestroyEffect(AddSpecialEffectTarget(GetArrayString(k,16), m, "origin" )) //[16=pfx_path]
call SetArrayReal(k,14,0) //[14=pfx_current]
else
call SetArrayReal(k,14,F) //[14=pfx_current]
endif
endif
endif
if done then
call CollisionMissile_Destroyer(m,k,GetArrayTrigger(k,2)) //[2=T]
endif
return done
endfunction
function CasterSystemMovementTimer takes nothing returns nothing
local timer ti=GetExpiredTimer()
local location L=GetTableLoc("CasterSystem","MOVEMENT_LIST")
local location B
local location A
local location T=GetLocationX_Loc(L)
local location F=null
local unit p
local integer k
local integer mtype
loop
exitwhen (T==null)
set A=T
set p=GetLocationX_Unit(A) //The list is a sequence of units and integers
set B=GetLocationY_Loc(A)
set k=GetLocationX_Int(B)
set T=GetLocationY_Loc(B)
set mtype=GetArrayInt(k,0)
if (mtype==2) then //[0: type , 2==collision missile]
if not(CollisionMissile_Move(p,k)) then
call MoveLocation(B,CS_i2r(k),CS_h2r(F))
set F=A
else
call RemoveLocation(A)
call RemoveLocation(B)
endif
elseif (mtype==1) then
if not(UnitMoveToAsProjectileAnySpeed_Move(p,k )) then
call MoveLocation(B,CS_i2r(k),CS_h2r(F))
set F=A
else
call RemoveLocation(A)
call RemoveLocation(B)
endif
else
call BJDebugMsg("Caster System: Unexpected Error (1) Wrong Array:"+I2S(k))
endif
endloop
if (F==null) then
call SetTableObject("CasterSystem","MOVEMENT_TIMER",null)
call RemoveLocation(L)
call SetTableObject("CasterSystem","MOVEMENT_LIST",null)
call DestroyTimer(ti)
else
call MoveLocation(L,CS_h2r(F),0.0)
endif
set p=null
set L=null
set T=null
set F=null
set ti=null
endfunction
function UnitMoveToAsProjectileAnySpeed_Effect takes unit m, effect fx, real speed, real arc, real x2, real y2, unit target, real z2 returns nothing
//
// The internal projectile system used by all the projectile functions
//
local timer t //=GetTableTimer("CasterSystem","MOVEMENT_TIMER")
local string km
local integer k
local location L
local location F
set km=I2S(CS_H2I(m))
set k=GetTableInt("MOVEMENT_TABLES",km)
if (k>0) then
call SetArrayInt(k,10,1) //[10=done]
endif
set k=NewArray(12,true)
call StoreInteger(udg_cscache,"MOVEMENT_TABLES",km,k)
if (HaveStoredInteger(CSCache(),"CasterSystem","MOVEMENT_TIMER")) then
set L=GetTableLoc("CasterSystem","MOVEMENT_LIST")
set F=Location(CS_i2r(k),GetLocationX(L))
set F=Location(CS_h2r(m),CS_h2r(F))
call MoveLocation(L,CS_h2r(F),0.0)
else
set t=CreateTimer()
call SetTableObject("CasterSystem","MOVEMENT_TIMER",t)
set F=Location(CS_i2r(k),CS_h2r(null))
set F=Location(CS_h2r(m),CS_h2r(F))
set L=Location(CS_h2r(F),0.0)
call SetTableObject("CasterSystem","MOVEMENT_LIST",L)
call TimerStart(t,CS_Cycle(),true,function CasterSystemMovementTimer)
set t=null
endif
set F=null
set L=null
call SetArrayInt(k,0,1) //[0:type(1==projectile)
if (target!=null) then
call SetArrayInt(k,1,1) //[1=unit]
call SetArrayObject(k,2,target) //[2=tg]
call SetArrayReal(k,6,GetUnitX(target)) //[6=x2]
call SetArrayReal(k,7,GetUnitY(target)) //[7=y2]
call SetArrayReal(k,3,z2) //[3=z2o]
else
call SetArrayReal(k,6,x2) //[6=x2]
call SetArrayReal(k,7,y2) //[7=y2]
endif
call SetArrayReal(k,5,z2) //[5=z2]
call SetArrayReal(k,8,speed) //[8=speed]
call SetArrayReal(k,9,arc*8000) //[9=acel]
if (fx!=null) then
call SetArrayObject(k,11,fx) //[11=fx]
set fx=null
endif
loop
exitwhen GetArrayInt(k,10)==1 //[10=done]
call TriggerSleepAction(0)
endloop
call StoreInteger(udg_cscache,"MOVEMENT_TABLES",km,0)
call DestroyArray(k)
endfunction
function UnitMoveToAsProjectileAnySpeed takes unit m, real speed, real arc, real x2, real y2, unit target, real z2 returns nothing
//Left for compat
call UnitMoveToAsProjectileAnySpeed_Effect(m,null,speed,arc,x2,y2,target,z2)
endfunction
//========================================================================================================================
function UnitMoveToAsProjectileGen takes unit m, real arc, real x2, real y2, unit target, real z2 returns nothing
//
// The internal projectile system used by all the projectile functions
//
local real x1=GetUnitX(m)
local real y1=GetUnitY(m)
local real acel=arc*1600
local real speed=GetUnitMoveSpeed(m)
local real z1=GetUnitFlyHeight(m)
local real d
local real d1
local real d2
local real t
local real vel
local real dif=0
local boolean tounit= (target!=null)
local boolean b=false
local boolean mode=false
if tounit then
set x2=GetUnitX(target)
set y2=GetUnitY(target)
set z2=GetUnitFlyHeight(target)+z2
endif
set mode=(z2>z1)
set d=SquareRoot(Pow(x2-x1,2)+Pow(y2-y1,2))
set d1=1000000
set d2=0
set t=d/speed
if t==0 then
set t=0.001
endif
set vel=(z2-z1+0.5*acel*t*t)/t
call SetUnitFacing( m, Atan2BJ(y2 - y1, x2 - x2) )
call IssuePointOrder( m, "move", x2,y2)
set t=0
loop
set d2=d1
if tounit then
if IsUnitDeadBJ(target) then
set tounit=false
else
set x2=GetUnitX(target)
set y2=GetUnitY(target)
endif
endif
set d1=SquareRoot(Pow(x2-GetUnitX(m),2)+Pow(y2-GetUnitY(m),2))
exitwhen b or d1==0
set b=(d1<=speed*(t-dif))
exitwhen (mode and b) or (GetUnitCurrentOrder(m) != OrderId("move"))
if tounit then
call IssuePointOrder( m, "move", x2,y2)
endif
set dif=t
if dif==0.001 then
set t=0.1
else
set t= (d-d1)/speed
endif
set t= 2*t-dif
call SetUnitFlyHeight( m, z1+(vel*t-0.5*acel*t*t), RAbsBJ( vel-acel*(t+dif)/2) )
set t=(t+dif)/2
call TriggerSleepAction(0)
endloop
if tounit then
set x2=GetUnitX(target)
set y2=GetUnitY(target)
endif
call SetUnitFlyHeight( m,z2,0)
call CS_MoveUnit(m,x2,y2)
endfunction
function UnitMoveToAsProjectile takes unit m, real arc, real x2, real y2, real z2 returns nothing
call UnitMoveToAsProjectileGen(m, arc,x2,y2,null,z2)
endfunction
//============================================================================================================
function ProjectileLaunchEx takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc,real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1),x1,y1 )
local effect fx=null
call SetUnitScale( m, scale, scale, scale)
call SetUnitVertexColor(m, red, green, blue, alpha)
call SetUnitFlyHeight( m, z1, 0)
set fx= AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
if (speed<=522) then
call SetUnitMoveSpeed(m, speed)
call UnitMoveToAsProjectile(m, arc, x2, y2, z2)
call DestroyEffect(fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed,arc,x2,y2,null,z2)
endif
call ExplodeUnitBJ(m)
set owner=null
set fx=null
set m=null
endfunction
function ProjectileLaunchExLoc takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, location loc1, real z1, location loc2, real z2 returns nothing
call ProjectileLaunchEx( owner, modelpath, scale, red, green, blue, alpha, speed, arc,GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2)
endfunction
//============================================================================================================
function ProjectileLaunch takes string modelpath, real speed, real arc,real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
call ProjectileLaunchEx( Player(15), modelpath, 1, 255, 255, 255, 255, speed, arc,x1,y1,z1,x2,y2,z2)
endfunction
function ProjectileLaunchLoc takes string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2 returns nothing
call ProjectileLaunchExLoc( Player(15), modelpath, 1,255,255,255,255,speed,arc,loc1,z1,loc2,z2)
endfunction
//============================================================================================================
function DamagingProjectileLaunchAOE_Child takes nothing returns nothing
local unit m=udg_currentcaster
local effect fx=bj_lastCreatedEffect
local real x2=udg_castervars[0]
local real y2=udg_castervars[1]
local real aoeradius=udg_castervars[3]
local real damage=udg_castervars[4]
local boolean affectallied=bj_isUnitGroupInRectResult
local integer V=CreateDamageOptions(R2I(udg_castervars[5]))
local unit hurter=udg_currenthurter
local real speed=udg_castervars[6]
if (speed<=522) then
call SetUnitMoveSpeed(m, speed)
call UnitMoveToAsProjectile(m, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], udg_castervars[2])
call DestroyEffect(fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed,bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1],null, udg_castervars[2])
endif
call DamageUnitsInAOEEx(hurter,damage,x2,y2,aoeradius,affectallied,LoadDamageOptions(V))
call DestroyDamageOptions(V)
call ExplodeUnitBJ(m)
set m=null
set fx=null
endfunction
function DamagingProjectileLaunchAOE takes unit hurter, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1) ,x1,y1)
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, GetOwningPlayer(hurter), true)
set bj_meleeNearestMineDist = arc
set udg_castervars[0] = x2
set udg_castervars[1] = y2
set udg_castervars[2] = z2
set udg_castervars[3] =aoeradius
set udg_castervars[4] =damage
set udg_castervars[5] =DamageOptions
set udg_castervars[6] =speed
set udg_currenthurter=hurter
set bj_isUnitGroupInRectResult=affectallied
call ExecuteFunc("DamagingProjectileLaunchAOE_Child")
set m=null
return udg_currentcaster
endfunction
function DamagingProjectileLaunchAOELoc takes unit hurter, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied, integer DamageOptions returns unit
return DamagingProjectileLaunchAOE(hurter,modelpath,speed,arc,GetLocationX(loc1),GetLocationY(loc1),z1,GetLocationX(loc2),GetLocationY(loc2),z2, aoeradius, damage, affectallied, DamageOptions )
endfunction
function ProjectileLaunchDamage takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2, real aoeradius, real damage, boolean affectallied returns unit
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1) ,x1,y1 )
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
set bj_meleeNearestMineDist = arc
set udg_castervars[0] = x2
set udg_castervars[1] = y2
set udg_castervars[2] = z2
set udg_castervars[3] =aoeradius
set udg_castervars[4] =damage
set udg_castervars[5] =0
set udg_castervars[6]= speed
set bj_isUnitGroupInRectResult=affectallied
set udg_currenthurter=m
call ExecuteFunc("DamagingProjectileLaunchAOE_Child")
set m=null
return udg_currentcaster
endfunction
function ProjectileLaunchDamageLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2, real aoeradius, real damage, boolean affectallied returns unit
return ProjectileLaunchDamage( owner, modelpath, speed, arc, GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2, aoeradius, damage, affectallied)
endfunction
//============================================================================================================
function ProjectileLaunchKill_Child takes nothing returns nothing
local unit m=udg_currentcaster
local effect fx=bj_lastCreatedEffect
local real x2=udg_castervars[0]
local real y2=udg_castervars[1]
local real speed=udg_castervars[3]
if (speed<=522) then
call SetUnitMoveSpeed( m, speed)
call UnitMoveToAsProjectile(m, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], udg_castervars[2])
call DestroyEffect( fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, bj_meleeNearestMineDist, udg_castervars[0], udg_castervars[1], null, udg_castervars[2])
endif
call ExplodeUnitBJ(m)
set m=null
set fx=null
endfunction
function ProjectileLaunchKill takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, real x2, real y2, real z2 returns unit
local unit m=CreateCaster( Atan2BJ(y2 - y1, x2 - x1),x1,y1 )
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
set bj_meleeNearestMineDist = arc
set udg_castervars[0] = x2
set udg_castervars[1] = y2
set udg_castervars[2] = z2
set udg_castervars[3] = speed
call ExecuteFunc("ProjectileLaunchKill_Child")
set m=null
return udg_currentcaster
endfunction
function ProjectileLaunchKillLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, location loc2, real z2 returns unit
return ProjectileLaunchKill( owner, modelpath, speed, arc, GetLocationX(loc1), GetLocationY(loc1), z1, GetLocationX(loc2), GetLocationY(loc2), z2)
endfunction
//====================================================================================================================================================================
function UnitMoveToUnitAsProjectile takes unit m, real arc, unit target, real zoffset returns nothing
call UnitMoveToAsProjectileGen(m, arc,0,0,target,zoffset)
endfunction
//====================================================================================================================================================================
function ProjectileLaunchToUnitEx takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset returns nothing
local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )
local effect fx=null
call SetUnitFlyHeight( m, z1, 0)
call SetUnitScale( m, scale, scale, scale)
call SetUnitVertexColor(m, red, green, blue, alpha)
set fx=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m , owner, true)
if (speed<=522) then
call SetUnitMoveSpeed( m, speed)
call UnitMoveToUnitAsProjectile(m,arc,target, zoffset)
call DestroyEffect(fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, arc,0,0,target,zoffset)
endif
call ExplodeUnitBJ(m)
set m=null
set fx=null
endfunction
function ProjectileLaunchToUnitExLoc takes player owner, string modelpath, real scale, integer red, integer green, integer blue, integer alpha, real speed, real arc, location loc1, real z1, unit target, real zoffset returns nothing
call ProjectileLaunchToUnitEx( owner, modelpath, scale, red, green, blue, alpha, speed, arc, GetLocationX(loc1),GetLocationY(loc1), z1, target, zoffset)
endfunction
function ProjectileLaunchToUnit takes string modelpath, real speed, real arc,real x1, real y1, real z1, unit target, real zoffset returns nothing
call ProjectileLaunchToUnitEx( Player(15), modelpath, 1, 255,255,255,255,speed,arc,x1,y1,z1,target,zoffset)
endfunction
function ProjectileLaunchToUnitLoc takes string modelpath, real speed, real arc, location loc1, real z1, unit target, real zoffset returns nothing
call ProjectileLaunchToUnitExLoc( Player(15), modelpath, 1, 255,255,255,255, speed, arc, loc1, z1, target,zoffset)
endfunction
//====================================================================================================================================================================
function DamagingProjectileLaunchTarget_Child takes nothing returns nothing
local unit m=udg_currentcaster
local unit target=bj_meleeNearestMine
local effect fx=bj_lastCreatedEffect
local real damage=udg_castervars[4]
local damagetype dmgT=ConvertDamageType(R2I(udg_castervars[6]))
local attacktype attT=ConvertAttackType(R2I(udg_castervars[5]))
local unit hurter=udg_currenthurter
local real speed=udg_castervars[7]
if (speed<=522) then
call SetUnitMoveSpeed( m, speed)
call UnitMoveToUnitAsProjectile(m, bj_meleeNearestMineDist, target, udg_castervars[2])
call DestroyEffect( fx)
else
call UnitMoveToAsProjectileAnySpeed_Effect(m,fx,speed, bj_meleeNearestMineDist,0,0,target,udg_castervars[2])
endif
call DamageUnitByTypes(hurter,target,damage,attT,dmgT)
call ExplodeUnitBJ(m)
set m=null
set hurter=null
set target=null
set fx=null
set dmgT=null
set attT=null
endfunction
function DamagingProjectileLaunchTarget takes unit hurter, string modelpath, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset, real damage, attacktype attT, damagetype dmgT returns unit
local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )
set udg_castervars[7]=speed
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, GetOwningPlayer(hurter), true)
set bj_meleeNearestMineDist = arc
set udg_castervars[2]= zoffset
set bj_meleeNearestMine=target
set udg_castervars[4]=damage
set udg_castervars[5]=CS_H2I(attT)
set udg_castervars[6]=CS_H2I(dmgT)
set udg_currenthurter=hurter
call ExecuteFunc("DamagingProjectileLaunchTarget_Child")
set m=null
return udg_currentcaster
endfunction
function DamagingProjectileLaunchTargetLoc takes unit hurter, string modelpath, real speed, real arc, location loc, real z1, unit target, real zoffset, real damage, attacktype attT, damagetype dmgT returns unit
return DamagingProjectileLaunchTarget(hurter,modelpath,speed,arc,GetLocationX(loc),GetLocationY(loc), z1, target, zoffset, damage, attT, dmgT)
endfunction
function ProjectileLaunchToUnitDamage takes player owner, string modelpath, real speed, real arc, real x1, real y1, real z1, unit target, real zoffset, real damage returns unit
local unit m=CreateCaster( Atan2BJ(GetUnitY(target) - y1, GetUnitX(target) - x1),x1,y1 )
set udg_castervars[7]=speed
call SetUnitFlyHeight( m, z1, 0)
set udg_currentcaster=m
set bj_lastCreatedEffect=AddSpecialEffectTarget( modelpath, m,"origin" )
call SetUnitOwner( m, owner, true)
set bj_meleeNearestMineDist = arc
set udg_castervars[2]= zoffset
set bj_meleeNearestMine=target
set udg_castervars[4]=damage
set udg_castervars[5]=CS_H2I(Caster_DefaultAttackType())
set udg_castervars[6]=CS_H2I(Caster_DefaultDamageType())
set udg_currenthurter=m
call ExecuteFunc("DamagingProjectileLaunchTarget_Child")
set m=null
return udg_currentcaster
endfunction
function ProjectileLaunchToUnitDamageLoc takes player owner, string modelpath, real speed, real arc, location loc1, real z1, unit target, real zoffset, real damage returns unit
return ProjectileLaunchToUnitDamage( owner, modelpath, speed, arc,GetLocationX(loc1),GetLocationY(loc1),z1,target,zoffset,damage)
endfunction
//==============================================================================================================================================================================
// Caster System Class: CollisionMissile
//
function CollisionMissile_Destroy takes unit m returns nothing
local integer k=GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)) )
local effect fx=GetArrayEffect(k,17) //[17=fx]
if (fx!=null) then
call DestroyEffect(fx)
call SetArrayObject(k,17,null) //[17=fx]
set fx=null
endif
//For convenience, always wait for next tic to destroy the thing. But destroy the effect so
//players don't ever notice it.
call SetArrayInt(k,1,2) //[1=state]
endfunction
function CollisionMissile_Create takes string MissileModelPath, real x, real y, real dirangle, real speed, real AngleSpeed, real MaxDist, real height, boolean UseNewCaster, real Collision, code OnImpact returns unit
local timer t
local integer k
local trigger R
local location F
local location L
local unit m
if UseNewCaster then
set m=CreateCaster(dirangle,x,y)
call SetArrayInt(k,19,1) //[19=new]
else
set m=GetACaster()
call SetUnitFacing(m,dirangle)
call SetUnitPosition(m,CS_SafeX(x),CS_SafeY(y))
endif
set k=NewArray(21,true)
if (HaveStoredInteger(CSCache(),"CasterSystem","MOVEMENT_TIMER")) then
set L=GetTableLoc("CasterSystem","MOVEMENT_LIST")
set F=Location(CS_i2r(k),GetLocationX(L))
set F=Location(CS_h2r(m),CS_h2r(F))
call MoveLocation(L,CS_h2r(F),0.)
else
set F=Location(CS_i2r(k),CS_h2r(null))
set F=Location(CS_h2r(m),CS_h2r(F))
set L=Location(CS_h2r(F),0.)
set t=CreateTimer()
call SetTableObject("CasterSystem","MOVEMENT_TIMER",t)
call SetTableObject("CasterSystem","MOVEMENT_LIST",L)
call TimerStart(t,CS_Cycle(),true,function CasterSystemMovementTimer)
endif
set F=null
set L=null
call StoreInteger(udg_cscache,"MOVEMENT_TABLES",GetAttachmentTable(m),k)
call SetArrayInt(k,0,2) //[type=2(collision missile)]
call SetArrayReal(k,4,speed) //[4=speed]
call SetArrayReal(k,6,AngleSpeed) //[6=aspeed]
call SetArrayReal(k,5,dirangle) //[5=F]
call SetArrayReal(k,12,MaxDist) //[13=maxd]
call SetUnitFlyHeight(m,height,0)
set R=CreateTrigger()
call AttachObject(R,"m",m)
call SetArrayReal(k,3,Collision) //[3=collision]
call SetArrayInt(k,1,1) //[1=state]
call SetArrayObject(k,2,R) //[2=T]
call StoreInteger(udg_cscache,"MOVEMENT_TABLES",I2S(CS_H2I(R)),k)
call SetArrayObject(k,17, AddSpecialEffectTarget(MissileModelPath,m,"origin") ) //[17=fx]
call SetArrayObject(k,20,m) //[20=unit m]
call SetArrayObject(k,18,TriggerAddAction(R,OnImpact)) //[18 = triggeraction]
set t=null
set R=null
set udg_currentcaster=m
set m=null
return udg_currentcaster
endfunction
function CollisionMissile_CreateLoc takes string MissileModelPath, location loc, real dirangle, real speed, real AngleSpeed, real MaxDist, real height, boolean UseNewCaster, real Collision, code OnImpact returns unit
return CollisionMissile_Create(MissileModelPath,GetLocationX(loc),GetLocationY(loc),dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact)
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetAngleSpeed takes unit m, real newAspeed returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayReal(k,6,newAspeed ) //[6=aspeed]
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetSpeed takes unit m, real newspeed returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayReal(k,4,newspeed) //[4=speed]
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetTargetPoint takes unit m, real tx, real ty returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayReal(k,8,tx) //[8=tx]
call SetArrayReal(k,9,ty) //[9=ty]
call SetArrayInt(k,7,1) //[7=TType]
endfunction
function CollisionMissile_SetTargetPointLoc takes unit m, location tloc returns nothing
call CollisionMissile_SetTargetPoint(m,GetLocationX(tloc),GetLocationY(tloc))
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetTarget takes unit m, widget Target returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayObject(k,10,Target) //[10=tw]
call SetArrayInt(k,7,2) //[7=TType]
endfunction
//=========================================================================================================================================================
function CollisionMissile_ForgetTarget takes unit m returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayInt(k,7,0) //[7=TType]
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetDirAngle takes unit m, real f returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayReal(k,5,f) //[5=F]
call SetUnitFacing(m,f)
endfunction
//=========================================================================================================================================================
function CollisionMissile_ResetMaxDist takes unit m, real maxdist returns nothing
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayReal(k,12,maxdist) //[12=maxd]
endfunction
//=========================================================================================================================================================
function CollisionMissile_PeriodicFX takes unit m, string fx, real dur returns nothing
// [1 integer state][2 trigger T][3 real collision][4 real speed][5 real F][6 real aspeed][7 integer TType]
// [8 real Tx][9 real Ty][10 widget Tw][11 real F][12 real maxd][13 boolean pfx][14 real pfx_current][15 real pfx_dur][16 pfx_path]
// [17 fx][18 ac][19 boolean new][20 m]
local integer k= GetStoredInteger(CSCache(),"MOVEMENT_TABLES",I2S(CS_H2I(m)))
call SetArrayInt(k,13,1) //[13=pfx]
call SetArrayString(k,16,fx) //[16=pfx_path]
call SetArrayReal(k,15,dur) //[15=pfx_dur]
call SetArrayReal(k,14,0) //[14=pfx_current]
endfunction
//==============================================================================================================================================================================
// Caster System Class: Damager
//
function Damager_SetAbility takes unit Damager, integer abilid, integer l returns nothing
local string k=GetAttachmentTable(Damager)
local integer i
if (GetTableBoolean(k,"CS_IsDamager")) then
set i=GetTableInt(k,"CS_abil")
if (i!=0) then
call UnitRemoveAbility(Damager,i)
endif
call UnitAddAbility(Damager,abilid)
call SetUnitAbilityLevel(Damager,abilid,l)
call SetTableInt(k,"CS_abil",abilid)
endif
endfunction
function Damager_Removage takes unit u, timer t, group g returns nothing
local string k=GetAttachmentTable(u)
call PauseTimer(t)
call CleanAttachedVars(t)
call DestroyTimer(t)
call GroupRemoveUnit(g,u)
call DestroyEffect( GetTableEffect(k,"CS_fx") )
call RecicleCasterAfterCastEx(u,4,GetTableInt(k,"CS_abil"),false)
call ClearTable(k)
endfunction
function Damager_Remove takes unit Damager returns nothing
local string k=GetAttachmentTable(Damager)
local timer dg
local group g
if (GetTableBoolean(k,"CS_IsDamager")) then
set g=GetTableGroup(I2S( GetTableInt(k,"CS_DG") ),"G")
if (IsUnitInGroup(Damager,g)) then
call Damager_Removage(Damager,GetTableTimer(k,"CS_t"),g)
endif
endif
set g=null
set dg=null
endfunction
function Damager_Expire takes nothing returns nothing
local timer t=GetExpiredTimer()
local unit u=GetAttachedUnit(t,"u")
call Damager_Removage(u,t, GetAttachedGroup( GetAttachedObject(u,"CS_DG") ,"G") )
set t=null
set u=null
endfunction
function Damager_SetLifeSpan takes unit Damager, real lifespan returns nothing
local timer t
if (GetAttachedBoolean(Damager,"CS_IsDamager")) then
set t=GetAttachedTimer(Damager,"CS_t")
if (lifespan==0) then
call PauseTimer(t)
else
call TimerStart(t,lifespan,false, function Damager_Expire)
endif
set t=null
endif
endfunction
//============================================================================================================
// Caster System Class: DamagerGroup
//
function DamagerGroup_Destroy takes timer DamagerGroup returns nothing
local string k=I2S(CS_H2I(DamagerGroup))
local gamecache H=CSCache()
local group g=GetTableGroup(k,"G")
local unit p
call DestroyDamageOptions(GetStoredInteger(H,k,"dop") )
call CS_KillTimer( GetTableTimer(k,"lifespan") )
loop
set p=FirstOfGroup(g)
exitwhen (p==null)
call Damager_Removage(p, GetAttachedTimer(p,"CS_t") ,g)
endloop
call DestroyGroup(g)
call FlushStoredMission(H,k)
call PauseTimer(DamagerGroup)
call DestroyTimer(DamagerGroup)
set g=null
set H=null
endfunction
function DamagerGroup_Enum takes nothing returns nothing
call GroupAddUnit(bj_groupAddGroupDest, GetFilterUnit() )
endfunction
function DamagerGroup_DoDamage takes nothing returns nothing
local timer t=GetExpiredTimer()
local string k=I2S(CS_H2I(t))
local gamecache H=CSCache()
local group g=CreateGroup()
local group a=CS_CopyGroup(GetTableGroup(k,"G"))
local group arg=CreateGroup()
local unit p
local unit u=GetTableUnit(k,"hur")
local real x=GetStoredReal(H,k,"are")
local real dm
local integer d
local boolean trees=GetStoredBoolean(H,k,"trees")
local boolexpr bex=Condition(function DamagerGroup_Enum)
set bj_groupAddGroupDest=g
if (FirstOfGroup(a)!=null) then
loop
set p=FirstOfGroup(a)
exitwhen (p==null)
call GroupRemoveUnit(a,p)
call CS_EnumUnitsInAOE(arg,GetUnitX(p),GetUnitY(p),x,bex)
if trees then
call DamageTreesInCircle(GetUnitX(p),GetUnitY(p),x)
endif
endloop
if (FirstOfGroup(g)!=null) then
set d=LoadDamageOptions( GetStoredInteger(H,k,"dop") )
set dm=GetStoredReal(H,k,"dmg")
loop
set p=FirstOfGroup(g)
exitwhen (p==null)
set x=GetDamageFactorByOptions(u,p,d)
if (x!=0) then
call UnitDamageTarget(u,p,dm*x,true,false,null,null,null)
endif
call GroupRemoveUnit(g,p)
endloop
endif
elseif GetStoredBoolean(H,k,"autodestruct") then
call DamagerGroup_Destroy(t)
endif
call DestroyBoolExpr(bex)
call DestroyGroup(g)
call DestroyGroup(arg)
call DestroyGroup(a)
set bex=null
set t=null
set g=null
set arg=null
set a=null
set u=null
set H=null
endfunction
function DamagerGroup_Create takes unit hurter, real damage, real damageperiod, real area, integer DamageOptions returns timer
local gamecache g=CSCache()
local timer t=CreateTimer()
local integer i=CS_H2I(t)
local string k=I2S(i)
if (damageperiod<0.01) then
set damageperiod=0.01
endif
call StoreInteger(g,k,"dop",CreateDamageOptions(DamageOptions))
call StoreInteger(g,k,"hur",CS_H2I(hurter))
call StoreReal(g,k,"dmg",damage)
call StoreReal(g,k,"are",area)
call StoreInteger(g,k,"G",CS_H2I(CreateGroup()))
if IsDamageOptionIncluded(DamageOptions, DamageTrees() ) then
call StoreBoolean(g,k,"trees", true )
endif
call TimerStart(t,damageperiod,true,function DamagerGroup_DoDamage)
set i=CS_H2I(t)
set t=null
return i
return null
endfunction
function DamagerGroup_Update takes timer DamagerGroup, unit hurter, real damage, real damageperiod, real area, integer DamageOptions returns nothing
local integer i
local string k=GetAttachmentTable(DamagerGroup)
local unit p=GetTableUnit(k,"hur")
local player ow
local group g
if (damageperiod<0.01) then
set damageperiod=0.01
endif
if (p!=hurter) then
set g=CS_CopyGroup( GetTableGroup(k,"G") )
call SetTableObject(k,"hur",hurter)
set ow=GetOwningPlayer(hurter)
loop
set p=FirstOfGroup(g)
exitwhen (p==null)
call GroupRemoveUnit(g,p)
call SetUnitOwner(p,ow,true)
endloop
call DestroyGroup(g)
set g=null
set ow=null
endif
call SetTableBoolean(k,"trees",IsDamageOptionIncluded(DamageOptions, DamageTrees() ) )
call SetDamageOptions(GetTableInt(k,"dop") , DamageOptions )
call SetTableReal(k,"dmg",damage)
call SetTableReal(k,"are",area)
call TimerStart(DamagerGroup,damageperiod,true,function DamagerGroup_DoDamage)
set p=null
endfunction
function DamagerGroup_AddDamager takes timer DamagerGroup, string modelpath, real x, real y, real LifeSpan returns unit
local unit c=GetACaster()
local string k=GetAttachmentTable(c)
local string dk=GetAttachmentTable(DamagerGroup)
local timer t=CreateTimer()
call SetUnitPosition(c,x,y)
call SetTableObject(k,"CS_fx",AddSpecialEffectTarget( modelpath,c,"origin") )
call SetTableObject(k,"CS_t", t)
call SetTableObject(k,"CS_DG", DamagerGroup)
call AttachObject(t,"u", c)
if (LifeSpan>0) then
call TimerStart(t,LifeSpan,false, function Damager_Expire)
endif
call SetUnitOwner(c,GetOwningPlayer(GetTableUnit(dk,"hur")),true)
call GroupAddUnit(GetTableGroup(dk,"G"),c)
call SetTableBoolean(k,"CS_IsDamager",true)
set udg_currentcaster=c
set c=null
set t=null
return udg_currentcaster
endfunction
function DamagerGroup_AddDamagerLoc takes timer DamagerGroup, string modelpath, location loc, real LifeSpan returns unit
return DamagerGroup_AddDamager(DamagerGroup,modelpath,GetLocationX(loc),GetLocationY(loc),LifeSpan)
endfunction
function DamagerGroup_OnLifeSpanExpire takes nothing returns nothing
call DamagerGroup_Destroy( GetAttachedTimer(GetExpiredTimer() , "t") )
endfunction
function DamagerGroup_SetLifeSpan takes timer DamagerGroup, real lifespan returns nothing
local string k=GetAttachmentTable(DamagerGroup)
local timer t=GetAttachedTimer(DamagerGroup,"lifespan")
if (HaveSetField(k,"lifespan",bj_GAMECACHE_INTEGER)) then
set t=GetTableTimer(k,"lifespan")
else
set t=CreateTimer()
call SetTableObject(k,"lifespan",t)
set k=GetAttachmentTable(t)
call AttachObject(t,"t",DamagerGroup)
endif
call TimerStart(t,lifespan,false, function DamagerGroup_OnLifeSpanExpire)
set t=null
endfunction
function DamagerGroup_AutoDestruct takes timer DamagerGroup, boolean auto returns nothing
call AttachBoolean(DamagerGroup,"autodestruct",auto)
endfunction
//**************************************************************************************************
//*
//* Caster System Special Events:
//*
//*
//**************************************************************************************************
//==================================================================================================
// Event: OnAbilityLearn
//
function Event_OnLearn1 takes nothing returns nothing
local gamecache g=CSCache()
local integer s=GetLearnedSkill()
local string k=I2S(s)
if HaveStoredString( g, "events_onlearn",k) then
call ExecuteFunc( GetStoredString( g, "events_onlearn",k) )
endif
set g=null
endfunction
function Event_OnLearn2 takes nothing returns nothing
local gamecache g=CSCache()
local integer s=GetLearnedSkill()
local string k=I2S(s)
if HaveStoredString( g, "events_onlearn",k) then
call StoreInteger(g,"events_variables","unit",CS_H2I(GetTriggerUnit()))
call StoreInteger(g,"events_variables","current",s)
call ExecuteFunc( GetStoredString( g, "events_onlearn",k) )
endif
set g=null
endfunction
function InitLearnEvent takes gamecache g, integer i returns nothing
local trigger t=CreateTrigger()
local integer j=0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(j),EVENT_PLAYER_HERO_SKILL, null)
set j=j+1
exitwhen j==bj_MAX_PLAYER_SLOTS
endloop
if (i==1) then
call StoreInteger(g,"Events_ProbablyTemp","learntrig",CS_H2I(t))
call StoreInteger(g,"Events_ProbablyTemp","learntriga",CS_H2I(TriggerAddAction(t, function Event_OnLearn1)))
else
call TriggerAddAction(t, function Event_OnLearn2)
endif
call StoreInteger(g,"eventhandlers","learn",i)
set t=null
endfunction
function OnAbilityLearn takes integer abilid, string funcname returns nothing
local gamecache g=CSCache()
if (not HaveStoredInteger(g,"eventhandlers","learn")) then
call InitLearnEvent(g,1)
endif
call StoreString( g,"events_onlearn", I2S(abilid), funcname)
set g=null
endfunction
//==================================================================================================
// Event: OnAbilityGet
//
function GetAbilityAcquiringUnit takes nothing returns unit
return GetStoredInteger(CSCache(),"events_variables","unit")
return null
endfunction
function GetAcquiredAbilityId takes nothing returns integer
return GetStoredInteger(CSCache(),"events_variables","current")
endfunction
function UnitAddAbility_ConsiderEvent takes unit whichUnit, integer abilid, integer level returns nothing
local gamecache g=CSCache()
local string k=I2S(abilid)
call UnitAddAbility(whichUnit,abilid)
call SetUnitAbilityLevel(whichUnit,abilid,level)
if (HaveStoredString(g,"events_onlearn",k)) then
call StoreInteger(g,"events_variables","units",CS_H2I(whichUnit))
call StoreInteger(g,"events_variables","current",abilid)
call ExecuteFunc(GetStoredString(g,"events_onlearn",k))
endif
set g=null
endfunction
function Event_OnPassive_Browse takes gamecache g, unit u, string k returns nothing
local integer n=GetStoredInteger(g,"events_passives","n")
local integer un=0
local integer i=1
local integer s
loop
exitwhen (i>n)
set s=GetStoredInteger(g,"events_passives",I2S(i))
if (GetUnitAbilityLevel(u,s)>0) then
if (un==0) then
set un=1
call StoreInteger(g,"events_variables","unit",CS_H2I(u))
else
set un=un+1
endif
call StoreInteger(g,"events_unit_passive"+I2S(un),k,s)
call StoreInteger(g,"events_variables","current",s)
call ExecuteFunc(GetStoredString(g,"events_onlearn",I2S(s)))
endif
set i=i+1
endloop
if (un==0) then
set un=-1
endif
call StoreInteger(g,"events_unit_passives",k,un)
endfunction
function Event_OnPassive_Do takes gamecache g, unit u, string k, integer n returns nothing
local integer i=1
local integer s
call StoreInteger(g,"events_variables","unit",CS_H2I(u))
loop
exitwhen (i>n)
set s=GetStoredInteger(g,"events_unit_passive"+I2S(i),k)
if (GetUnitAbilityLevel(u,s)>0) then
call StoreInteger(g,"events_variables","current",s)
call ExecuteFunc(GetStoredString(g,"events_onlearn",I2S(s)))
endif
set i=i+1
endloop
endfunction
function Event_OnPassive_EnterRect takes nothing returns nothing
local gamecache g=CSCache()
local unit u=GetTriggerUnit()
local string k=I2S(GetUnitTypeId(u))
local integer n=GetStoredInteger(g,"events_unit_passives",k)
if (n>0) then
call Event_OnPassive_Do(g,u,k,n)
elseif (n==0) then
call Event_OnPassive_Browse(g,u,k)
endif
set g=null
set u=null
endfunction
function Event_OnPassive_NoCasters takes nothing returns boolean
return (GetUnitTypeId(GetTriggerUnit())!=Caster_UnitId())
endfunction
function Event_OnPassive_InitEnum takes nothing returns nothing
local gamecache g=CSCache()
local trigger t
local integer n=GetStoredInteger(g,"events_passives","n")
local integer i=1
local integer array p
local string array s
local unit u
local group a=CreateGroup()
local boolean saved
call DestroyTimer(GetExpiredTimer())
loop
exitwhen (i>n)
set p[i]=GetStoredInteger(g,"events_passives",I2S(i))
set s[i]=GetStoredString(g,"events_onlearn", I2S(p[i]))
set i=i+1
endloop
call GroupEnumUnitsInRect(a,bj_mapInitialPlayableArea,null)
loop
set u=FirstOfGroup(a)
exitwhen (u==null)
set i=1
set saved=false
loop
exitwhen (i>n)
if (GetUnitAbilityLevel(u,p[i])>0) then
if (not saved) then
set saved=true
call StoreInteger(g,"events_variables","unit",CS_H2I(u))
endif
call StoreInteger(g,"events_variables","current",p[i])
call ExecuteFunc(s[i])
endif
set i=i+1
endloop
call GroupRemoveUnit(a,u)
endloop
set t=CreateTrigger()
call TriggerRegisterEnterRectSimple(t,bj_mapInitialPlayableArea)
call TriggerAddAction(t,function Event_OnPassive_EnterRect)
call TriggerAddCondition(t,Condition(function Event_OnPassive_NoCasters))
call DestroyGroup(a)
set t=null
set a=null
endfunction
function InitPassiveEvent takes gamecache g returns nothing
local trigger t
call TimerStart(CreateTimer(),0,false,function Event_OnPassive_InitEnum)
call StoreInteger(g,"eventhandlers","passives",1)
if (not HaveStoredInteger(g,"eventhandlers","learn")) then
call InitLearnEvent(g,2)
else
set t=GetTableTrigger("Events_ProbablyTemp","learntrig")
call TriggerRemoveAction(t,GetTableTriggerAction("Events_ProbablyTemp","learntriga") )
call FlushStoredMission(g,"Events_ProbablyTemp")
set t=CreateTrigger()
call TriggerAddAction(t, function Event_OnLearn2)
call StoreInteger(g,"eventhandlers","learn",2)
set t=null
endif
endfunction
function OnAbilityGet takes integer abilid, string funcname returns nothing
local gamecache g=CSCache()
local integer n=GetStoredInteger(g,"events_passives","n")+1
if (not HaveStoredInteger(g,"eventhandlers","passives")) then
call InitPassiveEvent(g)
endif
call StoreString( g,"events_onlearn", I2S(abilid), funcname)
call StoreInteger(g,"events_passives","n",n)
call StoreInteger(g,"events_passives",I2S(n),abilid)
set g=null
endfunction
//==================================================================================================
// Event: OnAbilityEffect
//
function Event_OnEffect takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
local gamecache g=CSCache()
if HaveStoredString(g, "events_oneffect",k) then
call ExecuteFunc( GetStoredString(g, "events_oneffect",k))
endif
set g=null
endfunction
function InitEffectEvent takes gamecache g returns nothing
local trigger t=CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t,function Event_OnEffect)
call StoreInteger(g,"eventhandlers","effect",1)
set t=null
endfunction
function OnAbilityEffect takes integer abilid, string funcname returns nothing
local gamecache g=CSCache()
if (not HaveStoredInteger(g,"eventhandlers","effect")) then
call InitEffectEvent(g)
endif
call StoreString(g,"events_oneffect",I2S(abilid),funcname)
set g=null
endfunction
//==================================================================================================
// Event: OnAbilityCast
//
function Event_OnCast takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
local gamecache g=CSCache()
if HaveStoredString(g, "events_oncast",k) then
call ExecuteFunc( GetStoredString(g, "events_oncast",k))
endif
set g=null
endfunction
function InitCastEvent takes gamecache g returns nothing
local trigger t=CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_CAST, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t,function Event_OnCast)
call StoreInteger(g,"eventhandlers","cast",1)
set t=null
endfunction
function OnAbilityPreCast takes integer abilid, string funcname returns nothing
local gamecache g=CSCache()
if (not HaveStoredInteger(g,"eventhandlers","cast")) then
call InitCastEvent(g)
endif
call StoreString(g,"events_oncast",I2S(abilid),funcname)
set g=null
endfunction
//==================================================================================================
// Event: OnAbilityEndCast
//
function Event_OnEndCast takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
local gamecache g=CSCache()
if HaveStoredString(g, "events_onendcast",k) then
call ExecuteFunc( GetStoredString(g, "events_onendcast",k))
endif
set g=null
endfunction
function InitEndCastEvent takes gamecache g returns nothing
local trigger t=CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_ENDCAST, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t,function Event_OnEndCast)
call StoreInteger(g,"eventhandlers","endcast",1)
set t=null
endfunction
function OnAbilityEndCast takes integer abilid, string funcname returns nothing
local gamecache g=CSCache()
if (not HaveStoredInteger(g,"eventhandlers","endcast")) then
call InitEndCastEvent(g)
endif
call StoreString(g,"events_onendcast",I2S(abilid),funcname)
set g=null
endfunction
//==================================================================================================
// Spell Helpers
//
function IsPointWater takes real x, real y returns boolean
return IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) and not(IsTerrainPathable(x,y,PATHING_TYPE_AMPHIBIOUSPATHING))
endfunction
function IsPointWaterLoc takes location loc returns boolean
return IsPointWater(GetLocationX(loc),GetLocationY(loc))
endfunction
//==================================================================================================
function IsUnitSpellImmune takes unit u returns boolean
return IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)
endfunction
function IsUnitImmuneToPhisical takes unit u returns boolean
return (GetDamageFactor(u,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DEMOLITION)==0)
endfunction
function IsUnitInvulnerable takes unit u returns boolean
return (GetDamageFactor(u,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL)==0)
endfunction
//## Utility functions ##
//====================================================================================================
// Mimic an interface error message
// ForPlayer : The player to show the error
// msg : The error
//
function CS_Error takes player ForPlayer, string msg returns nothing
local sound error=CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
if (GetLocalPlayer() == ForPlayer) then
if (msg!="") and (msg!=null) then
call ClearTextMessages()
call DisplayTimedTextToPlayer( ForPlayer, 0.52, -1.00, 2.00, "|cffffcc00"+msg+"|r" )
endif
call StartSound( error )
endif
call KillSoundWhenDone( error)
set error=null
endfunction
//## Safe item hiding system ##
//===============================
// Hides an item, it keeps it safe while leaving other units unable to use it
// (unless an (attached) variable / table field points to it and user does
// something with it) - THIS IS HIGHLY DISCOURAGED
//
// * Don't use it with tomes that increase hero stats
// * Make triggers with item acquire/lose events ignore when a
// Caster is triggering unit.
//
function CS_HideItem takes item i returns integer
local gamecache g=CSCache()
local unit s
local group gr=GetTableGroup("CSItemStorage","gr")
local integer k=NewTableIndex()
local string ks=I2S(k)
if (gr==null) then
set gr=CreateGroup()
call StoreInteger(g,"CSItemStorage","gr",CS_H2I(gr))
endif
set s=FirstOfGroup(gr)
if (s==null) then
set s=AddCaster()
call ShowUnit(s,false)
call UnitAddAbility(s,CS_InventoryId())
call GroupAddUnit(gr,s)
endif
call UnitAddItem(s,i)
call StoreInteger(g,ks,"s",CS_H2I(s))
call StoreInteger(g,ks,"i",CS_H2I(i))
if(UnitInventorySize(s)==UnitInventoryCount(s)) then
call GroupRemoveUnit(gr,s)
endif
set s=null
set g=null
set gr=null
return (k)
endfunction
function CS_FromIntegerToItem takes integer i returns item
return i
return null
endfunction
//===============================
// Restores an item
//
function CS_RestoreItem takes integer hiddenindex, real x, real y returns item
local gamecache g=CSCache()
local group gr=GetTableGroup("CSItemStorage","gr")
local string k=I2S(hiddenindex)
local unit s=GetTableUnit(k,"s")
local integer r=GetStoredInteger(g,k,"i")
local item i=CS_FromIntegerToItem(r)
local integer c
call UnitRemoveItem(s,i)
set c=UnitInventoryCount(s)
if (c==0) then
call UnitRemoveAbility(s,CS_InventoryId())
call GroupRemoveUnit(gr,s)
call ExplodeUnitBJ(s)
else
call GroupAddUnit(gr,s)
endif
call SetItemPosition(i,x,y)
call DestroyTable(k)
set i=null
set s=null
set g=null
return r
return null
endfunction
function CS_RestoreItemLoc takes integer hiddenindex, location loc returns item
return CS_RestoreItem(hiddenindex,GetLocationX(loc),GetLocationY(loc))
endfunction
//=============================================================================================================
// Obsolette functions: (Left for compatibility)
//
constant function WaterDetectorId takes nothing returns integer
return 'Asb2' //Left for compat
endfunction
function SpellEffectModelPath takes integer abilityid, effecttype t returns string
return GetAbilityEffectById(abilityid,t, 0)
endfunction
//##End##
//## Start BonusMod InvX version - Created by weaddar, some modifications by Vexorian for InvX ##
constant function IxLimit takes nothing returns integer
return 11
endfunction
function Ix takes integer x, integer y returns integer
return(x*IxLimit()+y)
endfunction
constant function BonusHPManaFactor takes nothing returns integer
return 10
endfunction
function SetupBonusModAbilities takes nothing returns nothing
//Damage
set udg_BnsBit[Ix(0,0)]= 'A03K' //+0001
set udg_BnsBit[Ix(0,1)]= 'A03L' //+0002
set udg_BnsBit[Ix(0,2)]= 'A03M' //+0004
set udg_BnsBit[Ix(0,3)]= 'A03N' //+0008
set udg_BnsBit[Ix(0,4)]= 'A03O' //+0016
set udg_BnsBit[Ix(0,5)]= 'A03P' //+0032
set udg_BnsBit[Ix(0,6)]= 'A03Q' //+0064
set udg_BnsBit[Ix(0,7)]= 'A03R' //+0128
set udg_BnsBit[Ix(0,8)]= 'A03S' //+0256
set udg_BnsBit[Ix(0,9)]= 'A03T' //+0512
set udg_BnsBit[Ix(0,10)]='A04F' //-1024
//armor
set udg_BnsBit[Ix(1,0)]= 'A03A' //+0001
set udg_BnsBit[Ix(1,1)]= 'A03B' //+0002
set udg_BnsBit[Ix(1,2)]= 'A03C' //+0004
set udg_BnsBit[Ix(1,3)]= 'A03D' //+0008
set udg_BnsBit[Ix(1,4)]= 'A03E' //+0016
set udg_BnsBit[Ix(1,5)]= 'A03F' //+0032
set udg_BnsBit[Ix(1,6)]= 'A03G' //+0064
set udg_BnsBit[Ix(1,7)]= 'A03H' //+0128
set udg_BnsBit[Ix(1,8)]= 'A03I' //+0256
set udg_BnsBit[Ix(1,9)]= 'A03J' //+0512
set udg_BnsBit[Ix(1,10)]='A04E' //-1024
//HP
set udg_BnsBit[Ix(2,0)]= 'A03U' //+00010
set udg_BnsBit[Ix(2,1)]= 'A03V' //+00020
set udg_BnsBit[Ix(2,2)]= 'A03W' //+00040
set udg_BnsBit[Ix(2,3)]= 'A03X' //+00080
set udg_BnsBit[Ix(2,4)]= 'A03Y' //+00160
set udg_BnsBit[Ix(2,5)]= 'A03Z' //+00320
set udg_BnsBit[Ix(2,6)]= 'A040' //+00640
set udg_BnsBit[Ix(2,7)]= 'A041' //+01280
set udg_BnsBit[Ix(2,8)]= 'A042' //+02560
set udg_BnsBit[Ix(2,9)]= 'A043' //+05120
set udg_BnsBit[Ix(2,10)]='A04G' //-10240
//Mana
set udg_BnsBit[Ix(3,0)]= 'A044' //+00010
set udg_BnsBit[Ix(3,1)]= 'A045' //+00020
set udg_BnsBit[Ix(3,2)]= 'A046' //+00040
set udg_BnsBit[Ix(3,3)]= 'A047' //+00080
set udg_BnsBit[Ix(3,4)]= 'A048' //+00160
set udg_BnsBit[Ix(3,5)]= 'A049' //+00320
set udg_BnsBit[Ix(3,6)]= 'A04A' //+00640
set udg_BnsBit[Ix(3,7)]= 'A04B' //+01280
set udg_BnsBit[Ix(3,8)]= 'A04C' //+02560
set udg_BnsBit[Ix(3,9)]= 'A04D' //+05120
set udg_BnsBit[Ix(3,10)]='A04H' //-10240
endfunction
function BONUSMAX takes nothing returns integer
return ( R2I(Pow( 2, Ix(1,0)-1))-1)
endfunction
function bonusmin takes nothing returns integer
return - R2I( Pow( 2, Ix(1,0)-1) )
endfunction
function UnitGetBonus takes unit who,integer t returns integer
return GetAttachedInt(who,"BonusMod"+I2S(t))
endfunction
function UnitSetBonus takes unit who, integer t, integer amount returns boolean
local integer x
local integer i=Ix(1,-1)
local integer bit=R2I(Pow(2,i))
local boolean bol=false
local boolean man=false
if who==null or t<0 or t>3 then
return false
elseif t>1 then
set amount=amount/BonusHPManaFactor()
call AttachInt(who,"BonusMod"+I2S(t),amount*BonusHPManaFactor())
else
call AttachInt(who,"BonusMod"+I2S(t),amount)
endif
if (t==3) and (GetUnitState(who,UNIT_STATE_MAX_MANA)<=0) then
set man=true
endif
call UnitRemoveAbility( who, udg_BnsBit[Ix(t,Ix(1,-1))] )
if amount<0 then
set bol=true
set amount=bit+amount
endif
loop
set bit=bit/2
set i=i-1
exitwhen i<0
if amount >= bit then
set x=udg_BnsBit[Ix(t,i)]
call UnitAddAbility( who, x )
call UnitMakeAbilityPermanent(who, true, x )
set amount=amount-bit
else
call UnitRemoveAbility( who, udg_BnsBit[Ix(t,i)] )
endif
endloop
if bol then
set x=udg_BnsBit[Ix(t,Ix(1,-1))]
call UnitAddAbility( who, x )
call UnitMakeAbilityPermanent(who, true, x )
endif
if man and (GetUnitState(who,UNIT_STATE_MAX_MANA)>0) then
call SetUnitState(who,UNIT_STATE_MANA,0)
endif
return amount == 0
endfunction
function UnitClearBonus takes unit who,integer t returns nothing
call UnitSetBonus(who,t,0)
endfunction
function UnitAddBonus takes unit who, integer t, integer amount returns boolean
local integer x
local boolean b
local real l
local string s
local real min
local real mod
if amount==0 then
return true
endif
if t>1 then
set amount= (amount/BonusHPManaFactor())*BonusHPManaFactor()
endif
if t>=2 then
if t==2 then
set l=GetWidgetLife( who )
set mod=ModuloReal(l,BonusHPManaFactor())
set s="BonusModLeftHP"
if mod>=1 then
set min=0
else
set min=BonusHPManaFactor()
endif
else
set l=GetUnitState( who, UNIT_STATE_MAX_MANA )
set mod=ModuloReal(l,BonusHPManaFactor())
set s="BonusModLeftMana"
set min=0
endif
set amount=amount+GetAttachedInt(who,s)
if (amount < 0) and ( l + amount < 1 ) then
set x=R2I(min+mod-l)
set b= UnitSetBonus(who,t,UnitGetBonus(who,t)+x)
call AttachInt(who,s, (amount-x) )
else
call AttachInt(who,s,0)
set b= UnitSetBonus(who,t,UnitGetBonus(who,t)+amount)
endif
return b
endif
return UnitSetBonus(who,t,UnitGetBonus(who,t)+amount)
endfunction
function InitBonusMod takes nothing returns nothing
local unit dummy=GetACaster()
local integer i=0
call SetupBonusModAbilities()
loop
if i>1 then
call UnitSetBonus( dummy, i,-BonusHPManaFactor())
else
call UnitSetBonus( dummy, i,-1)
endif
call UnitSetBonus( dummy, i,0)
set i=i+1
exitwhen (i==4)
endloop
call RecicleCaster(dummy)
set dummy=null
endfunction
// ## End BonusMod ##
Name | Type | is_array | initial_value |
AAAInventory | gamecache | No | |
AAAInventoryGroup | group | No | |
BnsBit | abilcode | Yes | |
casters | group | No | |
castervars | real | Yes | |
csarray1 | integer | Yes | |
csarray2 | integer | Yes | |
cscache | gamecache | No | |
csfreeindexes | location | Yes | |
currentabi | integer | No | |
currentcaster | unit | No | |
currenthurter | unit | No | |
delayhack | real | No | |
sourcehack | location | No | |
TESTUNIT | unit | No |
Read Me
¯¯¯¯¯¯¯
AAAInventory System version 1.0
Table Of Contents:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
1. About.
2. Implementation.
3. Usage
4. Final Notes
5. Contact Info
1. About
¯¯¯¯¯¯¯¯
What is this?
This is an inventory system I created quite some time ago for my map Azeroth's Arcane Arena.
I am releasing this, because several guys have requested it.
This system is inspired by Vexorian's InvX and weaaddar' Drag & Drop system.
It has the features I needed for my map, nothing more, nothing less.
Therefore I suggest you to check out one of the two systems mentioned above instead, if you want
a more advanced, and better inventory system.
This system is a lot simpler than those two systems, and that might be good in some situations.
It is not the best system out there, so unless this is what you want, check one of the other two
systems I mentioned. They are different, but generally a lot better.
But well, if this is what you need, then it is good, and I think this is a bit easier to use than the
other two systems, since it is less advanced.
2. Implementation
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
NOTE: Always make a back up of your map before implementing anything.
This system requires Vexorian's Caster System - Find it with a large read me at
http://www.wc3campaigns.net/vexorian
It mostly just uses the CSCache system, but it also uses the PreloadAbility function - Therefore you
will need the whole Caster System. If you know JASS, I am sure that you can just use the CSCache
system and create a PreloadAbility function yourself - Just created a unit, add the ability and
remove the unit from the game.
The Caster System is not the only thing this system requires.
It also requires BonusMod, a system made by weaaddar, that uses abilities to modify the max life,
max mana, damage and armor of units.
When I coded this system, I used the InvX version of BonusMod - A version optimized to use the Caster
System, modified for InvX. Vexorian made these modifications to weaaddar's system, for his inventory
system InvX.
That version of BonusMod is used in this map (with permission), get it with a read me
and implementation instructions from the InvX map at:
http://www.wc3campaigns.net/vexorian/invx/
While you are at InvX, reconsider what system to use, both InvX and weaaddar's Drag and Drop systems
are better.
After implementing BonusMod, it is time to copy some stuff from this map to your map.
First copy the "Inventory Spell" ability - It is just a dummy ability used by the items, so they are
clickable.
Then copy the 9 custom items to your map (Accessory, Armor, Backpack, Cancel, Equipment Menu, Head,
Shield, Switch Page & Weapon) and make sure that the ability on the Backpack, Cancel, Equipment Menu
& Switch Page items is the Inventory Spell ability.
Now copy the variables used by the inventory system to your map (look at the "Required Variables"
trigger for instructions about doing that).
When that is done, copy the "AAAInventory" trigger to your map - Yeah, you guessed right, that is the
system itself.
Now it is time to change the rawcodes of the items in the top of the "AAAInventory" trigger.
A rawcode is a unique id that every object has. To find it, go to the object editor and press CTRL+D.
Now the names of all objects should change - The first four letters in the name is the rawcode.
Rawcodes are case sensitive, and must be put between single quotes (Example: 'I00A').
Replace the rawcodes in the trigger with the ones from your map.
In my map, the amount of items that can be in a backpack is 12 - You can change this, if you want.
Just change the integer returned by the BackPack size constant function in the configuration section.
The integer returned by that function MUST be a multiple of 4, as that is the amount of items that
can be on a page. If it is not, then the system won't work correctly.
Now take a look at the InventorySafeX/Y configuration functions.
When a item is not in the unit's actual inventory, but the unit owns the item (the item is in another
menu in the inventory system than the currently open one), the item is dropped on the grund and
hidden. It is, however, possible for units to pick the items up up even though they are hidden, so
if you have some trigger that, for example, orders computer units to pick up items in range, they
will be able to pick up the hidden items, and that will cause problems.
Therefore specify some coordinates of a place in your map where units are not able to go and pick the
items up, and the items will be moved to that place when dropped. To know what the coordinates of a
point is, just hover your mouse over the point in the World Editor, and look in the down-left corner
to see the coordinates.
3. Usage
¯¯¯¯¯¯¯¯
The trigger that contains the system will automatically initialize the system itself.
You will, however, need to initialize BonusMod manually, else the system will not work.
To do that, you will need a custom script (JASS) call like this:
call InitBonusMod()
It must be called at map initilization, before any unit uses the system.
Now it is time to set up the items.
Find the "SetupItemBonuses" function in the "AAAInventory" trigger - That function is automatically
executed when the system initializes itself, so all the item setup lines must be put in there.
Use the following function to set up an item type's bonuses:
___________________________________________________________________________________________________________________________________________________________________________________________________________________________
function SetItemBonuses takes integer itemId, integer dmg, integer arm, integer hp, integer mp, integer str, integer agi, integer int, integer abil, string equipSlot, string equipFunc, string unequipFunc returns nothing
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
integer itemId - This is the rawcode of the item type.
integer dmg - The damage bonus added by the item type.
integer arm - The armor bonus added by the item type.
integer hp - The HP bonus added by the item type.
integer mp - The MP bonus added by the item type.
integer str - The strength bonus added by the item type.
integer agi - The agility bonus added by the item type.
integer int - The intelligence bonus added by the item type.
integer abil - The rawcode of an ability added to the hero when he equips the item*. If the ability is added by multiple items equipped by the hero, it will first be removed when all those items are drop.
string equipSlot - The slot that the item is equipped to**.
string equipFunc - A function executed using the ExecuteFunc native when the item is equipped***. Use an empty string if you don't want any function to be executed ("").
string unequipFunc - A function executed using the ExecuteFunc native when the item is unequipped***. Use an empty string if you don't want any function to be executed ("").
* If you want to add a passive ability that takes up a slot in the command card, but don't want it to
show up there, create a new ability based on the Spell Book ability. Change it's orderstring to
something random (just so it won't collide with other spellbooks).
Add your ability to the spell book, and at map initialization use the following code:
call SetPlayerAbilityAvailable(player, abilCode, false)
Where player is the player (it must be done for all 12 players) and abilCode is the rawcode of the
ability. Then just use the rawcode of the spellbook ability, and the ability will be added, but
hidden in the command card.
** Must be either "Head", "Armor", "Weapon", "Shield" or "Accessory" (case sensitive.
You can change the names of the items, but in the code you will have to use the original names,
else it will not work.
You can use the table in the Trigger Comment field of the "AAAInventory" trigger to see where each
slot is placed.
*** Use GetOrderedUnit() to refer to the hero equipping/unequipping the item.
Make sure that you removed all original bonus abilities from the item type in the object editor, else
things won't work correctly.
An example of how to set up an item:
call SetItemBonuses('ratf', 15, 0, 0, 0, 0, 0, 0, 0, "Weapon", "", "") // Claws of Attack +15
Sets up the Claws of Attack +15 to be an item that can be equipped to the Weapon slot. The only bonus added by that item is +15 damage.
There are a couple of examples in the "SetupItemBonuses" function in the "AAAInventory" trigger, you
can look at them if you are not sure about how to do this yet. Remember to remove them, unless you
want items with exactly the same bonuses in your map.
Please notice that items with charges must be in the "Charged" item category in the Object Editor,
else they won't work correctly with this system.
Now it is time to give a unit the extended inventory. You can do this with as many units as you want.
_____________________________________________________________________________________________________
function CreateExtendedInventory takes unit u returns nothing
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
The above function is all that is required to give a unit extended inventory.
Call it like this:
call CreateExtendedInventory(unit)
Where 'unit' of course is the unit you want to create the extended inventory for.
Please notice that this is supposed to be called as soon as the unit is created, and it will REMOVE
all items already in the unit's inventory.
If you want to remove a Hero from the game, use the following function to get rid of the extended
inventory:
_____________________________________________________________________________________________________
function DestroyExtendedInventory takes unit u returns nothing
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
It is not required, but it is a good idea, as it will remove the data stored in the gamecache, and
the items used by the inventory system. It will REMOVE all items the hero owns from the game, no
matter if they are in the backpack, the equipment menu, or the quick menu.
Call it like this:
call DestroyExtendedInventory(unit)
Where 'unit' still is the unit you want to remove the extended inventory from.
This system uses Set/GetItemUserData, so if you use that yourself in your triggers, you might screw
up the system. Therefore do NOT use SetUnitUserData (Set Custom Value Of Item in GUI), or the system
might not work correctly.
Now you should know how to use the system.
4. Final Notes
¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* There might be some of the functions that are created for internal use and can be found in the
"AAAInventory" system trigger that might be useful for you, GetItemSlot() for example.
You will have to find out how to uset them yourself though.
* This is not the best inventory system out there, so if you want something more advanced, check out
Vexorian's and weaaddar's systems.
* This system might contain bugs, but I all the bugs I've found when using it in my map have been
fixed, so hopefully there are no bugs left.
* I use some custom icons for this system, they are just modified Blizzard icons, but they make the
system make more sense. You can use them if you want, find them in the import manager.
* This is not _exactly_ the same system as in my map, it has been updated a bit since the latest
release of the map, and some bugs have been fixed.
* Remember to GIVE CREDIT if you use this system.
5. Contact Info
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Contact me by:
E-Mail: [email protected]
Or send me (Blade.dk) a pm at http://www.wc3campaigns.net or http://www.wc3jass.com.
Sites:
http://www.wc3campaigns.net - The number one Warcraft 3 Modding site, with everything you might want
from resources, to tutorials, to forums, to real-time chat where you
can get help with your modding problems.
http://aaa.wc3jass.com - My map, Azeroth's Arcane Arena, that this system was originally created
for. Check it out!
http://www.wc3jass.com - The Jass Vault, the largest Jass site on the internet. Contains forums,
a grand library of Jass functions and more.
Resources:
http://www.wc3campaigns.net/resources.php?f=613&u=66470 - More resources made by me, Blade.dk.
http://www.wc3campaigns.net/forumdisplay.php?f=658 - Vexorian's Caster System.
http://www.wc3campaigns.net/vexorian/invx/ - Vexorian's InvX inventory system.
http://www.wc3campaigns.net/showthread.php?t=84088 - weaaddar's Drag and Drop Systems.
Have fun, and thanks for downloading this system.
- Blade.dk
//***************************************************************************
//* *
//* Azeroth' Arcane Arena Inventory System *
//* *
//* By Blade.dk - [email protected] *
//* *
//* http://aaa.wc3jass.com - http://www.wc3campaigns.net *
//* *
//***************************************************************************
//===========================================================================
// Configuration functions
constant function Cancel_ItemID takes nothing returns integer
return 'I00B' // Rawcode of the Cancel item.
endfunction
constant function BackpackMenu_ItemID takes nothing returns integer
return 'I00C' // Rawcode of the Backpack item.
endfunction
constant function SwitchPage_ItemID takes nothing returns integer
return 'I00D' // Rawcode of the Switch Page item.
endfunction
constant function EquipmentMenu_ItemID takes nothing returns integer
return 'I00E' // Rawcode of the Equipment Menu item.
endfunction
constant function HeadFiller_ItemID takes nothing returns integer
return 'I00F' // Rawcode of the Head item.
endfunction
constant function ArmorFiller_ItemID takes nothing returns integer
return 'I00G' // Rawcode of the Armor item.
endfunction
constant function WeaponFiller_ItemID takes nothing returns integer
return 'I00H' // Rawcode of the Weapon item.
endfunction
constant function ShieldFiller_ItemID takes nothing returns integer
return 'I00I' // Rawcode of the Shield item.
endfunction
constant function AccessoryFiller_ItemID takes nothing returns integer
return 'I00J' // Rawcode of the Accessory item.
endfunction
constant function BackpackSize takes nothing returns integer
return 16 // The number of items that can be in a Hero's Backpack. MUST be a multiple of 4.
endfunction
constant function InventorySafeX takes nothing returns real
return -2040.00 // The X coordinate of a safe place to place items, so computer units won't be able to pick the up.
endfunction
constant function InventorySafeY takes nothing returns real
return 2040.00 // The Y coordinate of a safe place to place items, so computer units won't be able to pick the up.
endfunction
//===========================================================================
// Private functions - Do not modify them unless you know what you are doing!
function InventoryCache takes nothing returns gamecache
if udg_AAAInventory == null then
call FlushGameCache(InitGameCache("AAAInv.w3v"))
set udg_AAAInventory = InitGameCache("AAAInv.w3v")
endif
return udg_AAAInventory
endfunction
function SetItemBonuses takes integer itemId, integer dmg, integer arm, integer hp, integer mp, integer str, integer agi, integer int, integer abil, string equipSlot, string equipFunc, string unequipFunc returns nothing
local gamecache g = InventoryCache()
local string s = I2S(itemId)
if equipSlot == "Head" or equipSlot == "Armor" or equipSlot == "Weapon" or equipSlot == "Shield" or equipSlot == "Accessory" then
call StoreString(g, s, "equipmentslot", equipSlot)
if dmg > 0 then
call StoreInteger(g, s, "damage", dmg)
endif
if arm > 0 then
call StoreInteger(g, s, "armor", arm)
endif
if hp > 0 then
call StoreInteger(g, s, "hitpoints", hp)
endif
if mp > 0 then
call StoreInteger(g, s, "manapoints", mp)
endif
if str > 0 then
call StoreInteger(g, s, "strength", str)
endif
if agi > 0 then
call StoreInteger(g, s, "agility", agi)
endif
if int > 0 then
call StoreInteger(g, s, "intelligence", int)
endif
if abil > 0 then
call StoreInteger(g, s, "ability", PreloadAbility(abil))
endif
if equipFunc != "" and equipFunc != null then
call StoreString(g, s, "OnEquip", equipFunc)
endif
if unequipFunc != "" and unequipFunc != null then
call StoreString(g, s, "OnDrop", unequipFunc)
endif
endif
set g = null
endfunction
//===========================================================================
// Put the SetItemBonuses calls that sets up your items in this function, that is executed by the
// system at map init.
function SetupItemBonuses takes nothing returns nothing
call SetItemBonuses('ratf', 15, 0, 0, 0, 0, 0, 0, 0, "Weapon", "", "")
// Set up the Claws of Attack +15 to be a Weapon that adds 15 bonus damage.
call SetItemBonuses('mnsf', 0, 0, 0, 200, 0, 0, 0, 'A000', "Weapon", "", "")
// Set up the Mindstaff item to be a Weapon that adds 200 mana and the 'A000' ability (See the "Extra" trigger for more info).
call SetItemBonuses('blba', 0, 7, 0, 0, 0, 0, 0, 'A001', "Armor", "", "")
// Set up the Bladebane Armor item to be an Armor that adds 7 armor and the 'A001' ability (See the "Extra" trigger for more info).
call SetItemBonuses('rin1', 0, 0, 0, 0, 0, 0, 3, 0, "Armor", "", "")
// Set up the Mantle of Intelligence item to be an Armor that adds 3 intelligence.
call SetItemBonuses('bfhr', 0, 0, 0, 0, 0, 10, 0, 0, "Accessory", "", "")
// Set up the Bloodfeather's Heart item to be an Accessory that adds 10 agility.
call SetItemBonuses('lnrn', 0, 0, 0, 0, 0, 1, 0, 0, "Accessory", "", "")
// Set up the Lion's Ring item to be an Accessory that adds 1 agility.
call SetItemBonuses('ckng', 0, 0, 0, 0, 5, 5, 5, 0, "Head", "", "")
// Set up the Crown of Kings +5 item to be a Head equippable item that adds 5 to all hero stats.
call SetItemBonuses('rwiz', 0, 0, 0, 0, 0, 0, 0, 'AIrm', "Head", "", "")
// Set up the Sobi Mask item to be a Head equippable item that adds the 'AIrm' ability.
call SetItemBonuses('shen', 0, 2, 50, 0, 0, 0, 0, 0, "Shield", "", "")
// Set up the Enchanted Shield item to be a Shield that adds 2 armor and 50 HP.
call SetItemBonuses('shhn', 0, 8, 0, 0, 0, 0, 0, 'A002', "Shield", "", "")
// Set up the Shield of Honor item to be a Shield that adds 8 armor and the 'A002' ability (See the "Extra" trigger for more info).
call SetItemBonuses('wtlg', 0, 0, 0, 0, 0, 0, 0, 0, "Accessory", "WirtsLegEquip", "WirtsLegUnequip")
// Set up the Wirt's Leg item to be an Accessory that adds no bonuses, but executes the "WirtsLegEquip" function when equipped, and the "WirtsLegUnequip" function when unequipped (see the "Extra" trigger for more info).
endfunction
//===========================================================================
// Private functions - Do not modify them unless you know what you are doing!
function BackpackHasEmptySlots takes string s returns boolean
local integer a = 1
loop
exitwhen a > BackpackSize()
if GetTableItem(s, "BackpackItem"+I2S(a)) == null then
return true
endif
set a = a+1
endloop
return false
endfunction
function QuickMenuHasEmptySlots takes string s returns boolean
return GetTableItem(s, "QuickMenuItem1") == null or GetTableItem(s, "QuickMenuItem2") == null or GetTableItem(s, "QuickMenuItem3") == null or GetTableItem(s, "QuickMenuItem4") == null
endfunction
function IsItemFiller takes item i returns boolean
local integer id = GetItemTypeId(i)
return id == HeadFiller_ItemID() or id == ArmorFiller_ItemID() or id == WeaponFiller_ItemID() or id == ShieldFiller_ItemID() or id == AccessoryFiller_ItemID()
endfunction
function BackpackContainsItem takes string s, item i returns boolean
local integer a = 1
loop
exitwhen a > BackpackSize()
if GetTableItem(s, "BackpackItem"+I2S(a)) == i then
return true
endif
set a = a+1
endloop
return false
endfunction
function QuickMenuContainsItem takes string s, item i returns boolean
return GetTableItem(s, "QuickMenuItem1") == i or GetTableItem(s, "QuickMenuItem2") == i or GetTableItem(s, "QuickMenuItem3") == i or GetTableItem(s, "QuickMenuItem4") == i
endfunction
function IsEquipmentSlotValid takes string es returns boolean
return es == "Head" or es == "Armor" or es == "Weapon" or es == "Shield" or es == "Accessory"
endfunction
function GetItemEquipmentSlot takes item i returns string
return GetStoredString(InventoryCache(), I2S(GetItemTypeId(i)), "equipmentslot")
endfunction
function GetItemSlot takes unit u, item i returns integer
local integer a = 0
loop
exitwhen a > 5
if UnitItemInSlot(u, a) == i then
return a
endif
set a = a + 1
endloop
return -1
endfunction
function SlotToFillerName takes integer s returns string
if s == 0 then
return "Head"
elseif s == 1 then
return "Armor"
elseif s == 2 then
return "Weapon"
elseif s == 3 then
return "Shield"
elseif s == 4 then
return "Accessory"
else
return "Cancel"
endif
endfunction
function FillerNameToSlot takes string es returns integer
if es == "Head" then
return 0
elseif es == "Armor" then
return 1
elseif es == "Weapon" then
return 2
elseif es == "Shield" then
return 3
elseif es == "Accessory" then
return 4
endif
return 5
endfunction
function InventoryRemoveItem takes unit u, item i returns nothing
call SetItemUserData(i, 1)
call UnitRemoveItem(u, i)
call SetItemPosition(i, InventorySafeX(), InventorySafeY())
call SetItemVisible(i, false)
endfunction
function InventoryAddItem takes unit u, item i returns nothing
call SetItemUserData(i, 0)
call SetItemVisible(i, true)
call UnitAddItem(u, i)
endfunction
function CreateExtendedInventory takes unit u returns nothing
local item i
local string s = NewTable()
local integer a = 0
loop
exitwhen a > 5
call RemoveItem(UnitItemInSlot(u, a))
set a = a + 1
endloop
call GroupAddUnit(udg_AAAInventoryGroup, u)
call AttachString(u, "InventoryTable", s)
call SetTableInt(s, "CurrentMenu", 0)
call SetTableInt(s, "CurrentBackpackPage", 1)
call UnitAddItemToSlotById(u, EquipmentMenu_ItemID(), 4)
set i = UnitItemInSlot(u, 4)
call SetTableObject(s, "EquipmentMenu", i)
call UnitAddItemToSlotById(u, BackpackMenu_ItemID(), 5)
set i = UnitItemInSlot(u, 5)
call SetTableObject(s, "BackpackMenu", i)
set i = CreateItem(Cancel_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "Cancel", i)
set i = CreateItem(SwitchPage_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "SwitchPage", i)
call SetItemCharges(i, 1)
set i = CreateItem(HeadFiller_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "HeadFiller", i)
call SetTableObject(s, "HeadItem", i)
set i = CreateItem(ArmorFiller_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "ArmorFiller", i)
call SetTableObject(s, "ArmorItem", i)
set i = CreateItem(WeaponFiller_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "WeaponFiller", i)
call SetTableObject(s, "WeaponItem", i)
set i = CreateItem(ShieldFiller_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "ShieldFiller", i)
call SetTableObject(s, "ShieldItem", i)
set i = CreateItem(AccessoryFiller_ItemID(), 0, 0)
call SetItemVisible(i, false)
call SetTableObject(s, "AccessoryFiller", i)
call SetTableObject(s, "AccessoryItem", i)
set i = null
endfunction
function DestroyExtendedInventory takes unit u returns nothing
local string s = GetAttachedString(u, "InventoryTable")
local item i
local item t
local integer a = 1
if s == "" then
set i = null
set t = null
return
endif
loop
exitwhen a > BackpackSize()
call RemoveItem(GetTableItem(s, "BackpackItem"+I2S(a)))
set a = a + 1
endloop
set a = 1
loop
exitwhen a > 4
call RemoveItem(GetTableItem(s, "QuickPage"+I2S(a)))
set a = a + 1
endloop
call RemoveItem(GetTableItem(s, "EquipmentMenu"))
call RemoveItem(GetTableItem(s, "BackpackMenu"))
call RemoveItem(GetTableItem(s, "Cancel"))
call RemoveItem(GetTableItem(s, "SwitchPage"))
set a = 0
loop
exitwhen a > 4
set i = GetTableItem(s, SlotToFillerName(a)+"Item")
set t = GetTableItem(s, SlotToFillerName(a)+"Filler")
if i != t then
call RemoveItem(i)
endif
call RemoveItem(t)
set a = a + 1
endloop
call DestroyTable(s)
call GroupRemoveUnit(udg_AAAInventoryGroup, u)
call AttachString(u, "InventoryTable", "")
set i = null
set t = null
endfunction
function InventoryError takes unit u, string e returns nothing
call CS_Error(GetOwningPlayer(u), e)
call PauseUnit(u, true)
call IssueImmediateOrder(u, "stop")
call PauseUnit(u, false)
endfunction
function CompressBackpack takes string s returns nothing
local integer a = 1
local item array t
local integer b = 1
local integer m = 0
local integer e = 1
local string l
loop
exitwhen a > BackpackSize()
set l = "BackpackItem"+I2S(a)
set t[a] = GetTableItem(s, l)
call SetTableObject(s, l, null)
set a = a + 1
endloop
set a = 1
loop
exitwhen a > BackpackSize()
set b = e
loop
exitwhen b > BackpackSize()
if t[b] != null then
call SetTableObject(s, "BackpackItem"+I2S(a), t[b])
set e = b+1
set m = m + 1
set b = BackpackSize()+1
endif
set b = b + 1
endloop
set a = a + 1
endloop
set a = 1
loop
exitwhen a > BackpackSize()
set t[a] = null
set a = a + 1
endloop
call SetTableInt(s, "BackpackItemsCount", m)
endfunction
function AddItemToBackpack takes unit u, string s, item i returns nothing
local integer a
call CompressBackpack(s)
set a = GetTableInt(s, "BackpackItemsCount")+1
call SetTableObject(s, "BackpackItem"+I2S(a), i)
call InventoryRemoveItem(u, i)
call SetItemCharges(GetTableItem(s, "BackpackMenu"), a)
call SetTableInt(s, "BackpackItemsCount", a)
endfunction
function AddItemToQuickMenu takes unit u, string s, item i, boolean f returns nothing
local integer a = 1
local string c
local item t
local string m
loop
exitwhen a > 4
set c = "QuickMenuItem"+I2S(a)
if GetTableItem(s, c) == null then
call SetTableObject(s, c, i)
call InventoryRemoveItem(u, i)
set a = 4
endif
set a = a + 1
endloop
if f then
call CompressBackpack(s)
endif
set t = null
endfunction
function InventorySwapMenu takes unit c, string s, integer o, integer m, integer op, integer np returns nothing
local integer a = 1
local integer b = 0
local item i
if o == 0 then
loop
exitwhen a > 6
set i = UnitItemInSlot(c, a-1)
if a < 5 then
call SetTableObject(s, "QuickMenuItem"+I2S(a), i)
endif
call InventoryRemoveItem(c, i)
set a = a + 1
endloop
elseif o == 1 then
set a = 0
loop
exitwhen a > 4
set i = UnitItemInSlot(c, a)
call SetTableObject(s, SlotToFillerName(a)+"Item", i)
call InventoryRemoveItem(c, i)
set a = a + 1
endloop
set i = UnitItemInSlot(c, 5)
call SetTableObject(s, "Cancel", i)
call InventoryRemoveItem(c, i)
elseif o == 2 then
loop
exitwhen a > 6
set i = UnitItemInSlot(c, a-1)
if a < 5 then
call SetTableObject(s, "BackpackItem"+I2S((4*(op-1))+a), i)
endif
call InventoryRemoveItem(c, i)
set a = a + 1
endloop
endif
set a = 1
call SetTableInt(s, "CurrentMenu", m)
if m == 0 then
loop
exitwhen a > 4
set i = GetTableItem(s, "QuickMenuItem"+I2S(a))
call InventoryAddItem(c, i)
call SetItemPawnable(i, true)
set a = a + 1
endloop
set i = GetTableItem(s, "EquipmentMenu")
call InventoryAddItem(c, i)
call UnitDropItemSlot(c, i, 4)
set i = GetTableItem(s, "BackpackMenu")
call InventoryAddItem(c, i)
call UnitDropItemSlot(c, i, 5)
call SetItemCharges(i, GetTableInt(s, "BackpackItemsCount"))
call SetTableInt(s, "CurrentBackpackPage", 1)
elseif m == 1 then
set a = 0
loop
exitwhen a > 4
set i = GetTableItem(s, SlotToFillerName(a)+"Item")
call InventoryAddItem(c, i)
call SetItemPawnable(i, false)
set a = a + 1
endloop
set i = GetTableItem(s, "Cancel")
call InventoryAddItem(c, i)
elseif m == 2 then
call CompressBackpack(s)
loop
exitwhen b >= 4 or a > BackpackSize()
set i = GetTableItem(s, "BackpackItem"+I2S((4*(np-1))+a))
if i != null then
set b = b + 1
call InventoryAddItem(c, i)
call SetItemPawnable(i, false)
endif
set a = a + 1
endloop
call SetTableInt(s, "CurrentBackpackPage", np)
set i = GetTableItem(s, "SwitchPage")
call InventoryAddItem(c, i)
call UnitDropItemSlot(c, i, 4)
call SetItemCharges(i, np)
set i = GetTableItem(s, "Cancel")
call InventoryAddItem(c, i)
call UnitDropItemSlot(c, i, 5)
endif
if GetLocalPlayer() == GetOwningPlayer(c) then
call ClearTextMessages()
endif
set i = null
endfunction
function EquipItem takes unit c, string s, item i, string es returns nothing
local item e = GetTableItem(s, es+"Item")
local item f = GetTableItem(s, es+"Filler")
local string x
local gamecache g = InventoryCache()
local string m = I2S(GetItemTypeId(e))
local integer v
local string a
local integer l
call InventoryRemoveItem(c, i)
call SetTableObject(s, es+"Item", i)
if e != f then
set x = GetStoredString(g, m, "OnDrop")
if x != "" and x != null then
call ExecuteFunc(x)
endif
set v = GetStoredInteger(g, m, "damage")
if v > 0 then
call UnitAddBonus(c, 0, -v)
endif
set v = GetStoredInteger(g, m, "armor")
if v > 0 then
call UnitAddBonus(c, 1, -v)
endif
set v = GetStoredInteger(g, m, "hitpoints")
if v > 0 then
call UnitAddBonus(c, 2, -v)
endif
set v = GetStoredInteger(g, m, "manapoints")
if v > 0 then
call UnitAddBonus(c, 3, -v)
endif
set v = GetStoredInteger(g, m, "strength")
if v > 0 then
call SetHeroStr(c, GetHeroStr(c, false)-v, true)
endif
set v = GetStoredInteger(g, m, "agility")
if v > 0 then
call SetHeroAgi(c, GetHeroAgi(c, false)-v, true)
endif
set v = GetStoredInteger(g, m, "intelligence")
if v > 0 then
call SetHeroInt(c, GetHeroInt(c, false)-v, true)
endif
set v = GetStoredInteger(g, m, "ability")
if v > 0 then
set a = "Ability"+I2S(v)
set l = GetTableInt(s, a)-1
call SetTableInt(s, a, l)
if l < 1 then
call UnitRemoveAbility(c, v)
endif
endif
call InventoryAddItem(c, e)
endif
set m = I2S(GetItemTypeId(i))
set x = GetStoredString(g, m, "OnEquip")
if x != "" and x != null then
call ExecuteFunc(x)
endif
set v = GetStoredInteger(g, m, "damage")
if v > 0 then
call UnitAddBonus(c, 0, v)
endif
set v = GetStoredInteger(g, m, "armor")
if v > 0 then
call UnitAddBonus(c, 1, v)
endif
set v = GetStoredInteger(g, m, "hitpoints")
if v > 0 then
call UnitAddBonus(c, 2, v)
endif
set v = GetStoredInteger(g, m, "manapoints")
if v > 0 then
call UnitAddBonus(c, 3, v)
endif
set v = GetStoredInteger(g, m, "strength")
if v > 0 then
call SetHeroStr(c, GetHeroStr(c, false)+v, true)
endif
set v = GetStoredInteger(g, m, "agility")
if v > 0 then
call SetHeroAgi(c, GetHeroAgi(c, false)+v, true)
endif
set v = GetStoredInteger(g, m, "intelligence")
if v > 0 then
call SetHeroInt(c, GetHeroInt(c, false)+v, true)
endif
set v = GetStoredInteger(g, m, "ability")
if v > 0 then
set a = "Ability"+I2S(v)
set l = GetTableInt(s, a)+1
call SetTableInt(s, a, l)
call UnitAddAbility(c, v)
endif
call InventorySwapMenu(c, s, 0, 0, 0, 0)
set e = null
set f = null
set g = null
endfunction
function UnequipItem takes unit c, string s, item i, string es returns nothing
local item f = GetTableItem(s, es+"Filler")
local string x
local gamecache g = InventoryCache()
local string m = I2S(GetItemTypeId(i))
local integer v
local string a
local integer l
call AddItemToQuickMenu(c, s, i, false)
call SetTableObject(s, es+"Item", f)
call InventoryAddItem(c, f)
call UnitDropItemSlot(c, f, FillerNameToSlot(es))
set x = GetStoredString(g, m, "OnDrop")
if x != "" and x != null then
call ExecuteFunc(x)
endif
set v = GetStoredInteger(g, m, "damage")
if v > 0 then
call UnitAddBonus(c, 0, -v)
endif
set v = GetStoredInteger(g, m, "armor")
if v > 0 then
call UnitAddBonus(c, 1, -v)
endif
set v = GetStoredInteger(g, m, "hitpoints")
if v > 0 then
call UnitAddBonus(c, 2, -v)
endif
set v = GetStoredInteger(g, m, "manapoints")
if v > 0 then
call UnitAddBonus(c, 3, -v)
endif
set v = GetStoredInteger(g, m, "strength")
if v > 0 then
call SetHeroStr(c, GetHeroStr(c, false)-v, true)
endif
set v = GetStoredInteger(g, m, "agility")
if v > 0 then
call SetHeroAgi(c, GetHeroAgi(c, false)-v, true)
endif
set v = GetStoredInteger(g, m, "intelligence")
if v > 0 then
call SetHeroInt(c, GetHeroInt(c, false)-v, true)
endif
set v = GetStoredInteger(g, m, "ability")
if v > 0 then
set a = "Ability"+I2S(v)
set l = GetTableInt(s, a)-1
call SetTableInt(s, a, l)
if l < 1 then
call UnitRemoveAbility(c, v)
endif
endif
set f = null
set g = null
endfunction
function InventoryDragItemConditions takes nothing returns boolean
local integer i = GetIssuedOrderId()
return i > 852001 and i < 852008 and IsUnitInGroup(GetOrderedUnit(), udg_AAAInventoryGroup) and GetOrderTargetItem() != UnitItemInSlot(GetOrderedUnit(), i-852002)
endfunction
function InventoryDragItemActions takes nothing returns nothing
local unit c = GetOrderedUnit()
local string s = GetAttachedString(c, "InventoryTable")
local item d = GetOrderTargetItem()
local integer ts = GetIssuedOrderId()-852002
local item t = UnitItemInSlot(c, ts)
local integer m = GetTableInt(s, "CurrentMenu")
local integer di = GetItemTypeId(d)
local integer ti = GetItemTypeId(t)
local integer i = GetItemSlot(c, d)
local item e = GetTableItem(s, "EquipmentMenu")
local item b = GetTableItem(s, "BackpackMenu")
local item ca = GetTableItem(s, "Cancel")
local item sw = GetTableItem(s, "SwitchPage")
local integer p = GetTableInt(s, "CurrentBackpackPage")
local string es = GetItemEquipmentSlot(d)
if m == 0 then
if t == GetTableItem(s, "BackpackMenu") and d != e then
if BackpackHasEmptySlots(s) then
call AddItemToBackpack(c, s, d)
elseif d != t and t == b then
call InventoryError(c, "Backpack is full.")
endif
else
if d == e and ts != 4 then
call InventoryError(c, "Unable to drop this item.")
elseif d == b and ts != 5 then
call InventoryError(c, "Unable to drop this item.")
elseif t == e and d != b then
if IsEquipmentSlotValid(es) then
call EquipItem(c, s, d, es)
else
call InventoryError(c, "Item is not equipable.")
endif
elseif ts == 5 and d != b then
call InventoryError(c, "Can not add this item to your backpack.")
endif
endif
elseif m == 1 then
if t == ca then
if QuickMenuHasEmptySlots(s) then
call UnequipItem(c, s, d, es)
else
call InventoryError(c, "Quick page is full.")
endif
else
call InventoryError(c, "Unable to drop this item.")
endif
elseif m == 2 then
if t == ca and d != sw then
if QuickMenuHasEmptySlots(s) then
call AddItemToQuickMenu(c, s, d, true)
call InventorySwapMenu(c, s, 2, 2, p, p)
else
call InventoryError(c, "Quick page is full.")
endif
elseif t == sw then
call InventoryError(c, "Unable to drop this item.")
elseif t == ca and d != sw then
call InventoryError(c, "Unable to drop this item.")
elseif d == ca and ts != 5 then
call InventoryError(c, "Unable to drop this item.")
elseif d == sw and ts != 4 then
call InventoryError(c, "Unable to drop this item.")
endif
endif
set c = null
set d = null
set t = null
set e = null
set b = null
set ca = null
set sw = null
endfunction
function InventoryUnitUsesItemConditions takes nothing returns boolean
local integer i = GetItemTypeId(GetManipulatedItem())
return IsUnitInGroup(GetManipulatingUnit(), udg_AAAInventoryGroup) and (i == Cancel_ItemID() or i == BackpackMenu_ItemID() or i == SwitchPage_ItemID() or i == EquipmentMenu_ItemID())
endfunction
function InventoryUnitUsesItemActions takes nothing returns nothing
local unit c = GetManipulatingUnit()
local string s = GetAttachedString(c, "InventoryTable")
local item m = GetManipulatedItem()
local integer g = GetItemCharges(m)
local string ts = ""
local integer ti = 0
local integer a
local integer e = GetTableInt(s, "CurrentMenu")
local integer i = GetItemTypeId(m)
local integer o = GetTableInt(s, "CurrentBackpackPage")
local integer n = o + 1
if n > BackpackSize()/4 then
set n = 1
endif
if m == GetTableItem(s, "Cancel") then
set ti = Cancel_ItemID()
set ts = "Cancel"
elseif m == GetTableItem(s, "BackpackMenu") then
set ti = BackpackMenu_ItemID()
set ts = "BackpackMenu"
elseif m == GetTableItem(s, "EquipmentMenu") then
set ti = EquipmentMenu_ItemID()
set ts = "EquipmentMenu"
elseif m == GetTableItem(s, "SwitchPage") then
set ti = SwitchPage_ItemID()
set ts = "SwitchPage"
endif
if g == 0 and (i == BackpackMenu_ItemID() or i == SwitchPage_ItemID()) then
set a = GetItemSlot(c, m)
call RemoveItem(m)
call UnitAddItemToSlotById(c, ti, a)
set m = UnitItemInSlot(c, a)
call SetTableObject(s, ts, m)
call SetItemCharges(m, g+1)
else
call SetItemCharges(m, 0)
endif
call CompressBackpack(s)
if i == EquipmentMenu_ItemID() then
call InventorySwapMenu(c, s, e, 1, 0, 0)
elseif i == BackpackMenu_ItemID() then
call InventorySwapMenu(c, s, e, 2, o, o)
elseif i == SwitchPage_ItemID() then
call InventorySwapMenu(c, s, e, 2, o, n)
elseif i == Cancel_ItemID() then
call InventorySwapMenu(c, s, e, 0, o, o)
call SetItemCharges(GetTableItem(s, "BackpackMenu"), GetTableInt(s, "BackpackItemsCount"))
endif
set c = null
set m = null
endfunction
function UnitReAddItem_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local string s = GetAttachmentTable(t)
local unit u = GetTableUnit(s, "Unit")
local item i = GetTableItem(s, "Item")
if IsItemOwned(i) and not UnitHasItem(u, i) then
call SetItemUserData(i, 2)
endif
call UnitAddItem(u, i)
call UnitDropItemSlot(u, i, GetTableInt(s, "Slot"))
call ClearTable(s)
call DestroyTimer(t)
set t = null
set u = null
set i = null
endfunction
function UnitReAddItem takes unit u, item i, integer s returns nothing
local timer t = CreateTimer()
local string a = GetAttachmentTable(t)
call SetTableObject(a, "Unit", u)
call SetTableObject(a, "Item", i)
call SetTableInt(a, "Slot", s)
call TimerStart(t, 0, false, function UnitReAddItem_Child)
set t = null
endfunction
function InventoryDropItemConditions takes nothing returns boolean
local integer i = GetItemTypeId(GetManipulatedItem())
if not IsUnitInGroup(GetManipulatingUnit(), udg_AAAInventoryGroup) then
return false
endif
if (i == EquipmentMenu_ItemID() or i == BackpackMenu_ItemID() or i == Cancel_ItemID() or i == SwitchPage_ItemID()) and (GetItemUserData(GetManipulatedItem()) == 0) then
return true
endif
if GetItemUserData(GetManipulatedItem()) == 2 then
call SetItemUserData(GetManipulatedItem(), 0)
return false
endif
return GetTableInt(GetAttachedString(GetManipulatingUnit(), "InventoryTable"), "CurrentMenu") > 0 and (GetItemUserData(GetManipulatedItem()) == 0)
endfunction
function InventoryDropItemActions takes nothing returns nothing
local unit c = GetManipulatingUnit()
local string s = GetAttachedString(c, "InventoryTable")
local item i = GetManipulatedItem()
local integer d = GetItemTypeId(i)
if GetItemType(i) == ITEM_TYPE_CHARGED and GetItemCharges(i) == 0 then
set d = GetTableInt(s, "CurrentBackpackPage")
call InventorySwapMenu(c, s, 2, 2, d, d)
elseif d == EquipmentMenu_ItemID() or d == SwitchPage_ItemID() then
call UnitReAddItem(c, i, 4)
call CS_Error(GetOwningPlayer(c), "Unable to drop this item.")
elseif d == BackpackMenu_ItemID() or d == Cancel_ItemID() then
call UnitReAddItem(c, i, 5)
call CS_Error(GetOwningPlayer(c), "Unable to drop this item.")
elseif GetTableInt(s, "CurrentMenu") > 0 then
call UnitReAddItem(c, i, GetItemSlot(c, i))
call CS_Error(GetOwningPlayer(c), "Can only drop items from the quick menu.")
endif
set c = null
set i = null
endfunction
function InventoryOrderConditions takes nothing returns boolean
if not IsUnitInGroup(GetOrderedUnit(), udg_AAAInventoryGroup) or GetIssuedOrderId() != OrderId("smart") or GetOrderTargetItem() == null then
return false
endif
return GetTableInt(GetAttachedString(GetOrderedUnit(), "InventoryTable"), "CurrentMenu") > 0
endfunction
function InventoryOrderActions takes nothing returns nothing
local unit c = GetOrderedUnit()
local string s = GetAttachedString(c, "InventoryTable")
call InventorySwapMenu(c, s, GetTableInt(s, "CurrentMenu"), 0, GetTableInt(s, "CurrentBackpackPage"), 0)
call IssueTargetOrder(c, "smart", GetOrderTargetItem())
set c = null
endfunction
function Init_AAAInventory takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger u = CreateTrigger()
local trigger d = CreateTrigger()
local trigger o = CreateTrigger()
call ExecuteFunc("SetupItemBonuses")
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(t, Condition( function InventoryDragItemConditions))
call TriggerAddAction(t, function InventoryDragItemActions)
call TriggerRegisterAnyUnitEventBJ( u, EVENT_PLAYER_UNIT_USE_ITEM )
call TriggerAddCondition(u, Condition(function InventoryUnitUsesItemConditions))
call TriggerAddAction(u, function InventoryUnitUsesItemActions)
call TriggerRegisterAnyUnitEventBJ( d, EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerAddCondition(d, Condition(function InventoryDropItemConditions))
call TriggerAddAction(d, function InventoryDropItemActions)
call TriggerRegisterAnyUnitEventBJ(o, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(o, Condition(function InventoryOrderConditions))
call TriggerAddAction(o, function InventoryOrderActions)
set t = null
set u = null
set d = null
set o = null
endfunction
//===========================================================================
function InitTrig_AAAInventory takes nothing returns nothing
call ExecuteFunc("Init_AAAInventory")
endfunction
function WirtsLegEquip takes nothing returns nothing
// This function is executed when a unit equips an item of the type Wirt's Leg.
call TriggerSleepAction(0) // To avoid the system from clearing the text message instantly.
call BJDebugMsg("Wirt's Leg equipped.")
endfunction
function WirtsLegUnequip takes nothing returns nothing
// This function is executed when a unit unequips an item of the type Wirt's Leg.
call TriggerSleepAction(0) // To avoid the system from clearing the text message instantly.
call BJDebugMsg("Wirt's Leg unequipped.")
endfunction
function DisableDummySpellbooks takes nothing returns nothing
local integer i = 0
local player p
loop
exitwhen i > 15
set p = Player(i)
call SetPlayerAbilityAvailable(p, 'A000', false) // Disable the "Dummy Spell Book - Brilliance Aura" ability for all players.
call SetPlayerAbilityAvailable(p, 'A001', false) // Disable the "Dummy Spell Book - Devotion Aura" ability for all players.
call SetPlayerAbilityAvailable(p, 'A002', false) // Disable the "Dummy Spell Book - Command Aura" ability for all players.
set i = i + 1
endloop
set p = null
endfunction
//===========================================================================
function InitTrig_Extra takes nothing returns nothing
call ExecuteFunc("DisableDummySpellbooks")
endfunction