//UTF8
//ENDUTF8
Name | Type | is_array | initial_value |
creep_count | integer | Yes | |
spieler | player | No | |
unit_type | unitcode | Yes |
//TESH.scrollpos=0
//TESH.alwaysfold=0
//! zinc
/*
* PowerupSentinel
* ------------
* Placing this library in your map will automatically fix all rune/tome
* memory leaks in your map.
*
* Powerup items don't get removed automatically by the game, they instead
* just leave a small item in the map, this caused memory leaks but - worse -
* it also makes areas of your map where a lot of tomes have been used lag a lot.
*
*/
library PowerupSentinel
{
function onInit(){
trigger t = CreateTrigger();
TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DROP_ITEM);
TriggerAddCondition(t, function()->boolean {
if (GetWidgetLife(GetManipulatedItem())==0) {
RemoveItem(GetManipulatedItem());
}
return false;
});
}
}
//! endzinc
//TESH.scrollpos=75
//TESH.alwaysfold=0
library Jumpsystem requires TimedLoop
globals
private constant real DT = TimedLoop_PERIOD
private location temploc = Location(0,0)
private constant real RISE = 100
private constant integer FLY_TRICK = 'Amrf'
endglobals
private function TerrainZ takes real x, real y returns real
call MoveLocation(temploc, x, y)
return GetLocationZ(temploc)
endfunction
private function ApplyFlyTrick takes unit u returns nothing
call UnitAddAbility(u, FLY_TRICK)
call UnitRemoveAbility(u, FLY_TRICK)
endfunction
private struct Jump
real x
real y
real z
unit u
real vx
real vy
real vz
real grav
private method onTimedLoop takes nothing returns boolean
local real h
set .vz = .vz + .grav*DT
set .x = .x + .vx*DT
set .y = .y + .vy*DT
set .z = .z + .vz*DT
set h = .z - TerrainZ(.x, .y)
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
call SetUnitFlyHeight(.u, h, 0.)
return h > 0
endmethod
implement TimedLoop
static method create takes unit u, real targetX, real targetY, real height, real endtime returns Jump
local Jump this = Jump.allocate()
local real h
local real endZ
local real startZ
local real temp
if endtime > 0 then
call ApplyFlyTrick(u)
set .u = u
set .x = GetUnitX(u)
set .y = GetUnitY(u)
set .z = TerrainZ(.x, .y) + GetUnitFlyHeight(u)
set startZ = .z
set endZ = TerrainZ(targetX, targetY)
set h = 0.5*(startZ + endZ) + height
if h < startZ then
set h = startZ + RISE
endif
if h < endZ then
set h = endZ + RISE
endif
//assert h > max(startZ, endZ)
//assert endtime > 0
//calculate start speed and gravity
set temp = - SquareRoot(h - startZ) * SquareRoot(h - endZ)
set .vz = - ((2*(temp + startZ - h)) / endtime)
set .grav = 2*(endZ - .vz*endtime - startZ)/(endtime*endtime)
//calculate x and y speed
set .vx = (targetX - .x) / endtime
set .vy = (targetY - .y) / endtime
//start the TimedLoop:
call .startTimedLoop()
else
call BJDebugMsg("Function Jump called with invalid parameter: endtime == " + R2S(endtime))
endif
return this
endmethod
endstruct
function UnitJump takes unit u, real targetX, real targetY, real height, real endtime returns nothing
call Jump.create(u, targetX, targetY, height, endtime)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TimedLoop
//********************************************************
//* TimedLoop
//* ---------
//*
//* Requires jasshelper 0.9.G.1 or greater.
//*
//* A library + module that are meant to make those
//* array + timer loops easy, yet still faster than
//* other alternatives meant to be easy (In other words
//* no TriggerEvaluate is involved).
//*
//* The OOPness is interesting.
//*
//* Before implementing TimedLoop
//* your struct needs an onTimedLoop method that takes
//* nothing and returns boolean, if the method
//* returns false, the instance will get removed
//* from the loop and destroyed, else it will continue,
//* think of it as if the call asks the method a
//* question: "Should I continue the loop afterwards?"
//*
//* Alternatively, if you are not convinced, you may
//* use the TimedLoop_CONTINUE and TimedLoop_STOP
//* constants in the method's returns.
//*
//* After implementing TimedLoop, you can call
//* the startTimedLoop method to add the periodic event
//* to that instance, only call it once per instance.
//*
//* I recommend to call implement just bellow the
//* declaration of the onLoop method, else it will
//* actually use TriggerEvaluate, which is lame. Remind
//* me to implement a topsort in jasshelper.
//*
//* If you feel the need to destroy the struct outside
//* the loop, well, you'll have to add a flag to it so
//* you send a message to onLoop to make it return false.
//* A more complicated module to allow that easily would
//* come later.
//*
//********************************************************
//========================================================
// config:
globals
public constant real PERIOD = 0.025
// A lower value and everything using the module will
// look better, yet performance will drop.
endglobals
//========================================================
// implementation:
//
globals
public constant boolean STOP = false
public constant boolean CONTINUE = true
endglobals
//===========================
module TimedLoop
// god bless private module members.
//
private static thistype array V // The array
private static integer N = 0 // The count
private static timer T = null // the timer, one per
// struct that implements this
private static method onExpire takes nothing returns nothing
local integer n = 0
local thistype this // yay for odd-sounding syntax constructs
local integer i = 0
loop
exitwhen (i== thistype.N)
set this = .V[i]
if ( this.onTimedLoop() == CONTINUE ) then
set .V[n] = this
set n=n+1
else
call this.destroy()
endif
set i=i+1
endloop
set thistype.N = n
if (n== 0) then
call PauseTimer(.T)
endif
endmethod
public method startTimedLoop takes nothing returns nothing
set .V[.N] = this
set .N=.N + 1
if (.N == 1) then
if (.T == null) then
set .T = CreateTimer()
endif
call TimerStart(.T, PERIOD, true, function thistype.onExpire)
endif
endmethod
endmodule
endlibrary
library CSData initializer init
//****************************************************************************************************
// CSData 16.0
// ¯¯¯¯¯¯¯¯¯¯¯
// CSDatas are like UserData in units and items, they now use a hashtable instead of big arrays,
// should be faster and safer
//
// Notice that for public spells or systems to be distributed you should only use these
// for private objects (those who the mapper would never have access to) If you are making something
// for your map you can use them wherever you want.
//
// Best to be used in conjunction to CSArrays so you just specify an array id for a handle.
//
// DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag,
// -any 'argument' handle (like playerstate, damagetype, etc)
//
//****************************************************************************************************
//====================================================================================================
globals
private constant integer MAX_HANDLE_ID_COUNT = 408000
// values lower than 8191: very fast, but very unsafe.
// values bigger than 8191: not that fast, the bigger the number is the slower the function gets
// Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
// as the rather inflated value of 408000
endglobals
//=================================================================================================
// a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems, it then stayed that
// instead of changing to a private or public function since many outside spells use it.
//
function CS_H2I takes handle h returns integer //For compat
return GetHandleId(h) //
endfunction //
//==================================================================================================
globals
private hashtable ht
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetCSData takes handle h, integer v returns nothing
call SaveInteger(ht , 0, GetHandleId(h) , v)
endfunction
function GetCSData takes handle h returns integer
return LoadInteger( ht, 0, GetHandleId(h) )
endfunction
private function init takes nothing returns nothing
set ht = InitHashtable()
endfunction
endlibrary
//TESH.scrollpos=724
//TESH.alwaysfold=0
library CSSafeCache initializer init requires CSData
//*************************************************************************************************
//* *
//* CSSafeCache 15.3 http://wc3campaigns.net/vexorian *
//* ¯¯¯¯¯¯¯ *
//* CSCache is evil now, use just CSSafeCache when possible as it now contains all functions *
//* that do not use I2H or similar functions that are considered to cause unstability in the map *
//* *
//* CSCache has been deprecated, and is now unusuable since it can't be ported to patch 1.23b *
//* Migration from CSCache to CSSafeCache+structs should be easy *
//* *
//* However, for old compatibility, CSSafeCache needs to stick to using gamecache, which is not *
//* as good as hashtable (it is slower and may be vulnerable to Sync attacks) I recommend *
//* switching from CSSafeCache to hashtable or Table *
//* *
//*************************************************************************************************
//=================================================================================================
// CSSafeCache globals:
//
globals
gamecache cs_cache = null
hashtable cs_hcache = null
integer array cs_array1
integer array cs_array3
integer array cs_array2
private integer array cs_freeindexes
private integer array cs_pairx
private integer array cs_pairy
private integer array cs_freepairs
endglobals
private function init takes nothing returns nothing
// CSSafeCache initializer :
call FlushGameCache(InitGameCache("cscache"))
set cs_cache=InitGameCache("cscache")
call ExecuteFunc("InitArrayIndexes")
call ExecuteFunc("Pool_SetupCharMap")
set cs_hcache = InitHashtable()
endfunction
//=================================================================================================================
// CS Pairs
// ¯¯¯¯¯¯¯¯
// This is a sub system to assist csarrays, you can use them but CSArrays of size 2 have the same functionality
// although cspairs are be faster their space is limited and will start using gamecache if abused
//
function NewPair takes integer x, integer y returns integer
local integer i
if (cs_freepairs[0]==0) then
set cs_freepairs[8190]=cs_freepairs[8190]+1
set i= cs_freepairs[8190]
else
set i= cs_freepairs[cs_freepairs[0]]
set cs_freepairs[0]=cs_freepairs[0]-1
endif
if (i>=8189) then //because we can only recycle up to 8189 (free pairs array uses indexes 0 and 8190 for other purposes)
call StoreInteger(cs_cache,"pairx",I2S(i),x)
call StoreInteger(cs_cache,"pairy",I2S(i),y)
else
set cs_pairx[i]=x
set cs_pairy[i]=y
endif
return i
endfunction
function DestroyPair takes integer id returns nothing
if (id>=8189) then
call FlushStoredInteger(cs_cache,"pairx",I2S(id))
call FlushStoredInteger(cs_cache,"pairy",I2S(id))
else
set cs_freepairs[0]=cs_freepairs[0]+1
set cs_freepairs[cs_freepairs[0]] = id
endif
endfunction
function SetPairXY takes integer id, integer x, integer y returns nothing
if (id>=8189) then
call StoreInteger(cs_cache,"pairx",I2S(id),x)
call StoreInteger(cs_cache,"pairy",I2S(id),y)
else
set cs_pairx[id]=x
set cs_pairy[id]=y
endif
endfunction
function SetPairX takes integer id, integer x returns nothing
if (id>=8189) then
call StoreInteger(cs_cache,"pairx",I2S(id),x)
else
set cs_pairx[id]=x
endif
endfunction
function SetPairY takes integer id, integer y returns nothing
if (id>=8189) then
call StoreInteger(cs_cache,"pairy",I2S(id),y)
else
set cs_pairy[id]=y
endif
endfunction
function GetPairX takes integer id returns integer
if (id>=8189) then
return GetStoredInteger(cs_cache,"pairy",I2S(id))
endif
return cs_pairx[id]
endfunction
function GetPairY takes integer id returns integer
if (id>=8189) then
return GetStoredInteger(cs_cache,"pairx",I2S(id))
endif
return cs_pairy[id]
endfunction
//=================================================================================================================
// CS Dynamic Arrays
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Thanks: Pipedream, Peppar
//
// We can now create arrays in game! , also pass them as arguments or return values!
// a 1 length array is a pointer!
//
function Array_TryFree takes nothing returns nothing
local integer i
local integer N=cs_array1[0]
local integer k
local boolean cleaned=false
local integer loc
local integer q
local integer r
set i=cs_array1[146]
if (i>144) then
call TimerStart(GetExpiredTimer(),60.,false,function Array_TryFree)
return
endif
set loc=cs_freeindexes[i]
set q=0
loop
exitwhen (loc==0)
// we could just have used:
//set k=GetPairX(loc)
//set r=GetPairY(loc) But it is slower than direct usage:
if (loc>=8192) then
set k=GetStoredInteger(cs_cache,"pairx",I2S(loc))
set r=GetStoredInteger(cs_cache,"pairy",I2S(loc))
else
set k=cs_pairx[loc]
set r=cs_pairy[loc]
endif
if (k+i-1==N) then
//we found one we can remove from the list
set cleaned=true
//decrement N
set N=k-2
//Remove from the list:
if (q==null) then
//That was the first, update the array as well
set cs_freeindexes[i]=r
else
//Update the next of the previous one
//We could use : call SetPairY(q,,r) but it is slower
if (q>=8189) then
call StoreInteger(cs_cache,"pairy",I2S(q),r)
else
set cs_pairy[q]=r
endif
endif
if (r==null) then
//This was the last one, update it in the array as well
set cs_freeindexes[i+4096]=q
endif
call DestroyPair(loc)
set loc=q
endif
set q=loc
set loc=r
endloop
if (cleaned) then
set cs_array1[0]=N
set cs_array1[146]=1
else
set cs_array1[146]=cs_array1[i+1]
endif
call TimerStart(GetExpiredTimer(),0.2,false,function Array_TryFree)
endfunction
function InitArrayIndexes2 takes nothing returns nothing
local integer i=0
loop
exitwhen (i==8191)
set cs_pairx[i]=777
set cs_pairy[i]=777
set i=i+1
endloop
endfunction
function InitArrayIndexes takes nothing returns nothing
local integer i=0
local integer a=1
local integer b=1
local integer c
//By placing 777 there instead of 0 it is easier to recognize non correctly initialized bugs
loop
exitwhen (i== 8191)
set cs_array1[i]=777
set cs_array2[i]=777
set cs_array3[i]=777
//set cs_pairx[i]=777
//set cs_pairy[i]=777
set i=i+1
endloop
call ExecuteFunc("InitArrayIndexes2")
set cs_freeindexes[0]=0 //The stack for the table indexes.
set cs_freepairs[0]=0
set cs_freepairs[8190]=0
set i=1
loop
set c=a+b
set a=b
set b=c
exitwhen (b>144) //max size is 144
set cs_freeindexes[b]=0 //the first of the list
set cs_freeindexes[b+4096]=0 //the last of the list
loop
exitwhen (i>b)
set cs_array1[i]=b
set i=i+1
endloop
endloop
set cs_array1[i]=b //i is 145
set cs_array1[146]=1
set cs_array1[147]=101 //initial table index is 101
set cs_array1[0]=147
//index 0: Last used index
// 1 to 145 : Fibonacci sequence
// 146 : last check
// 147 : Table indexes check
//This has a good chance to compress the thing when necesary
call TimerStart(CreateTimer(),60.,false,function Array_TryFree)
endfunction
//=============================================================================================
// Create an array of size, max size is 144, if doinit is true it will put a bunch of zeros
// in the indexes
//
function NewArray takes integer size, boolean doinit returns integer
local integer i
local integer rsize=cs_array1[size]
local integer loc
set loc=cs_freeindexes[rsize]
if (loc!=0) then
set cs_freeindexes[rsize]= GetPairY(loc)
if (cs_freeindexes[rsize]==0) then
set cs_freeindexes[4096+rsize]=0
endif
set i=GetPairX(loc)
call DestroyPair(loc)
if (i==0) then
//this code was probably a good idea when we used locations for the free indexes list, now we use pairs which should not ever
//do this unless someone modiffied the pair array incorrectly
call BJDebugMsg("Caster System: Unexpected error (5): corrupt stack, attempt to recover "+I2S(rsize))
// recovering involves forgetting about the stack which got corrupted and start again from zero, it will leak
// and probably get slow due to usage of gamecache but it is better than the problems that a corrupt stack might cause
set cs_freeindexes[rsize]=0
set cs_freeindexes[4096+rsize]=0
return NewArray(size,doinit)
endif
else
//sz i i+1 i+2
//[ ][ ][ ][ ]
set i=cs_array1[0]+2
set cs_array1[0]=i+rsize-1
endif
//It used to store size in the index equal to the array's id
// but that required the get/set functions to increment 1 in every index
// calculation. Instead, making size the previous index to the array works
if (i<=8191) then
set cs_array1[i-1]=size
elseif (i<=16382) then
set cs_array2[i-8192]=size
else
call StoreInteger(cs_cache,I2S(-i),"size",size)
endif
if (not doinit) then
return i
endif
// 3
//[i][i+1][i+2]
set size=i+size-1
if (size>=16382) then
set size=16381
endif
loop
exitwhen (size<i) or (size<8191)
set cs_array2[size-8191]=0
set size=size-1
endloop
loop
exitwhen (size<i)
set cs_array1[size]=0
set size=size-1
endloop
//call DisplayTextToPlayer(GetLocalPlayer(),0,0,I2S(i))
return i
endfunction
//===============================================================================================================
// Remember to destroy arrays when you no longer need them, else new arrays will get slower after a bunch of
// arrays are active
//
function DestroyArray takes integer id returns nothing
local integer L
local integer loc
// local string k=I2S(-id)
local integer lstpace
if (id<=8191) then
set L=cs_array1[cs_array1[id-1]]
elseif (id<=16382) then
set L=cs_array1[cs_array2[id-8191]]
else
set L=cs_array1[GetStoredInteger(cs_cache,I2S(-id),"size")]
//No way you are gonna call DestroyArray without calling
//NewArray first, so we can use the gamecache variable directly instead
endif
set lstpace=id+L-1
call FlushStoredMission(cs_cache,I2S(-id))
if (lstpace>16382) then
if (lstpace==cs_array1[0]) then
//We just destroyed the array that happens to be at the end of the heap.
//Just get it back
set cs_array1[0]=id-2
set cs_array1[146]=1
else
//Add to the last
set loc=cs_freeindexes[L+4096]
if (loc==0) then
set loc=NewPair(id,0)
set cs_freeindexes[L]=loc
set cs_freeindexes[L+4096]=loc
else
set cs_freeindexes[L+4096]= NewPair(id,0)
//we could just use: call SetPairY(loc, cs_freeindexes[L+4096] ) //but that's slower
if (loc>=8189) then
call StoreInteger(cs_cache,"pairy",I2S(loc), cs_freeindexes[L+4096] )
else
set cs_pairy[loc]=cs_freeindexes[L+4096]
endif
endif
endif
elseif (lstpace==cs_array1[0]) then
//We just destroyed the array that happens to be at the end of the heap.
//Just get it back
set cs_array1[0]=id-2
set cs_array1[146]=1
else
set loc=cs_freeindexes[L]
set cs_freeindexes[L]=NewPair(id,loc)
if (loc==0) then
set cs_freeindexes[L+4096]=cs_freeindexes[L]
endif
endif
endfunction
//================================================================================================================
// Int Set/Get array usage prototypes.
//
// These are the actual functions, the rest are just the result of copy paste, if these functions are updated
// the other ones should be updated as well (They are just return bugged variations)
//
function SetArrayInt takes integer id, integer index, integer val returns nothing
set index=id+index
if (index<8191) then
set cs_array1[index]=val
elseif (index<16382) then
set cs_array2[index-8191]=val
else
call StoreInteger(cs_cache,I2S(-id),I2S(index),val)
endif
endfunction
function GetArrayInt takes integer id, integer index returns integer
set index=id+index
if (index<8191) then
return cs_array1[index]
elseif (index<16382) then
return cs_array2[index-8191]
endif
return GetStoredInteger(cs_cache,I2S(-id),I2S(index))
endfunction
//================================================================================================================
// String Set/Get array
//
// Due String related return bug issues, these are forced to use gamecache
//
function SetArrayString takes integer id, integer index, string val returns nothing
call StoreString(cs_cache,I2S(-id),I2S(index),val)
endfunction
function GetArrayString takes integer id, integer index returns string
return GetStoredString(cs_cache,I2S(-id),I2S(index))
endfunction
//(Boolean is not needed)
//==========================================================================================================================
// Returns the size of an array (the specified by player one, not the actual size of it) should be useful.
//
function GetArraySize takes integer id returns integer
if (id<=8191) then
return cs_array1[id-1]
elseif (id<=16382) then
return cs_array2[id-8192]
endif
return GetStoredInteger(cs_cache,I2S(-id),"size")
endfunction
//===========================================================================================================================
// Returns an array that is an exact copy of the given array
//
function CloneArray takes integer id returns integer
local integer sz
local integer i
local integer sz2
local integer x
local integer y
if (id<=8191) then
set sz=cs_array1[id-1]
elseif (id<=16382) then
set sz=cs_array2[id-8192]
else
set sz=GetStoredInteger(cs_cache,I2S(-id),"size")
//No way you are gonna call DestroyArray without calling
//NewArray first, so we can use the gamecache variable directly instead
endif
set i=NewArray(sz,false)
set sz2=i+sz-1
set sz=id+sz-1
set x=i
set y=id
loop
exitwhen ((y>sz) or (y>=8191) or (x>=8191))
set cs_array1[x]=cs_array1[y]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=8191) or (x>=16382))
set cs_array2[x-8191]=cs_array1[y]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=8191))
call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array1[y])
set x=y+1
set y=y+1
endloop
//...
loop
exitwhen ((y>sz) or (y>=16382) or (x>=8191))
set cs_array1[x]=cs_array2[y-8191]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=16382) or (x>=16382))
set cs_array2[x-8191]=cs_array2[y-8191]
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (y>=16382))
call StoreInteger(cs_cache,I2S(-i),I2S(x-i),cs_array2[y-8191])
set y=y+1
set x=x+1
endloop
//...
loop
exitwhen ((y>sz) or (x>=8191))
set cs_array1[x]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))
set y=y+1
set x=x+1
endloop
loop
exitwhen ((y>sz) or (x>=16382))
set cs_array2[x-8191]=GetStoredInteger(cs_cache,I2S(-id),I2S(y-id))
set y=y+1
set x=x+1
endloop
loop
exitwhen (y>sz)
call StoreInteger(cs_cache,I2S(-i),I2S(x-i),GetStoredInteger(cs_cache,I2S(-id),I2S(y-id)))
set y=y+1
set x=x+1
endloop
return i
endfunction
//==================================================================================================
// Attachable vars : Attacheable variables are what most other people call Handle Variables, they
// allow to relate data with any handle, using a label, and its value, the stuff auto flushes if
// the value is 0, false, "", or null .
//
// Differences between Attacheable variables and "Local Handle Variables" :
// - The names of the functions
// - The name of the function group does not cause confusion, it is difficult to say:
// "you should set local handle variables to null at the end of a function" since
// it sounds as if you were talking about the "Local Handle Variables"
// - And can work together with Tables.
//
// Gamecache stuff are NOT Case Sensitive, don't ever use "" for label (Crashes game!)
//
//
// Although locations and dynamic arrays are faster than gamecache, gamecache still keeps the flexibility
// Best thing to do in my opinion is to combine these options. By combining you can acquire gamecache
// flexibility and arrays/locs speed to solve a problem
//
//============================================================================================================
// For integers
//
function AttachInt takes handle h, string label, integer x returns nothing
if x==0 then
call FlushStoredInteger(cs_cache,I2S(GetHandleId(h)),label)
else
call StoreInteger(cs_cache,I2S(GetHandleId(h)),label,x)
endif
endfunction
function GetAttachedInt takes handle h, string label returns integer
return GetStoredInteger(cs_cache, I2S(GetHandleId(h)), label)
endfunction
//=============================================================================================================
function AttachReal takes handle h, string label, real x returns nothing
if x==0 then
call FlushStoredReal(cs_cache,I2S(GetHandleId(h)),label)
else
call StoreReal(cs_cache,I2S(GetHandleId(h)),label,x)
endif
endfunction
function GetAttachedReal takes handle h, string label returns real
return GetStoredReal(cs_cache,I2S(GetHandleId(h)),label)
endfunction
//=============================================================================================================
function AttachBoolean takes handle h, string label, boolean x returns nothing
if not x then
call FlushStoredBoolean(cs_cache,I2S(GetHandleId(h)),label)
else
call StoreBoolean(cs_cache,I2S(GetHandleId(h)),label,x)
endif
endfunction
function GetAttachedBoolean takes handle h, string label returns boolean
return GetStoredBoolean(cs_cache,I2S(GetHandleId(h)),label)
endfunction
//=============================================================================================================
function AttachString takes handle h, string label, string x returns nothing
if ((x=="") or (x==null)) then
call FlushStoredString(cs_cache,I2S(GetHandleId(h)),label)
else
call StoreString(cs_cache,I2S(GetHandleId(h)),label,x)
endif
endfunction
function GetAttachedString takes handle h, string label returns string
return GetStoredString(cs_cache,I2S(GetHandleId(h)),label)
endfunction
//============================================================================================================
function CleanAttachedVars takes handle h returns nothing
call FlushStoredMission(cs_cache,I2S(GetHandleId(h)))
endfunction
//============================================================================================================
// Left for compat
function CleanAttachedVars_NoSets takes handle h returns nothing
call FlushStoredMission(cs_cache,I2S(GetHandleId(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 integer loc=cs_freeindexes[0]
local integer i
if (loc!=0) then
set i=GetPairX(loc)
set cs_freeindexes[0]=GetPairY(loc)
call DestroyPair(loc)
return i
endif
set i=cs_array1[147]+1
set cs_array1[147]=i
return i
endfunction
function NewTable takes nothing returns string
local integer loc=cs_freeindexes[0]
local integer i
if (loc!=0) then
set i=GetPairX(loc)
set cs_freeindexes[0]=GetPairY(loc)
call DestroyPair(loc)
return I2S(i)
endif
set i=cs_array1[147]+1
set cs_array1[147]=i
return I2S(i)
endfunction
function GetAttachmentTable takes handle h returns string
return I2S(GetHandleId(h))
endfunction
//============================================================================================================
function DestroyTable takes string table returns nothing
local integer i=S2I(table)
local integer n
call FlushStoredMission(cs_cache,table)
if ((i>100) and (i<1000000)) then //All right, more than 1000000 tables is just wrong.
if (i==cs_array1[147]) then
set cs_array1[147]=cs_array1[147]-1
else
set cs_freeindexes[0]= NewPair(i,cs_freeindexes[0])
endif
endif
endfunction
//============================================================================================================
function ClearTable takes string table returns nothing
call FlushStoredMission(cs_cache,table)
call FlushChildHashtable(cs_hcache,StringHash(table))
endfunction
//============================================================================================================
//! textmacro TableHandleSetGet takes name,type,funcsuffix
function SetTable$name$ takes string table, string field, $type$ val returns nothing
if (val==null) then
call RemoveSavedHandle(cs_hcache,StringHash(table),StringHash(field))
else
call Save$funcsuffix$(cs_hcache,StringHash(table),StringHash(field),val)
endif
endfunction
function GetTable$name$ takes string table, string field returns $type$
return Load$funcsuffix$(cs_hcache,StringHash(table),StringHash(field))
endfunction
//! endtextmacro
//! runtextmacro TableHandleSetGet("Unit","unit","UnitHandle")
//! runtextmacro TableHandleSetGet("Trigger","trigger","TriggerHandle")
//! runtextmacro TableHandleSetGet("Group","group","GroupHandle")
//! runtextmacro TableHandleSetGet("Effect","effect","EffectHandle")
function SetTableObject takes string table, string field, unit val returns nothing
call SetTableUnit(table, field, val)
endfunction
//============================================================================================================
function SetTableInt takes string table, string field, integer val returns nothing
if (val==0) then
call FlushStoredInteger(cs_cache,table,field)
else
call StoreInteger(cs_cache,table,field,val)
endif
endfunction
function GetTableInt takes string table, string field returns integer
return GetStoredInteger(cs_cache,table,field)
endfunction
//============================================================================================================
function SetTableReal takes string table, string field, real val returns nothing
if (val==0) then
call FlushStoredReal(cs_cache,table,field)
else
call StoreReal(cs_cache,table,field,val)
endif
endfunction
function GetTableReal takes string table, string field returns real
return GetStoredReal(cs_cache,table,field)
endfunction
//============================================================================================================
function SetTableBoolean takes string table, string field, boolean val returns nothing
if (not(val)) then
call FlushStoredBoolean(cs_cache,table,field)
else
call StoreBoolean(cs_cache,table,field,val)
endif
endfunction
function GetTableBoolean takes string table, string field returns boolean
return GetStoredBoolean(cs_cache,table,field)
endfunction
//============================================================================================================
function SetTableString takes string table, string field, string val returns nothing
if (val=="") or (val==null) then
call FlushStoredString(cs_cache,table,field)
else
call StoreString(cs_cache,table,field,val)
endif
endfunction
function GetTableString takes string table, string field returns string
return GetStoredString(cs_cache,table,field)
endfunction
//============================================================================================================
// Returns true if the fiel contains a value different from 0, false, null, or "" (depending on the type)
// it is worthless to use this with boolean, since it would be the same as reading the boolean value
//
function HaveSetField takes string table, string field, integer fieldType returns boolean
if (fieldType == bj_GAMECACHE_BOOLEAN) then
return HaveStoredBoolean(cs_cache,table,field)
elseif (fieldType == bj_GAMECACHE_INTEGER) then
return HaveStoredInteger(cs_cache,table,field)
elseif (fieldType == bj_GAMECACHE_REAL) then
return HaveStoredReal(cs_cache,table,field)
elseif (fieldType == bj_GAMECACHE_STRING) then
return HaveStoredString(cs_cache,table,field)
endif
return false
endfunction
//============================================================================================================
// Allows to copy a table to another one, but it needs a FieldData object to know which fields of which type
// it is supposed to copy.
//
function CopyTable takes integer FieldData, string sourceTable, string destTable returns nothing
local integer i=1
local string k=I2S(FieldData)
local string k2
local string k3
local integer n=GetStoredInteger(cs_cache,k,"N")
local integer t
loop
exitwhen (i>n)
set k2=I2S(i)
set t=GetStoredInteger(cs_cache,k,k2)
set k3=GetStoredString(cs_cache,k,k2)
if (t==bj_GAMECACHE_BOOLEAN) then
if (HaveStoredBoolean(cs_cache,sourceTable,k3)) then
call StoreBoolean(cs_cache,destTable,k3,GetStoredBoolean(cs_cache,sourceTable,k3))
else
call FlushStoredBoolean(cs_cache,destTable,k3)
endif
elseif (t==bj_GAMECACHE_INTEGER) then
if (HaveStoredInteger(cs_cache,sourceTable,k3)) then
call StoreInteger(cs_cache,destTable,k3,GetStoredInteger(cs_cache,sourceTable,k3))
else
call FlushStoredInteger(cs_cache,destTable,k3)
endif
elseif (t==bj_GAMECACHE_REAL) then
if (HaveStoredReal(cs_cache,sourceTable,k3)) then
call StoreReal(cs_cache,destTable,k3,GetStoredReal(cs_cache,sourceTable,k3))
else
call FlushStoredReal(cs_cache,destTable,k3)
endif
elseif (t==bj_GAMECACHE_STRING) then
if (HaveStoredString(cs_cache,sourceTable,k3)) then
call StoreString(cs_cache,destTable,k3,GetStoredString(cs_cache,sourceTable,k3))
else
call FlushStoredString(cs_cache,destTable,k3)
endif
endif
set i=i+1
endloop
endfunction
//=============================================================================================
// FieldData inherits from Table, was just designed to be used by CopyTable.
//
function FieldData_Create takes nothing returns integer
return NewTableIndex()
endfunction
//============================================================================================================
// valueType uses the same integer variables from blizzard.j :
// bj_GAMECACHE_BOOLEAN, bj_GAMECACHE_INTEGER, bj_GAMECACHE_REAL and bj_GAMECACHE_STRING
//
function FieldData_AddField takes integer fielddata, string field, integer valueType returns nothing
local string k=I2S(fielddata)
local integer n=GetStoredInteger(cs_cache,k,"N")+1
local string k2=I2S(n)
call StoreString(cs_cache,k,k2,field)
call StoreInteger(cs_cache,k,k2,valueType)
call StoreInteger(cs_cache,k,"N",n)
endfunction
//=============================================================================================
// Destroys Field Data
function FieldData_Destroy takes integer fielddata returns nothing
call DestroyTable(I2S(fielddata))
endfunction
//=============================================================================================
// Pools
//
// A better name for pools would be sets, but by the time I made them I couldn't think of that
// name, besides the word set is already a JASS syntax word so it would have been problematic.
//
// Another naming failure is that values of a pool are called "items" but that conflicts with
// the word item that points to wc3 items, Pools can only store integer values, but if you want
// you can go and use the return bug on them.
//
function CreatePool takes nothing returns integer
local integer i=NewArray(34,false)
call SetArrayInt(i,0,0)
return i
endfunction
function ClearPool takes integer poolid returns nothing
call SetArrayInt(poolid,0,0) //[0:integer:n]
call FlushStoredMission(cs_cache,I2S(-poolid))
endfunction
function DestroyPool takes integer poolid returns nothing
call DestroyArray(poolid)
endfunction
function PoolAddItem takes integer poolid, integer value returns nothing
local integer n
local string k=I2S(-poolid)
local string vk="#"+I2S(value)
if not HaveStoredInteger(cs_cache,k,vk) then
set n=GetArrayInt(poolid,0)+1 //[0:integer:N]
call StoreInteger(cs_cache,k,vk,n)
if (n>33) then
call StoreInteger(cs_cache,k,I2S(n),value)
else
call SetArrayInt(poolid,n,value)
endif
call SetArrayInt(poolid,0,n) //[0:integer:N]
endif
endfunction
function PoolRemoveItem takes integer poolid, integer value returns nothing
local string k=I2S(-poolid)
local string vk="#"+I2S(value)
local integer p=GetStoredInteger(cs_cache,k,vk)
local integer n
if (p!=0) then
set n=GetArrayInt(poolid,0) //[0:integer:N]
call FlushStoredInteger( cs_cache, k, vk)
if (n>p) then
if (n>33) then
set vk=I2S(n)
set value=GetStoredInteger(cs_cache,k,vk)
call FlushStoredInteger(cs_cache,k,vk)
else
set value=GetArrayInt(poolid,n)
endif
call StoreInteger(cs_cache,k,"#"+I2S(value),p)
if (p>33) then
call StoreInteger(cs_cache,k,I2S(p),value)
else
call SetArrayInt(poolid,p,value)
endif
elseif (p>33) then
call FlushStoredInteger(cs_cache,k,I2S(p))
endif
call SetArrayInt( poolid,0,n - 1) //[0:integer:N]
endif
endfunction
//===================================================================================
function PoolGetItem takes integer poolid, integer itemn returns integer
if (itemn>33) then
return GetStoredInteger( cs_cache, I2S(-poolid), I2S(itemn))
endif
return GetArrayInt(poolid,itemn)
endfunction
//===================================================================================
function CountItemsInPool takes integer poolid returns integer
return GetArrayInt(poolid,0) //[0:integer:N]
endfunction
//===================================================================================
// Removed : GetEnumPoolItem , ForPool and ForPool2 they are much worse than just
// using CountItemsInPool and PoolGetItem to iterate the pool
//
//===================================================================================
function GetFirstOfPool takes integer poolid returns integer
return GetArrayInt(poolid,1) //[1 is just the first of the pool]
endfunction
//===================================================================================
function PoolPickRandomItem takes integer poolid returns integer
local integer p=GetRandomInt( 1, GetArrayInt(poolid,0) )
if (p>33) then
return GetStoredInteger( cs_cache, I2S(-poolid), I2S(p))
endif
return GetArrayInt(poolid,p)
endfunction
//===================================================================================
function GetItemPositionInPool takes integer poolid, integer it returns integer
return GetStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it))
endfunction
//===================================================================================
function IsItemInPool takes integer poolid, integer it returns boolean
return(HaveStoredInteger( cs_cache, I2S(-poolid), "#"+I2S(it)) )
endfunction
//===================================================================================
// This had to be optimized for speed, if it was just a loop using the above functions
// that would have been too slow to be worth keeping. That's a bad thing about JASS
// it is such an slow language that code reusability always has the cost of speed
//
function PoolAddPool takes integer sourcepoolid, integer destpoolid returns nothing
local integer a=1
local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N]
local integer dn=GetArrayInt( destpoolid,0) //[0:integer:N]
local string sk=I2S(-sourcepoolid)
local string k=I2S(-destpoolid)
local integer v
local string vk
loop
exitwhen (a>n)
if (a>33) then
set v=GetStoredInteger(cs_cache,sk,I2S(a))
else
set v=GetArrayInt(sourcepoolid,a)
endif
set vk="#"+I2S(v)
if not HaveStoredInteger(cs_cache,k,vk) then
set dn=dn+1
call StoreInteger(cs_cache,k,vk,dn)
if (dn>33) then
call StoreInteger(cs_cache,k,I2S(dn),v)
else
call SetArrayInt(destpoolid,dn,v)
endif
endif
set a=a+1
endloop
call SetArrayInt(destpoolid,0,dn) //[0:integer:N]
endfunction
//=============================================================================================
// Oh darn, After making PoolAddPool I don't feel like writting this one
// All right I am at least make the get code
//
function PoolRemovePool takes integer sourcepoolid, integer destpoolid returns nothing
local integer a=1
local integer n=GetArrayInt( sourcepoolid,0) //[0:integer:N]
local integer v
local string sk=I2S(-sourcepoolid)
loop
exitwhen a>n
if (a>33) then
set v=GetStoredInteger(cs_cache,sk,I2S(a) )
else
set v=GetArrayInt(sourcepoolid,a)
endif
call PoolRemoveItem( destpoolid, v)
set a=a+1
endloop
endfunction
//===================================================================================
// Adds a tokenized string to a pool,
// Example: PoolAddS(udg_p, "1;2;3;4") will add to the udg_p pool : 1,2,3 and 4
//
function PoolAddS takes integer poolid, string s returns nothing
local integer i=0
local integer st
local string c
set s=s+";"
set st=0
loop
set c=SubString(s, i, i+1)
exitwhen (c == "") or (c == null)
if (c == ";") then
call PoolAddItem( poolid, S2I(SubString(s, st, i)) )
set st=i+1
endif
set i=i+1
endloop
endfunction
//===================================================================================
// Converts a tokenized string into a pool,
// Example: S2Pool( "1;2;3;4") will return a pool that has 1,2,3 and 4 inside
//
function S2Pool takes string s returns integer
local integer spool= CreatePool()
call PoolAddS(spool,s)
return spool
endfunction
//===================================================================================
// Does the opposite of S2Pool, debugging is a good use for this function.
//
function Pool2S takes integer P returns string
local integer N=CountItemsInPool(P)
local integer i
local string s
if (N>=1) then
set s=I2S(PoolGetItem(P,1) )
set i=2
else
return ""
endif
loop
exitwhen (i>N)
set s=s+";"+I2S(PoolGetItem(P,i))
set i=i+1
endloop
return s
endfunction
//=============================================================================================================
// Fixes a lame bug by blizzard related to the custom script section (The condition of the if statement might
// actually be true.
//
function Pool_Percent takes nothing returns string
if ("%"=="") then
return "%%"
endif
return "%"
endfunction
function Pool_SetupCharMap takes nothing returns nothing
local string cm=".................................!.#$"+Pool_Percent()+"&'()*+,-./0123456789:;<=>.@ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................."
local integer i=0
local string c
if HaveStoredInteger(cs_cache,"charmap_upper","A") then
return
endif
loop
set c=SubString(cm,i,i+1)
exitwhen (c==null) or (c=="")
if (c!=".") then
if c==StringCase(c,true) then
call StoreInteger(cs_cache,"charmap_upper",c,i)
else
call StoreInteger(cs_cache,"charmap_lower",c,i)
endif
endif
set i=i+1
endloop
endfunction
function Pool_Rawcode2Int takes string s returns integer
local string c
local integer i=0
local integer r=0
loop
exitwhen i>3
set c=SubString(s,i,i+1)
set r=r*256
if c==StringCase(c,true) then
set r=r+GetStoredInteger(cs_cache,"charmap_upper",c)
else
set r=r+GetStoredInteger(cs_cache,"charmap_lower",c)
endif
set i=i+1
endloop
return r
endfunction
function PoolAddRawcodes_thread takes nothing returns nothing
//Threaded because I don't want it to halt execution for no reason
//
local string s=bj_lastPlayedMusic
local integer poolid=bj_groupEnumTypeId
local string c
local integer i=0
local integer st=0
set s=s+";"
loop
set c=SubString(s, i, i+1)
exitwhen (c == "") or (c == null)
if c == ";" then
call PoolAddItem(poolid, Pool_Rawcode2Int(SubString(s,st,i) ))
set st=i+1
endif
set i=i+1
endloop
endfunction
//=====================================================================================================================
// Adds a string of tokenized rawcodes to a pool
// Example: PoolAddRawcodes(udg_p,"A000;A001") will add 'A000' and 'A001' to the pool
//
// (Saves some lines, but is not as good efficiency wise)
//
function PoolAddRawcodes takes integer poolid, string s returns nothing
local string b=bj_lastPlayedMusic
set bj_groupEnumTypeId=poolid
set bj_lastPlayedMusic=s
call ExecuteFunc("PoolAddRawcodes_thread")
set bj_lastPlayedMusic=b
endfunction
//===================================================================================================================
// Converts a tokenized string of rawcodes into a pool,
// Example: Rawcodes2Pool( "A000;A001;AHbz;S000") will return a pool that has 'A000,'A001','AHbx' and 'S000' inside
//
// (Saves some lines, but is not as good efficiency wise)
//
function Rawcodes2Pool takes string s returns integer
local integer spool= CreatePool()
call PoolAddRawcodes(spool,s)
return spool
endfunction
//===================================================================================================================
// A subproduct of the Pool's Rawcode support is that we can easily have this function so I am including it even if
// it has nothing to do with data storage.
//
// takes "Aloc" and converts it into 'Aloc'
// it is different to the Pool_Rawcode2Int function in that it is safe to use it when it is the first CSCache
// function ever used. But it is a little slower (wc3mapoptimizer should make it as fast though)
//
function CS_Rawcode2Int takes string s returns integer
local string c
local integer i=0
local integer r=0
loop
exitwhen i>3
set c=SubString(s,i,i+1)
set r=r*256
if c==StringCase(c,true) then
set r=r+GetStoredInteger(cs_cache,"charmap_upper",c)
else
set r=r+GetStoredInteger(cs_cache,"charmap_lower",c)
endif
set i=i+1
endloop
return r
endfunction
endlibrary
//TESH.scrollpos=12
//TESH.alwaysfold=0
library CasterSystem initializer InitCasterSystem requires CSSafeCache, GroupUtils, TimerUtils
//***************************************************************************
//* *
//* Caster System 16.0 *
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ http://wc3campaigns.net/vexorian *
//* Requires: *
//* ¯¯¯¯¯¯¯¯¯ *
//* - Jasshelper / Newgen pack *
//* *
//* - The CSSafeCache Module *
//* - The CSData Module *
//* - The CSSafety Module *
//* *
//* - The caster unit from this map Can be found in this map's unit editor *
//* ( Custom Units\Neutral Passive\Units\Caster ) *
//* *
//* ( Update the cs_CasterUnitId constant next:) *
//* *
//* - the war3mapImported\dummy.mdx imported file (find it in this map) *
//* *
//***************************************************************************
//====================================================================================================================================================================
// Caster System Configuration constants :
//
globals
//
// Caster Unit type rawcode (changes betwen maps, always use it inside '')
//
constant integer cs_CasterUnitId = 'e003'
// cs_TIMER_CYCLE : Cycle value for the projectile movement in seconds (Each 0.04 the projectiles get moved)
// 0.01 looks smooth but is lag friendly
// 0.025 looks smooth and probably matches wc3's frame rate (so in theory, lower values than it are not needed)
// 0.1 looks horrible but is not laggy
// 0.04 is decent for the human eye and very efficient.
// 0.035 is ... well, a little smoother than 0.04
// 0.05 would be an improvement in efficiency but probably doesn't look too well )
//
constant real cs_TIMER_CYCLE = 0.035
//
// 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.
//
constant integer cs_DamageTreeDetectorId = 'Aeat'
//
// 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:
//
constant integer cs_FlyingHeightHack = 'Amrf'
//
// This must point to an inventory ability with 6 slots that does not add bonuses, you don't need one unless
// the caster system item hiding functions are used in your map
//
constant integer cs_DummyInventory_Id = 'null'
//
//Maximum collision size in your map - Affects the caster system's area cast/damage functions
//
constant real cs_MaxUnitCollisionSize = 55.0
//
// Next are default attack and damage types for the old caster system functions or when using 0 as damageoptions
//
constant attacktype cs_DefaultAttackType = ATTACK_TYPE_CHAOS
constant damagetype cs_DefaultDamageType = DAMAGE_TYPE_UNIVERSAL
//
// cs_InitialCastersNumber: Number of casters to create on map init:
//
constant integer cs_InitialCastersNumber = 12
endglobals
//
//=================================================================================================
// Caster System script:
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//=================================================================================================
// main Caster System global variables:
//
globals
//old ones (udg_ preffix forced for compat ( )
unit udg_currentcaster = null
real array udg_castervars
group udg_casters = null
integer udg_currentabi = 0
unit udg_currenthurter = null
real udg_delayhack = 0.
location udg_sourcehack = null
//--
integer array cs_missiles
integer cs_missilecount = 0
timer cs_movementtimer = CreateTimer()
boolean cs_movementtimer_active = false
endglobals
//=================================================================================================
function CS_CopyGroup takes group g returns group
set bj_groupAddGroupDest=NewGroup()
call ForGroup(g, function GroupAddGroupEnum)
return bj_groupAddGroupDest
endfunction
globals
constant real cs_RectLimitOffSet = 50.0
real cs_game_maxx
real cs_game_maxy
real cs_game_miny
real cs_game_minx
endglobals
function CS_SafeXY_Init takes nothing returns nothing
set cs_game_maxx=GetRectMaxX(bj_mapInitialPlayableArea)-cs_RectLimitOffSet
set cs_game_maxy=GetRectMaxY(bj_mapInitialPlayableArea)-cs_RectLimitOffSet
set cs_game_miny=GetRectMinY(bj_mapInitialPlayableArea)+cs_RectLimitOffSet
set cs_game_minx=GetRectMinX(bj_mapInitialPlayableArea)+cs_RectLimitOffSet
endfunction
function CS_SafeX takes real x returns real
if (x<cs_game_minx) then
return cs_game_minx
elseif (x>cs_game_maxx) then
return cs_game_maxx
endif
return(x)
endfunction
function CS_SafeY takes real y returns real
if (y<cs_game_miny) then
return cs_game_minx
elseif (y>cs_game_maxy) then
return cs_game_maxy
endif
return(y)
endfunction
//Deprecated, since patch 1.21 there is no crash anymore, it is possibly
// still mildly useful since it does bound checking.
function CS_MoveUnit takes unit u, real x, real y returns boolean
local boolean b=true
if (x<cs_game_minx) then
set b=false
elseif (x>cs_game_maxx) then
set b=false
elseif (y>cs_game_maxy) then
set b=false
elseif (y<cs_game_miny) then
set b=false
endif
if (b) then
call SetUnitX(u, x)
call SetUnitY(u, y)
endif
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_MaxUnitCollisionSize+area,cond)
if (bx!=null) then
call DestroyBoolExpr(cond)
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_MaxUnitCollisionSize+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), cs_CasterUnitId, x ,y ,fac)
call UnitAddAbility(m, 'Aloc')
call UnitAddAbility(m, cs_FlyingHeightHack)
call UnitRemoveAbility(m, cs_FlyingHeightHack )
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 CreateCasters takes integer n returns nothing
local integer a=0
local unit c
loop
exitwhen a>=n
set c=CreateCaster(0,0,0)
call GroupAddUnit( udg_casters, c)
set a=a+1
endloop
set c=null
endfunction
private function InitCasterSystem takes nothing returns nothing
set udg_casters=NewGroup()
call CS_SafeXY_Init()
call CreateCasters(cs_InitialCastersNumber)
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
set cs_dmg_caster=CreateCaster(0.,0.,0.)
call UnitRemoveAbility(cs_dmg_caster,'Aloc') //Otherwise the units would flee like crazy
endfunction
//====================================================================================================================================================================
function GetACaster takes nothing returns unit
set udg_currentcaster=FirstOfGroup( udg_casters)
if udg_currentcaster == null then
set udg_currentcaster=CreateCaster(0,0,0)
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 RecycleCaster 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 RecycleCaster_Light takes unit caster returns nothing
if GetWidgetLife(caster)>=0.405 then
call SetUnitOwner( caster, Player(15), true)
call GroupAddUnit( udg_casters, caster)
endif
endfunction
function RecicleCaster takes unit caster returns nothing
call RecycleCaster(caster)
endfunction
function RecicleCaster_Light takes unit caster returns nothing
call RecycleCaster_Light(caster)
endfunction
private struct csrecy
unit caster
integer abil
endstruct
function CasterRecycleTimed_X takes nothing returns nothing
local timer t=GetExpiredTimer()
local csrecy k=GetCSData(t)
if (k.abil!=0) then
call UnitRemoveAbility(k.caster,k.abil)
endif
call RecycleCaster(k.caster)
call k.destroy()
call ReleaseTimer(t)
endfunction
function CasterRecycleTimed takes unit caster, integer abi, real delay returns nothing
local timer t=NewTimer()
local csrecy k= csrecy.create()
set k.caster=caster
set k.abil=abi
call SetCSData(t,k)
call TimerStart(t,delay,false,function CasterRecycleTimed_X)
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 RecycleCaster(caster)
endif
set caster=null
endfunction
function RecycleCasterAfterCastEx 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 RecicleCasterAfterCastEx takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
call RecycleCasterAfterCastEx(caster,delaytime,abilid,activeability)
endfunction
function CasterWaitForEndCast_Light 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 RecycleCaster_Light(caster)
endif
set caster=null
endfunction
function RecycleCasterAfterCastEx_Light 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_Light" )
endfunction
function RecicleCasterAfterCastEx_Light takes unit caster, real delaytime, integer abilid, boolean activeability returns nothing
call RecycleCasterAfterCastEx_Light(caster,delaytime,abilid,activeability)
endfunction
function RecicleCasterAfterCast takes unit caster, integer abilid returns nothing
call RecycleCasterAfterCastEx(caster,udg_delayhack,abilid,false)
endfunction
function RecycleCasterAfterCast takes unit caster, integer abilid returns nothing
call RecycleCasterAfterCastEx(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 RecycleCaster_Light( 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 SetUnitX(caster,x)
call SetUnitY(caster,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 RecycleCaster_Light( caster)
else
call RecycleCasterAfterCastEx_Light(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 SetUnitX(caster,x1)
call SetUnitY(caster,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 RecycleCaster_Light( caster)
else
call RecicleCasterAfterCastEx_Light(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
//====================================================================================================================================================================
private struct cssabi
effect fx
unit caster
integer abil
endstruct
function CasterUseAbilityLevelStatic_Rec takes nothing returns nothing
local timer t=GetExpiredTimer()
local cssabi k=GetCSData(t)
call RecycleCaster(k.caster)
call k.destroy()
call ReleaseTimer(t)
endfunction
function CasterUseAbilityLevelStatic_X takes nothing returns nothing
local timer t=GetExpiredTimer()
local cssabi k=GetCSData(t)
call DestroyEffect(k.fx)
call UnitRemoveAbility( k.caster, k.abil)
call TimerStart(t,2,false, function CasterUseAbilityLevelStatic_Rec)
endfunction
function CasterUseAbilityLevelStatic takes player owner, string modelpath, integer abilityid, integer level, real duration, real x, real y returns unit
local timer t=NewTimer()
local unit c=GetACaster()
local cssabi k= cssabi.create()
call SetUnitPosition( c, x, y)
set k.fx= AddSpecialEffectTarget( modelpath, c,"origin" )
set k.caster = c
set k.abil=abilityid
call SetUnitOwner(c, owner, true)
call UnitAddAbility(c, abilityid)
call SetUnitAbilityLevel(c, abilityid, level)
call SetCSData(t,k)
call TimerStart(t,duration,false,function CasterUseAbilityLevelStatic_X)
set udg_currentcaster=c
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=NewGroup()
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 SetUnitX(caster,GetLocationX(udg_sourcehack))
call SetUnitY(caster,GetLocationY(udg_sourcehack))
else
call SetUnitX(caster,GetUnitX(tempunit))
call SetUnitY(caster,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 RecycleCaster(caster)
endif
call ReleaseGroup(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 ( GetWidgetLife(GetFilterUnit()) > 0.405)
endfunction
function CasterAOE_IsFilterAlly takes nothing returns boolean
return IsUnitAlly( GetFilterUnit(), bj_groupEnumOwningPlayer ) and ( GetWidgetLife(GetFilterUnit()) > 0.405)
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=NewGroup()
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
//====================================================================================================================================================================
globals
timer cs_sourcehacktimer = CreateTimer()
timer cs_delayhacktimer = CreateTimer()
endglobals
function ResetSourceHack takes nothing returns nothing
if (udg_sourcehack!=null) then
call RemoveLocation(udg_sourcehack)
set udg_sourcehack=null
endif
endfunction
function CasterSetCastSource takes real x, real y returns nothing
if (udg_sourcehack==null) then
set udg_sourcehack=Location(x,y)
else
call MoveLocation(udg_sourcehack,x,y)
endif
call TimerStart(cs_sourcehacktimer,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.
endfunction
function CasterSetRecycleDelay takes real Delay returns nothing
set udg_delayhack=Delay
call TimerStart(cs_delayhacktimer,0.,false,function ResetDelayHack)
endfunction
//====================================================================================================================================================================
//Super DamageOptions structure!
globals
attacktype cs_dopt_Atype = null
damagetype cs_dopt_Dtype = null
unittype cs_dopt_ExceptionUtype = null
real cs_dopt_ExceptionFct = 1.0
unittype cs_dopt_OnlyUtype = null
unittype cs_dopt_IgnoreUtype = null
integer cs_dopt_EnemyAlly = 0 //[ 0 = onlyenemies, 1= forceall, 2=onlyallies]
integer cs_dopt_dfab1 = 'null'
real cs_dopt_dfab1_fc = 1.0
integer cs_dopt_dfab2 = 'null'
real cs_dopt_dfab2_fc = 1.
integer cs_dopt_dfab3 = 'null'
real cs_dopt_dfab3_fc = 1.
real cs_dopt_Ally_fc = 1.
endglobals
function DamageTypes takes attacktype attT, damagetype dmgT returns integer
// set udg_castervars[100] = CS_H2I(attT)
// set udg_castervars[101] = CS_H2I(dmgT)
set cs_dopt_Atype=attT
set cs_dopt_Dtype=dmgT
return 1
endfunction
function DamageException takes unittype Exception, real ExceptionFactor returns integer
set cs_dopt_ExceptionUtype=Exception
set cs_dopt_ExceptionFct = ExceptionFactor
// set udg_castervars[102] = CS_H2I(Exception)
// set udg_castervars[103] = ExceptionFactor
return 2
endfunction
function DamageOnlyTo takes unittype ThisUnitType returns integer
set cs_dopt_OnlyUtype = ThisUnitType
// 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 cs_dopt_EnemyAlly=0
// ouch, forgot what it was
return 64
endfunction
function ForceDamageAllies takes nothing returns integer
set cs_dopt_EnemyAlly=1
return 64
endfunction
function DamageOnlyAllies takes nothing returns integer
set cs_dopt_EnemyAlly=2
return 64
endfunction
function DamageFactorAbility1 takes integer spellid, real factor returns integer
set cs_dopt_dfab1=spellid
set cs_dopt_dfab1_fc=factor
return 128
endfunction
function DamageFactorAbility2 takes integer spellid, real factor returns integer
set cs_dopt_dfab2=spellid
set cs_dopt_dfab2_fc=factor
return 256
endfunction
function DamageFactorAbility3 takes integer spellid, real factor returns integer
set cs_dopt_dfab3=spellid
set cs_dopt_dfab3_fc=factor
return 512
endfunction
function DamageIgnore takes unittype ThisUnitType returns integer
set cs_dopt_IgnoreUtype = ThisUnitType
// set udg_castervars[112] = CS_H2I(ThisUnitType)
return 1024
endfunction
function DamageAlliedFactor takes real fct returns integer
set cs_dopt_Ally_fc = fct
// 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
//=================================================================================================
globals
unit cs_dmg_caster=null
endglobals
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
//Since a unit is in that point, we don't need checks.
call SetUnitX(cs_dmg_caster,GetUnitX(u))
call SetUnitY(cs_dmg_caster,GetUnitY(u))
call SetUnitOwner(cs_dmg_caster,GetOwningPlayer(u),false)
set r=hp
if (hp<1) then
call SetWidgetLife(u,1)
set r=1
endif
call UnitDamageTarget(cs_dmg_caster,u,0.01,true,false,a,d,null)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
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)
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* cs_dopt_Ally_fc
endif
set d=d-2048
endif
if d>=1024 then
if CS_IsUnitType(target, cs_dopt_IgnoreUtype ) then
return 0.0
endif
set d=d-1024
endif
if d>=512 then
if GetUnitAbilityLevel(target, cs_dopt_dfab1 )>0 then
set r=r*cs_dopt_dfab1_fc
endif
set d=d-512
endif
if d>=256 then
if GetUnitAbilityLevel(target, cs_dopt_dfab2 )>0 then
set r=r*cs_dopt_dfab2_fc
endif
set d=d-256
endif
if d>=128 then
if GetUnitAbilityLevel(target, cs_dopt_dfab3 )>0 then
set r=r*cs_dopt_dfab3_fc
endif
set d=d-128
endif
if d>=64 then
if (cs_dopt_EnemyAlly==0) and IsUnitAlly(target,GetOwningPlayer(hurter)) then
return 0.0
elseif (cs_dopt_EnemyAlly==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 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,cs_dopt_OnlyUtype) then
return 0.0
endif
endif
if d>=2 then
set d=d-2
if CS_IsUnitType( target, cs_dopt_ExceptionUtype ) then
set r=r* cs_dopt_ExceptionFct
endif
endif
if d>=1 then
set d=d-1
set r=r*GetDamageFactor(target,cs_dopt_Atype,cs_dopt_Dtype)
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
call SetUnitX(cs_dmg_caster,GetUnitX(victim))
call SetUnitY(cs_dmg_caster,GetUnitY(victim))
call SetUnitOwner(cs_dmg_caster,hurter,false)
call DamageUnitByTypes(cs_dmg_caster,victim,damage,cs_DefaultAttackType,cs_DefaultDamageType)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
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=NewTimer()
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 GetWidgetLife(target)<=0.405
set i=i+1
set next=i*damageperiod
endif
exitwhen (TimerGetRemaining(t) <= 0) or GetWidgetLife(target)<=0.405
call TriggerSleepAction(0)
endloop
call DestroyEffect(fx)
call ReleaseTimer(t)
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=NewTimer()
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 GetWidgetLife(target)<=0.405
call TriggerSleepAction(0)
endloop
call DestroyEffect(fx)
call ReleaseTimer(t)
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
//[
private struct dostruct
integer value
attacktype attt
damagetype dmgt
unittype excp
real excf
unittype only
integer allied
integer dfab1
real dfab1_fc
integer dfab2
real dfab2_fc
integer dfab3
real dfab3_fc
unittype ign
real ally_fc
endstruct
// integer k used to point to a table in gamecache, this is the reason I am not using dostruct directly
// the evil backwards compatibility... You shall find out why OOP guys like encapsullation so much...
//
// It's fun, it was first an integer pointing to a mission in gamecache, then it was a dynamic array
// and now it is a struct... so much history.
function SetDamageOptions_i takes integer k, integer DamageOptions returns nothing
local integer d=DamageOptions
set dostruct(k).value=d
if (d>=8192) then
set d=d-8192
endif
if (d>=4096) then
set d=d-4096
endif
if d>=2048 then
set dostruct(k).ally_fc=cs_dopt_Ally_fc
set d=d-2048
endif
if d>=1024 then
set dostruct(k).ign = cs_dopt_IgnoreUtype
set d=d-1024
endif
if d>=512 then
set dostruct(k).dfab3=cs_dopt_dfab3
set dostruct(k).dfab3_fc=cs_dopt_dfab3_fc
set d=d-512
endif
if d>=256 then
set dostruct(k).dfab2=cs_dopt_dfab2
set dostruct(k).dfab2_fc=cs_dopt_dfab2_fc
set d=d-256
endif
if d>=128 then
set dostruct(k).dfab1=cs_dopt_dfab1
set dostruct(k).dfab1_fc=cs_dopt_dfab1_fc
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
set dostruct(k).allied=cs_dopt_EnemyAlly //[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
set dostruct(k).only=cs_dopt_OnlyUtype
set d=d-4
endif
if d >= 2 then
set dostruct(k).excp= cs_dopt_ExceptionUtype
set dostruct(k).excf= cs_dopt_ExceptionFct
set d=d-2
endif
if d >= 1 then
set dostruct(k).attt=cs_dopt_Atype
set dostruct(k).dmgt=cs_dopt_Dtype
endif
endfunction
// inline friendly:)
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 =integer(dostruct.create())
call SetDamageOptions_i(n,DamageOptions)
return n
endfunction
function DestroyDamageOptions takes integer id returns nothing
call dostruct(id).destroy()
endfunction
function LoadDamageOptions takes integer id returns integer
local integer opt=dostruct(id).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 cs_dopt_Ally_fc = dostruct(id).ally_fc
set v=v-2028
endif
if v>=1024 then
set cs_dopt_IgnoreUtype = dostruct(id).ign
set v=v-1024
endif
if v>=512 then
set cs_dopt_dfab3 =dostruct(id).dfab3
set cs_dopt_dfab3_fc=dostruct(id).dfab3_fc
set v=v-512
endif
if v>=256 then
set cs_dopt_dfab2 =dostruct(id).dfab2
set cs_dopt_dfab2_fc=dostruct(id).dfab2_fc
set v=v-256
endif
if v>=128 then
set cs_dopt_dfab1 =dostruct(id).dfab1
set cs_dopt_dfab1_fc=dostruct(id).dfab1_fc
set v=v-128
endif
if v >= 64 then
set v=v-64
set cs_dopt_EnemyAlly= dostruct(id).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
if v >= 4 then
set cs_dopt_OnlyUtype = dostruct(id).only
set v=v-4
endif
if v >= 2 then
set cs_dopt_ExceptionUtype= dostruct(id).excp
set cs_dopt_ExceptionFct= dostruct(id).excf
set v=v-2
endif
if v >= 1 then
set cs_dopt_Atype= dostruct(id).attt
set cs_dopt_Dtype= dostruct(id).dmgt
endif
return opt
endfunction
//==================================================================================================
function IsDestructableTree_withcs takes destructable d returns boolean
local boolean b
local boolean i=IsDestructableInvulnerable(d)
call SetUnitX(cs_dmg_caster,GetWidgetX(d))
call SetUnitY(cs_dmg_caster,GetWidgetY(d))
if i then
call SetDestructableInvulnerable(d,false)
endif
call UnitAddAbility(cs_dmg_caster,cs_DamageTreeDetectorId)
set b=(IssueTargetOrder(cs_dmg_caster,"eattree",d))
call UnitRemoveAbility(cs_dmg_caster,cs_DamageTreeDetectorId)
if i then
call SetDestructableInvulnerable(d,true)
endif
return b
endfunction
function IsDestructableTree takes destructable d returns boolean
local string k=I2S(GetDestructableTypeId(d))
local boolean b
if HaveStoredBoolean(cs_cache,"trees",k) then
set b=GetStoredBoolean(cs_cache,"trees",k)
return b
else
set b=IsDestructableTree_withcs(d)
call StoreBoolean(cs_cache,"trees",k,b)
endif
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=NewGroup()
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 ReleaseGroup(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=NewGroup()
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 (cs_dopt_EnemyAlly==2) then
set b=Condition(function CasterAOE_IsFilterAlly)
elseif (cs_dopt_EnemyAlly==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
call SetUnitOwner(cs_dmg_caster,hurter,false)
call DamageUnitGroupEx(cs_dmg_caster,damage,targetgroup,0)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
endfunction
//====================================================================================================================================================================
function DamageUnitsInAOE takes player hurter, real damage, real x, real y, real radius, boolean affectallied returns nothing
call SetUnitOwner(cs_dmg_caster,hurter,false)
call DamageUnitsInAOEEx(cs_dmg_caster,damage,x,y,radius,affectallied,0)
call SetUnitOwner(cs_dmg_caster,Player(15),false)
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 = NewTimer()
local real next = 0
local integer a = 0
local group inrange = NewGroup()
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=cs_dopt_dfab1_fc
local real f2=cs_dopt_dfab2_fc
local real f3=cs_dopt_dfab3_fc
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_dopt_dfab1
endif
if f2!=1 then
set a2=cs_dopt_dfab2
endif
if f3!=1 then
set a3=cs_dopt_dfab3
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=cs_DefaultAttackType
endif
if udg_castervars[10]!=-1 then
set dmgT=ConvertDamageType(R2I(udg_castervars[10]))
else
set dmgT=cs_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(GetWidgetLife(picked)<=0.405) 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(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 ReleaseGroup(inrange)
call DestroyEffect(fx[0])
call TriggerSleepAction(2)
call RecicleCaster(fire)
call ReleaseTimer(t)
set inrange=null
set fire=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]=cs_dopt_EnemyAlly
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]=CS_H2I(cs_dopt_OnlyUtype)
set v=v-4
else
set udg_castervars[6]=-1
endif
if v >= 2 then
set udg_castervars[7]=CS_H2I(cs_dopt_ExceptionUtype)
set udg_castervars[8]=damage*cs_dopt_ExceptionFct
set v=v-2
else
set udg_castervars[7]=-1
set udg_castervars[8]=-1
endif
if v >= 1 then
set udg_castervars[9]= CS_H2I(cs_dopt_Atype)
set udg_castervars[10]= CS_H2I(cs_dopt_Dtype)
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, csprojectile k returns boolean
local boolean tounit = k.tounit
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=k.target
if (GetWidgetLife(tg)<=0.405) then
set tounit=false
set k.tounit=false
else
set x2=GetUnitX(tg)
set y2=GetUnitY(tg)
set z2=GetUnitFlyHeight(tg)+k.z2o
set n=k.N
if (n==0) then
//Using the counter prevents us to save z2,x2,y2 too much times and saves speed
set k.z2=z2
set k.x2=x2 // Backup stuff just in case
set k.y2=y2
elseif (n==25) then
set n=0
else
set n=n+1
endif
set k.N=n
endif
set tg=null
endif
if not(tounit) then
set z2=k.z2
set x2=k.x2
set y2=k.y2
endif
set g=Atan2(y2-y1,x2-x1)
call SetUnitFacing(m,g*bj_RADTODEG)
set v=k.speed
set d= v * cs_TIMER_CYCLE
set od=SquareRoot(Pow(x1-x2,2) + Pow(y1-y2,2))
if( od <=d )then
call SetUnitX(m,x2)
call SetUnitY(m,y2)
set done=true
else
call SetUnitX(m,x1+d*Cos(g))
call SetUnitY(m,y1+d*Sin(g))
endif
set g=k.acel
set time= od / v
set d=v
set v=(z2-z1+0.5*g*time*time)/time //z speed
if (GetUnitTypeId(m)==cs_CasterUnitId) then
call SetUnitAnimationByIndex(m,R2I(Atan2(v,d)* bj_RADTODEG)+90) //Thanks infrane!
endif
call SetUnitFlyHeight(m,z1+v*cs_TIMER_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
set k.done=true
set fx=k.fx
if (fx!=null) then
call SetUnitAnimationByIndex(m,91)
call DestroyEffect(fx)
set fx=null
endif
endif
return done
endfunction
interface csmissile
integer mtype=0
unit m //the missile
endinterface
globals
constant integer cs_TYPE_COLLISIONMISSILE=2
constant integer cs_TYPE_PROJECTILE=1
endglobals
struct cscollisionmissile extends csmissile
integer state //state of the collision missile
trigger t
triggeraction ac
real collision
real speed
real aspeed //angle speed
real f //facing of collisionmissile
real maxd
integer ttype=0 //target type
static constant integer ttype_widget=2
static constant integer ttype_point=1
static constant integer ttype_none=0
real tx //homing target x
real ty //homing target y
widget tw //homing target widget
boolean pfx=false //periodic fx mode
real pfx_current //current pfx (timer)
real pfx_dur //duration of a periodic effect
string pfx_path //path for the periodix fx
boolean new //Was it a new collision missile or must be recycled?
effect fx
integer tag=0 //custom tag for the user.
endstruct
function CollisionMissile_Destroyer takes unit m, cscollisionmissile k, trigger T returns nothing
local trigger tr = T
local triggeraction ta = k.ac
if (k.fx!=null) then
call DestroyEffect(k.fx)
endif
if (k.new) then
call ExplodeUnitBJ(m)
else
call RecicleCasterAfterCastEx(m,4,0,true)
endif
call TriggerRemoveAction(tr,ta)
//call TriggerRemoveAction(T,GetArrayTriggerAction(k,18)) //[18=triggeraction]
call k.destroy()
//call Hostage(CS_H2I(tr))
call DestroyTrigger(tr)
//call CleanAttachedVars(T)
//call DestroyTrigger(T)
set tr = null
set ta = null
endfunction
function GetTriggerCollisionMissile takes nothing returns unit
return s__csmissile_m[GetCSData(GetTriggeringTrigger()) ]
endfunction
function CollisionMissile_Move takes unit m, cscollisionmissile k returns boolean
local integer state= k.state
local boolean done
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
local trigger TTT
if (state==2) then
set TTT=k.t
call TriggerExecute(TTT)
set TTT=null
set k.state=3
return false
elseif (state==3) then
call CollisionMissile_Destroyer(m,k,k.t)
return true
else
if (state==1) then
call TriggerRegisterUnitInRange(k.t,m,k.collision,null)
set k.state=0
endif
set d=k.speed * cs_TIMER_CYCLE
set F=k.f
set asp=k.aspeed
set x=GetUnitX(m)
set y=GetUnitY(m)
if (asp!=0) then
set tt=k.ttype
if (tt==cscollisionmissile.ttype_point) or (tt==cscollisionmissile.ttype_widget ) then
if (tt==cscollisionmissile.ttype_point) then
set nx=k.tx
set ny=k.ty
set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * cs_TIMER_CYCLE)
else
set wd=k.tw
if (GetWidgetLife(wd)<=0.405) then
set k.ttype=cscollisionmissile.ttype_none
set nx=x+0.001
set ny=y+0.001
set F=F+ asp * cs_TIMER_CYCLE
else
set nx=GetWidgetX(wd)
set ny=GetWidgetY(wd)
set F=Angles_MoveAngleTowardsAngle(F,Atan2(ny-y,nx-x)*bj_RADTODEG, asp * cs_TIMER_CYCLE)
endif
set wd=null
endif
else
set F=F+ asp * cs_TIMER_CYCLE
endif
set k.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=k.maxd-d
set k.maxd=d
set done=(d<=0)
if (not done) then
if not(CS_MoveUnit(m,nx,ny)) then
set done=true
elseif (k.pfx) then
set F= k.pfx_current+cs_TIMER_CYCLE
if (F>=k.pfx_dur) then
call DestroyEffect(AddSpecialEffectTarget(k.pfx_path, m, "origin" ))
set k.pfx_current=0.
else
set k.pfx_current=F
endif
endif
endif
endif
if done then
call DisableTrigger(k.t)
call DestroyEffect(k.fx)
set k.fx=null
set k.state=2
return false
endif
return false
endfunction
function CasterSystemMovementTimer takes nothing returns nothing
local timer ti
local integer n=cs_missilecount
local integer i=1
local unit p
local csmissile k
loop
exitwhen (i>n)
set k=cs_missiles[i]
if (k.mtype==cs_TYPE_COLLISIONMISSILE) then
set p=k.m
if not(CollisionMissile_Move(p,k)) then
set i=i+1
else
set cs_missiles[i]=cs_missiles[n]
set n=n-1
endif
elseif (k.mtype==cs_TYPE_PROJECTILE) then
set p=k.m
if not(UnitMoveToAsProjectileAnySpeed_Move(p,k )) then
set i=i+1
else
set cs_missiles[i]=cs_missiles[n]
set n=n-1
endif
else
set i=i+1
call BJDebugMsg("Caster System: Unexpected Error (1) Wrong Array:"+I2S(k)+" ; "+I2S(k.mtype))
endif
endloop
if (n==0) then
call PauseTimer(cs_movementtimer)
set cs_movementtimer_active=false
endif
set cs_missilecount=n
set p=null
endfunction
struct csprojectile extends csmissile
boolean tounit //Is it directed towards a unit?
unit target //if so, what target?
real z2
real x2
real y2
real speed
real acel
boolean done=false
effect fx
real z2o // offset for z2, useful for flyers
integer N=0
endstruct
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 csprojectile k
set km=I2S(CS_H2I(m))
set k=GetTableInt("MOVEMENT_TABLES",km)
if (k>0) then
set k.done=true
endif
set k=csprojectile.create()
set k.m=m
call StoreInteger(cs_cache,"MOVEMENT_TABLES",km,k)
set cs_missilecount=cs_missilecount+1
set cs_missiles[cs_missilecount]=k
if (not cs_movementtimer_active) then
call TimerStart(cs_movementtimer,cs_TIMER_CYCLE,true,function CasterSystemMovementTimer)
set cs_movementtimer_active=true
endif
set k.mtype=cs_TYPE_PROJECTILE
if (target!=null) then
set k.tounit=true
set k.target=target
set k.x2=GetUnitX(target)
set k.y2=GetUnitY(target)
set k.z2o=z2
else
set k.tounit=false
set k.x2=x2
set k.y2=y2
endif
set k.z2=z2
set k.speed=speed
set k.acel=arc*8000
if (fx!=null) then
set k.fx=fx
set fx=null
endif
loop
exitwhen k.done
call TriggerSleepAction(0)
endloop
call FlushStoredInteger(cs_cache,"MOVEMENT_TABLES",km)
call k.destroy()
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 (GetWidgetLife(target)<=0.405) 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 SetUnitX(m,x2)
call SetUnitY(m,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(cs_DefaultAttackType)
set udg_castervars[6]=CS_H2I(cs_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 cscollisionmissile k=GetUnitUserData(m)
if (k.fx!=null) then
call DestroyEffect(k.fx)
set k.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.
set k.state=2
call DisableTrigger(k.t)
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 cscollisionmissile k
local trigger R
local unit m
set k=cscollisionmissile.create()
if UseNewCaster then
set m=CreateCaster(dirangle,x,y)
set k.new=true
else
set m=GetACaster()
call SetUnitFacing(m,dirangle)
call SetUnitPosition(m,CS_SafeX(x),CS_SafeY(y))
set k.new=false
endif
set cs_missilecount=cs_missilecount+1
set cs_missiles[cs_missilecount]=k
if (not cs_movementtimer_active) then
call TimerStart(cs_movementtimer,cs_TIMER_CYCLE,true,function CasterSystemMovementTimer)
set cs_movementtimer_active=true
endif
call SetUnitUserData(m,k)
set k.mtype=cs_TYPE_COLLISIONMISSILE
set k.speed=speed
set k.aspeed=AngleSpeed
set k.f=dirangle
set k.maxd=MaxDist
call SetUnitFlyHeight(m,height,0)
set R=CreateTrigger()
set k.collision=Collision
set k.state=1
set k.t=R
call SetCSData(R,k)
set k.fx = AddSpecialEffectTarget(MissileModelPath,m,"origin")
set k.m=m
set k.ac=TriggerAddAction(R,OnImpact)
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
//! CollisionMissile_CreateLoc(MissileModelPath,loc,dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact) CollisionMissile_Create(MissileModelPath,GetLocationX(loc),GetLocationY(loc),dirangle,speed,AngleSpeed,MaxDist,height,UseNewCaster,Collision,OnImpact)
//=========================================================================================================================================================
function CollisionMissile_SetAngleSpeed takes unit m, real newAspeed returns nothing
local cscollisionmissile k=GetUnitUserData(m)
set k.aspeed=newAspeed
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetSpeed takes unit m, real newspeed returns nothing
local cscollisionmissile k=GetUnitUserData(m)
set k.speed=newspeed
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetTargetPoint takes unit m, real tx, real ty returns nothing
local cscollisionmissile k= GetUnitUserData(m)
set k.tx=tx
set k.ty=ty
set k.ttype=cscollisionmissile.ttype_point
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 cscollisionmissile k= GetUnitUserData(m)
set k.tw=Target
set k.ttype=cscollisionmissile.ttype_widget
endfunction
//=========================================================================================================================================================
function CollisionMissile_ForgetTarget takes unit m returns nothing
set cscollisionmissile(GetUnitUserData(m)).ttype=cscollisionmissile.ttype_none
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetDirAngle takes unit m, real f returns nothing
set cscollisionmissile(GetUnitUserData(m)).f=f
call SetUnitFacing(m,f)
endfunction
//=========================================================================================================================================================
function CollisionMissile_ResetMaxDist takes unit m, real maxdist returns nothing
set cscollisionmissile(GetUnitUserData(m)).maxd=maxdist
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 cscollisionmissile k= cscollisionmissile(GetUnitUserData(m))
set k.pfx=true
set k.pfx_path=fx
set k.pfx_dur=dur
set k.pfx_current=0.
endfunction
//=========================================================================================================================================================
function CollisionMissile_SetTag takes unit m, integer tag returns nothing
set cscollisionmissile(GetUnitUserData(m)).tag=tag
endfunction
//=========================================================================================================================================================
function CollisionMissile_GetTag takes unit m returns integer
return cscollisionmissile(GetUnitUserData(m)).tag
endfunction
//**************************************************************************************************
//*
//* Caster System Special Events:
//*
//*
//**************************************************************************************************
globals
private boolean eventhandlers_passives=false
private trigger events_probablytemp_learntrig=null
private triggeraction events_probablytemp_learntriga=null
endglobals
//==================================================================================================
// Event: OnAbilityLearn
//
function Event_OnLearn1 takes nothing returns nothing
local integer s=GetLearnedSkill()
local string k=I2S(s)
if HaveStoredString( cs_cache, "events_onlearn",k) then
call ExecuteFunc( GetStoredString( cs_cache, "events_onlearn",k) )
endif
endfunction
function Event_OnLearn2 takes nothing returns nothing
local integer s=GetLearnedSkill()
local string k=I2S(s)
if HaveStoredString( cs_cache, "events_onlearn",k) then
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(GetTriggerUnit()))
call StoreInteger(cs_cache,"events_variables","current",s)
call ExecuteFunc( GetStoredString( cs_cache, "events_onlearn",k) )
endif
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
set events_probablytemp_learntrig=t
set events_probablytemp_learntriga=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
if (not HaveStoredInteger(cs_cache,"eventhandlers","learn")) then
call InitLearnEvent(cs_cache,1)
endif
call StoreString(cs_cache,"events_onlearn", I2S(abilid), funcname)
endfunction
//==================================================================================================
// Event: OnAbilityGet
//
globals
private unit acquiringunit
private integer acquiredabil
endglobals
function GetAbilityAcquiringUnit takes nothing returns unit
return acquiringunit
endfunction
function GetAcquiredAbilityId takes nothing returns integer
return acquiredabil
endfunction
function UnitAddAbility_ConsiderEvent takes unit whichUnit, integer abilid, integer level returns nothing
local string k=I2S(abilid)
call UnitAddAbility(whichUnit,abilid)
call SetUnitAbilityLevel(whichUnit,abilid,level)
if (HaveStoredString(cs_cache,"events_onlearn",k)) then
set acquiringunit = whichUnit
set acquiredabil = abilid
call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",k))
endif
endfunction
function Event_OnPassive_Browse takes unit u, string k returns nothing
local integer n=GetStoredInteger(cs_cache,"events_passives","n")
local integer un=0
local integer i=1
local integer s
loop
exitwhen (i>n)
set s=GetStoredInteger(cs_cache,"events_passives",I2S(i))
if (GetUnitAbilityLevel(u,s)>0) then
if (un==0) then
set un=1
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
else
set un=un+1
endif
call StoreInteger(cs_cache,"events_unit_passive"+I2S(un),k,s)
call StoreInteger(cs_cache,"events_variables","current",s)
call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",I2S(s)))
endif
set i=i+1
endloop
if (un==0) then
set un=-1
endif
call StoreInteger(cs_cache,"events_unit_passives",k,un)
endfunction
function Event_OnPassive_Do takes unit u, string k, integer n returns nothing
local integer i=1
local integer s
call StoreInteger(cs_cache,"events_variables","unit",CS_H2I(u))
loop
exitwhen (i>n)
set s=GetStoredInteger(cs_cache,"events_unit_passive"+I2S(i),k)
if (GetUnitAbilityLevel(u,s)>0) then
call StoreInteger(cs_cache,"events_variables","current",s)
call ExecuteFunc(GetStoredString(cs_cache,"events_onlearn",I2S(s)))
endif
set i=i+1
endloop
endfunction
function Event_OnPassive_EnterRect takes nothing returns nothing
local unit u=GetTriggerUnit()
local string k=I2S(GetUnitTypeId(u))
local integer n=GetStoredInteger(cs_cache,"events_unit_passives",k)
if (n>0) then
call Event_OnPassive_Do(u,k,n)
elseif (n==0) then
call Event_OnPassive_Browse(u,k)
endif
set u=null
endfunction
function Event_OnPassive_NoCasters takes nothing returns boolean
return (GetUnitTypeId(GetTriggerUnit())!=cs_CasterUnitId)
endfunction
function Event_OnPassive_InitEnum takes nothing returns nothing
local trigger t
local integer n=GetStoredInteger(cs_cache,"events_passives","n")
local integer i=1
local integer array p
local string array s
local unit u
local group a=NewGroup()
local boolean saved
call ReleaseTimer(GetExpiredTimer())
loop
exitwhen (i>n)
set p[i]=GetStoredInteger(cs_cache,"events_passives",I2S(i))
set s[i]=GetStoredString(cs_cache,"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(cs_cache,"events_variables","unit",CS_H2I(u))
endif
call StoreInteger(cs_cache,"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 ReleaseGroup(a)
set t=null
set a=null
endfunction
function InitPassiveEvent takes nothing returns nothing
local trigger t
call TimerStart(NewTimer(),0,false,function Event_OnPassive_InitEnum)
set eventhandlers_passives=true
if (not HaveStoredInteger(cs_cache,"eventhandlers","learn")) then
call InitLearnEvent(cs_cache,2)
else
set t=events_probablytemp_learntrig
call TriggerRemoveAction(t,events_probablytemp_learntriga)
call TriggerAddAction(t, function Event_OnLearn2)
call StoreInteger(cs_cache,"eventhandlers","learn",2)
set t=null
endif
endfunction
function OnAbilityGet takes integer abilid, string funcname returns nothing
local integer n=GetStoredInteger(cs_cache,"events_passives","n")+1
if (not eventhandlers_passives) then
call InitPassiveEvent()
endif
call StoreString( cs_cache,"events_onlearn", I2S(abilid), funcname)
call StoreInteger(cs_cache,"events_passives","n",n)
call StoreInteger(cs_cache,"events_passives",I2S(n),abilid)
endfunction
//==================================================================================================
// Event: OnAbilityEffect
//
function Event_OnEffect takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
if HaveStoredString(cs_cache, "events_oneffect",k) then
call ExecuteFunc( GetStoredString(cs_cache, "events_oneffect",k))
endif
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
if (not HaveStoredInteger(cs_cache,"eventhandlers","effect")) then
call InitEffectEvent(cs_cache)
endif
call StoreString(cs_cache,"events_oneffect",I2S(abilid),funcname)
endfunction
//==================================================================================================
// Event: OnAbilityCast
//
function Event_OnCast takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
if HaveStoredString(cs_cache, "events_oncast",k) then
call ExecuteFunc( GetStoredString(cs_cache, "events_oncast",k))
endif
endfunction
function InitCastEvent takes nothing 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(cs_cache,"eventhandlers","cast",1)
set t=null
endfunction
function OnAbilityPreCast takes integer abilid, string funcname returns nothing
if (not HaveStoredInteger(cs_cache,"eventhandlers","cast")) then
call InitCastEvent()
endif
call StoreString(cs_cache,"events_oncast",I2S(abilid),funcname)
endfunction
//==================================================================================================
// Event: OnAbilityEndCast
//
function Event_OnEndCast takes nothing returns nothing
local string k=I2S(GetSpellAbilityId())
if HaveStoredString(cs_cache, "events_onendcast",k) then
call ExecuteFunc( GetStoredString(cs_cache, "events_onendcast",k))
endif
endfunction
function InitEndCastEvent takes nothing 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(cs_cache,"eventhandlers","endcast",1)
set t=null
endfunction
function OnAbilityEndCast takes integer abilid, string funcname returns nothing
if (not HaveStoredInteger(cs_cache,"eventhandlers","endcast")) then
call InitEndCastEvent()
endif
call StoreString(cs_cache,"events_onendcast",I2S(abilid),funcname)
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.
//
globals
private group CSItemStorage_gr=null
endglobals
//If your map got more than 8191 items, you are crazy.
private struct itemholder
unit s
item it
endstruct
function CS_HideItem takes item i returns integer
local unit s
local group gr=CSItemStorage_gr
local itemholder r
if (gr==null) then
set gr=NewGroup()
set CSItemStorage_gr=gr
endif
set s=FirstOfGroup(gr)
if (s==null) then
set s=CreateCaster(0,0,0)
call UnitAddAbility(s,cs_DummyInventory_Id)
if (UnitInventorySize(s)<bj_MAX_INVENTORY) then
call BJDebugMsg("CASTER SYSTEM ERROR: Please use a correct ability for cs_DummyInventory_Id ")
loop //crash the thread
endloop
endif
call GroupAddUnit(gr,s)
endif
call UnitAddItem(s,i)
set r=itemholder.create()
set r.it=i
set r.s=s
if(UnitInventorySize(s)==UnitInventoryCount(s)) then
call GroupRemoveUnit(gr,s)
endif
set s=null
set gr=null
return integer(r)
endfunction
//===============================
// Restores an item
//
globals
private item returnitem
endglobals
function CS_RestoreItem takes integer hiddenindex, real x, real y returns item
local group gr=CSItemStorage_gr
local itemholder r=itemholder(hiddenindex)
local unit s=r.s
local item i=r.it
local integer c
call r.destroy()
call UnitRemoveItem(s,i)
set c=UnitInventoryCount(s)
if (c==0) then
call UnitRemoveAbility(s,cs_DummyInventory_Id)
call GroupRemoveUnit(gr,s)
call ExplodeUnitBJ(s)
else
call GroupAddUnit(gr,s)
endif
call SetItemPosition(i,x,y)
set returnitem=i
set i=null
set s=null
return returnitem
endfunction
function CS_RestoreItemLoc takes integer hiddenindex, location loc returns item
return CS_RestoreItem(hiddenindex,GetLocationX(loc),GetLocationY(loc))
endfunction
//=============================================================================================================
// More convenient than CS_HideItem not compatible with CS_HideItem / CS_RestoreItem(loc)
//
function CS_SetItemVisible takes item it, boolean flag returns nothing
local itemholder r
local unit s
local string k=I2S(CS_H2I(it))
local group gr
local integer x
if (flag) then
if (HaveStoredInteger(cs_cache,"CSItemStorage",k )) then
//DO SHOW:
set r=itemholder(GetStoredInteger(cs_cache,"CSItemStorage",k))
set s=r.s
set gr=CSItemStorage_gr
if (gr==null) then
set gr=NewGroup()
set CSItemStorage_gr=gr
endif
call FlushStoredInteger(cs_cache,"CSItemStorage",k)
call UnitRemoveItem(s,it)
call SetItemVisible(it,true) //Just in case
set x=GetUnitUserData(s)-1
if (x==0) then
call UnitRemoveAbility(s,cs_DummyInventory_Id)
call GroupRemoveUnit(gr,s)
call ExplodeUnitBJ(s)
else
call SetUnitUserData(s,x)
call GroupAddUnit(gr,s)
endif
call r.destroy()
set s=null
set gr=null
else //What? Trying to show an item that was not hidden using this method?
endif
elseif (HaveStoredInteger(cs_cache,"CSItemStorage",k )) then
//What? Trying to hide an item that was already hidden by this method?
else //DO HIDE:
set gr=CSItemStorage_gr
if (gr==null) then
set gr=NewGroup()
set CSItemStorage_gr=gr
endif
set s=FirstOfGroup(gr)
if (s==null) then
set s=CreateCaster(0,0,0)
call UnitAddAbility(s,cs_DummyInventory_Id)
if (UnitInventorySize(s)<bj_MAX_INVENTORY) then
call BJDebugMsg("CASTER SYSTEM ERROR: Please use a correct ability for cs_DummyInventory_Id ")
set x=x
endif
call SetUnitUserData(s,0) //UserData will now hold total items
call GroupAddUnit(gr,s)
endif
call UnitAddItem(s,it)
set r=itemholder.create()
set r.s=s
set r.it=it
call StoreInteger(cs_cache,"CSItemStorage",k,integer(r))
set x=GetUnitUserData(s)+1
call SetUnitUserData(s,x)
if (x==bj_MAX_INVENTORY) then
call GroupRemoveUnit(gr,s)
endif
set s=null
set gr=null
endif
endfunction
function CS_IsItemVisible takes item it returns boolean
return not HaveStoredInteger(cs_cache,"CSItemStorage",I2S(CS_H2I(it)) )
endfunction
//=============================================================================================================
// Obsolette functions: (Left for compatibility)
//
constant function WaterDetectorId takes nothing returns integer
return 'Asb2'
endfunction
function SpellEffectModelPath takes integer abilityid, effecttype t returns string
return GetAbilityEffectById(abilityid,t, 0)
endfunction
constant function Caster_DefaultAttackType takes nothing returns attacktype
return cs_DefaultAttackType
endfunction
constant function Caster_DefaultDamageType takes nothing returns damagetype
return cs_DefaultDamageType
endfunction
constant function Caster_UnitId takes nothing returns integer
return cs_CasterUnitId
endfunction
constant function DamageTreeDetectorId takes nothing returns integer
return cs_DamageTreeDetectorId
endfunction
constant function ChangeableFlyingHeightAllowerId takes nothing returns integer
return cs_FlyingHeightHack
endfunction
constant function CS_MaxCollisionSize takes nothing returns real
return cs_MaxUnitCollisionSize
endfunction
constant function CS_Cycle takes nothing returns real
return cs_TIMER_CYCLE
endfunction
constant function CS_InventoryId takes nothing returns integer
return cs_DummyInventory_Id
endfunction
constant function CS_RectLimitOffSet takes nothing returns real
return cs_RectLimitOffSet
endfunction
function CS_IsUnitVisible takes unit u, player p returns boolean
return IsUnitVisible(u,p)
endfunction
endlibrary
//TESH.scrollpos=99
//TESH.alwaysfold=0
library CSDamagers initializer init requires CasterSystem, CSData, TimerUtils
//*************************************************************************************
//* CSDamagers 15.3
//* ---------------
//* Rebuilt from scratch since 15.1, now they use CSData instead of CSCache
//*
//* A DamagerGroup is a bunch of 'damagers', only that it does not matter how many
//* 'damagers' are in range of the target unit, it is only affected by the damage once.
//*
//* A damager is a single special effect that every once in a while causes damage to
//* nearby units, these things are MUI, dynamic and can have expiration times.
//*
//*
//**************************************************************************************
//======================================================================================
globals
private constant real EPSILON=0.000001
endglobals
private keyword damagerdata
private struct data
boolean expired=false
boolean end=false
unit hurter
real damage
real area
integer DamageOptions
boolean trees=false
boolean selfdestruct=false
damagerdata damagers=0
timer thetimer
timer lifespan=null
endstruct
globals
private group damagerflag
endglobals
private struct damagerdata
unit u
effect fx
timer lifespan
integer abil=0
data parent
damagerdata prev=0
damagerdata next=0
method onDestroy takes nothing returns nothing
call GroupRemoveUnit(damagerflag, this.u)
if (.prev==this) then
set .parent.damagers=0
else
if(.parent.damagers==this) then
set .parent.damagers=.prev
endif
set .prev.next=.next
set .next.prev=.prev
endif
call ReleaseTimer(.lifespan)
if(this.abil!=0) then
call UnitRemoveAbility(this.u, this.abil)
endif
call RecicleCasterAfterCastEx(this.u,4,0,false)
call DestroyEffect(.fx)
endmethod
endstruct
//============================================================================================================
globals
private group enumgroup
private group loggroup
private boolexpr procfilter
private real radius
private real centerx
private real centery
private unit array inrange
private integer an
endglobals
private function processUnitsInRange takes nothing returns boolean
local unit e=GetFilterUnit()
if( IsUnitInRangeXY(e,centerx,centery,radius) and not IsUnitInGroup(e, loggroup)) then
call GroupAddUnit(loggroup,e)
set inrange[an]=e
set an=an+1
endif
set e=null
return false
endfunction
private function expire takes nothing returns nothing
local data d=data(GetCSData(GetExpiredTimer()) )
local damagerdata p=d.damagers
local damagerdata q
local integer do1
local real x
set d.expired=true
set an=0
if(p!=0) then
set q=p
loop
set centerx=GetUnitX(q.u)
set centery=GetUnitY(q.u)
set radius=d.area
if d.trees then
call DamageTreesInCircle(centerx,centery,radius)
endif
call GroupEnumUnitsInRange(enumgroup, centerx,centery, radius+cs_MaxUnitCollisionSize, procfilter)
exitwhen (q.next==p)
set q=q.next
endloop
endif
if(an!=0) then
set do1=LoadDamageOptions(d.DamageOptions)
loop
exitwhen (an==0)
set an=an-1
set x=GetDamageFactorByOptions(d.hurter,inrange[an],do1)
if (x>=EPSILON) or (x<=-EPSILON) then
call UnitDamageTarget(d.hurter,inrange[an],d.damage*x,true,false,null,null,null)
endif
endloop
endif
call GroupClear(loggroup)
set d.expired=false
if(d.end or (d.selfdestruct and (p==0))) then
call DamagerGroup_Destroy.evaluate(GetExpiredTimer())
endif
endfunction
private function damagerExpires takes nothing returns nothing
call damagerdata(GetCSData(GetExpiredTimer() ) ).destroy()
endfunction
private function endOfDamagerGroup takes nothing returns nothing
local data d=data(GetCSData(GetExpiredTimer() ) )
call DamagerGroup_Destroy.evaluate(d.thetimer)
endfunction
//================================================================================================================================
//
//
function DamagerGroup_Create takes unit hurter, real damage, real damageperiod, real area, integer DamageOptions returns timer
local timer t=NewTimer()
local data d=data.create()
if IsDamageOptionIncluded(DamageOptions, DamageTrees() ) then
set d.trees=true
endif
set d.DamageOptions=CreateDamageOptions(DamageOptions)
set d.thetimer=t
set d.hurter=hurter
set d.damage=damage
set d.area=area
call SetCSData(t, integer(d) )
call TimerStart(t,damageperiod,true,function expire)
//since we use CSSafety, no need to null the timer...
return t
endfunction
function DamagerGroup_Destroy takes timer DamagerGroup returns nothing
local data d=data( GetCSData(DamagerGroup) )
if (d.expired) then
set d.end=true
return
endif
loop
exitwhen (d.damagers==0)
call d.damagers.destroy()
endloop
call ReleaseTimer(DamagerGroup)
call DestroyDamageOptions(d.DamageOptions)
if (d.lifespan!=null) then
call ReleaseTimer(d.lifespan)
endif
call d.destroy()
endfunction
//at least it is inlineable...
function DamagerGroup_AutoDestruct takes timer DamagerGroup, boolean auto returns nothing
set data( GetCSData(DamagerGroup) ).selfdestruct=auto
endfunction
function DamagerGroup_SetLifeSpan takes timer DamagerGroup, real LifeSpan returns nothing
local data d=data(GetCSData(DamagerGroup) )
if(d.lifespan==null) then
set d.lifespan=NewTimer()
call SetCSData(d.lifespan, integer(d) )
endif
call TimerStart(d.lifespan, LifeSpan, false, function endOfDamagerGroup)
endfunction
//
function DamagerGroup_Update takes timer DamagerGroup, unit hurter, real damage, real damageperiod, real area, integer DamageOptions returns nothing
local data d=data(GetCSData(DamagerGroup) )
set d.hurter=hurter
set d.damage=damage
call TimerStart(DamagerGroup,damageperiod,true,function expire)
call SetDamageOptions(d.DamageOptions,DamageOptions)
endfunction
function DamagerGroup_AddDamager takes timer DamagerGroup, string modelpath, real x, real y, real LifeSpan returns unit
local unit c=GetACaster()
local timer t=NewTimer()
local damagerdata dt=damagerdata.create()
local data d=data( GetCSData(DamagerGroup) )
set dt.u=c
call SetUnitUserData(c, integer(dt) )
set dt.lifespan=t
set dt.fx=AddSpecialEffectTarget(modelpath,c,"origin")
set dt.parent=d
if(d.damagers==0)then
set d.damagers=dt
set dt.next=dt
set dt.prev=dt
else
//brain hurts.
set dt.next=d.damagers
set dt.prev=d.damagers.prev
set d.damagers.prev.next=dt
set d.damagers.prev=dt
set d.damagers=dt
endif
call SetUnitX(c,x)
call SetUnitY(c,y)
call SetCSData(t, integer(dt) )
if (LifeSpan>=EPSILON) then
call TimerStart(t,LifeSpan,false, function damagerExpires)
endif
call SetUnitOwner(c,GetOwningPlayer(d.hurter),true)
call GroupAddUnit(damagerflag,c)
set c=null
return dt.u
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
//*************************************************
//* Damager functions
//*
//*************************************************
function Damager_SetLifeSpan takes unit Damager, real lifespan returns nothing
local damagerdata dt
if (not IsUnitInGroup(Damager,damagerflag)) then
return
endif
set dt=damagerdata( GetUnitUserData(Damager) )
if (lifespan<EPSILON) then
call PauseTimer(dt.lifespan)
else
call TimerStart(dt.lifespan,lifespan,false,function damagerExpires)
endif
endfunction
function Damager_Remove takes unit Damager returns nothing
if (not IsUnitInGroup(Damager,damagerflag)) then
return
endif
call damagerdata( GetUnitUserData(Damager) ).destroy()
endfunction
function Damager_SetAbility takes unit Damager, integer abilid, integer l returns nothing
local damagerdata dt
if (not IsUnitInGroup(Damager,damagerflag)) then
return
endif
set dt=damagerdata( GetUnitUserData(Damager) )
if(dt.abil!=abilid) then
if(dt.abil!=0) then
call UnitRemoveAbility(Damager,dt.abil)
endif
call UnitAddAbility(Damager,abilid)
set dt.abil=abilid
endif
call SetUnitAbilityLevel(Damager,abilid,l)
endfunction
//========================================================================================
private function init takes nothing returns nothing
set loggroup=CreateGroup()
set enumgroup=CreateGroup()
set damagerflag=CreateGroup()
set procfilter=Condition(function processUnitsInRange)
endfunction
endlibrary
library_once TimerUtils initializer init
//*********************************************************************
//* TimerUtils (Blue flavor for 1.23b or later)
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//* limit, which means that if more than 408000 handle ids
//* are used in your map, TimerUtils might fail, this
//* value is quite big and it is much bigger than the
//* timer limit in Red flavor.
//*
//********************************************************************
//==================================================================================================
globals
private hashtable hasht //I <3 blizz
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
call SaveInteger(hasht,0, GetHandleId(t), value)
endfunction
function GetTimerData takes timer t returns integer
return LoadInteger(hasht, 0, GetHandleId(t))
endfunction
//==========================================================================================
globals
private timer array tT
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
set tT[0]=CreateTimer()
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
set hasht = InitHashtable()
endfunction
endlibrary
library GroupUtils
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This library is a simple implementation of a stack for groups that need to
//* be in the user's control for greater than an instant of time. Additionally,
//* this library provides a single, global group variable for use with user-end
//* enumerations. It is important to note that users should not be calling
//* DestroyGroup() on the global group, since then it may not exist for when it
//* it is next needed.
//*
//* The group stack removes the need for destroying groups and replaces it with
//* a recycling method.
//* function NewGroup takes nothing returns group
//* function ReleaseGroup takes group g returns boolean
//* function GroupRefresh takes group g returns nothing
//*
//* NewGroup grabs a currently unused group from the stack or creates one if the
//* stack is empty. You can use this group however you'd like, but always
//* remember to call ReleaseGroup on it when you are done with it. If you don't
//* release it, it will 'leak' and your stack may eventually overflow if you
//* keep doing that.
//*
//* GroupRefresh cleans a group of any shadow references which may be clogging
//* its hash table. If you remove a unit from the game who is a member of a unit
//* group, it will 'effectively' remove the unit from the group, but leave a
//* shadow in its place. Calling GroupRefresh on a group will clean up any
//* shadow references that may exist within it.
//*
globals
//* Group for use with all instant enumerations
group ENUM_GROUP = CreateGroup()
//* Temporary references for GroupRefresh
private boolean Flag = false
private group Refr = null
//* Assorted constants
private constant integer MAX_HANDLE_COUNT = 408000
private constant integer MIN_HANDLE_ID = 0x100000
//* Arrays and counter for the group stack
private group array Groups
private integer array Status[MAX_HANDLE_COUNT]
private integer Count = 0
endglobals
private function H2I takes handle h returns integer
return GetHandleId(h)
endfunction
private function AddEx takes nothing returns nothing
if Flag then
call GroupClear(Refr)
set Flag = false
endif
call GroupAddUnit(Refr, GetEnumUnit())
endfunction
function GroupRefresh takes group g returns nothing
set Flag = true
set Refr = g
call ForGroup(Refr, function AddEx)
if Flag then
call GroupClear(g)
endif
endfunction
function NewGroup takes nothing returns group
if Count == 0 then
set Groups[0] = CreateGroup()
else
set Count = Count - 1
endif
set Status[H2I(Groups[Count])-MIN_HANDLE_ID] = 1
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer stat = Status[H2I(g)-MIN_HANDLE_ID]
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Null groups cannot be released")
return false
elseif stat == 0 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Group not part of stack")
return false
elseif stat == 2 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Groups cannot be multiply released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+" Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
else
call GroupClear(g)
set Groups[Count] = g
set Count = Count + 1
set Status[H2I(g)-MIN_HANDLE_ID] = 2
endif
return true
endfunction
endlibrary
// Old CSCache has been killed by the latest patch. It is unfortunately simply possible to port CSCache to
// the new hashtable functions.
//
// maps using CSCache will have to migrate, manually to something else, it should be easy to migrate to CSSafeCache + structs, yet not that easy.
//*****************************************************
//* As of 15.3, CS does not need CSSafety, it will
//* instead need TimerUtils and GroupUtils, this proxy
//* library is included if you still have stuff requiring
//* CSSafety in your map, so you can make it compatible
//* with Timer/GroupUtils
//*
library_once CSSafety requires TimerUtils, GroupUtils
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library main initializer main_init needs const, messages, helper, board
globals
public unit owner = null
public group shamans = CreateGroup()
public group heros = CreateGroup()
public group druids = CreateGroup()
public unit array hero
public integer number_of_shamans = 0
public integer number_of_druids = 0
public force team1 = CreateForce()
public force team2 = CreateForce()
private constant string owner_effect_path = "Doodads\\Cinematic\\EyeOfSargeras\\EyeOfSargeras.mdl"
private constant string owner_atachment = "origin"
private effect owner_effect = null
//private multiboard board = null
//private multiboarditem mbi_score_shamans
private integer score_shamans = 0
//private multiboarditem mbi_score_druids
private integer score_druids = 0
public constant integer score_limit = 600
private unit array revive_stone
private boolean array allowed_to_revive
//private event score_event = null
private real score_dt = 1.0
public integer array kills
endglobals
function end_game takes integer team returns nothing
local integer i = 0
call ClearTextMessages()
call messageDur("|cffffcc00##################################|r", 60.0)
if team == 1 then
call messageDur("|cffffcc00The Shamans have won the game!|r", 60.0)
else
call messageDur("|cffffcc00The Druids have won the game!|r", 60.0)
endif
call PauseGame(true)
call PolledWait(60.0)
call PauseGame(false)
loop
if team == 1 then
if i < 6 then
call CustomVictoryBJ( Player(i), true, true )
else
call CustomDefeatBJ( Player(i), "You have lost!" )
endif
else
if i >= 6 then
call CustomVictoryBJ( Player(i), true, true )
else
call CustomDefeatBJ( Player(i), "You have lost!" )
endif
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
endfunction
function set_owner takes unit new_owner returns nothing
local integer old_owner_player_id = GetPlayerId(GetOwningPlayer(owner))
local integer new_owner_player_id = GetPlayerId(GetOwningPlayer(new_owner))
local unit u = hero[new_owner_player_id]
local integer i = 0
if owner_effect != null then
call DestroyEffect(owner_effect)
call SetUnitMoveSpeed(owner, GetUnitDefaultMoveSpeed(owner))
endif
//Sichtbarkeit
loop
if ((old_owner_player_id < 6) and (i >= 6)) or ((old_owner_player_id > 5) and (i <= 5)) then
call SetPlayerAlliance(GetOwningPlayer(owner), Player(i), ALLIANCE_SHARED_VISION, false)
endif
call SetPlayerAlliance(GetOwningPlayer(new_owner), Player(i), ALLIANCE_SHARED_VISION, true)
//---
set i = i + 1
exitwhen i >= 12
endloop
set owner = u
set owner_effect = AddSpecialEffectTarget(owner_effect_path, u, owner_atachment)
call SetUnitMoveSpeed(owner, GetUnitDefaultMoveSpeed(owner) / 2)
call board_update_set_owner(GetPlayerId(GetOwningPlayer(new_owner)))
set score_dt = 1.0
endfunction
function hero_killed takes nothing returns nothing
local integer i = GetPlayerId(GetOwningPlayer(GetKillingUnit()))
if IsUnitType( GetDyingUnit(), UNIT_TYPE_HERO ) then
call message_kill( GetKillingUnit(), GetDyingUnit())
set kills[i] = kills[i] + 1
call board_update_kills(i, kills[i])
if GetDyingUnit() == owner then
call set_owner(GetKillingUnit())
endif
endif
endfunction
function revive_stone_selected takes nothing returns nothing
local integer player_id = GetPlayerId(GetTriggerPlayer())
local unit u = hero[player_id]
local unit stone = GetTriggerUnit()
local real x = GetUnitX(stone)
local real y = GetUnitY(stone)
if GetUnitTypeId(stone) == const.ut_revive_stone then
set revive_stone[player_id] = stone
if allowed_to_revive[player_id] then
if IsUnitDeadBJ(u) then
//revive
set revive_stone[player_id] = null
call ReviveHero(u, x,y , true)
call SetUnitAnimation(stone, "Stand Alternate")
//call PanCameraToTimedForPlayer(GetOwningPlayer(u), x,y, 0.0)
if GetLocalPlayer() == Player(player_id) then
call ClearSelection()
call SelectUnit(u,true)
endif
call SetUnitState(u,UNIT_STATE_MANA, GetUnitState(u,UNIT_STATE_MAX_MANA))
endif
endif
endif
set u = null
set stone = null
endfunction
function periodic_gold takes nothing returns nothing
local integer i = 0
local integer number_of_players = number_of_shamans + number_of_druids
local integer gold_base = 2 * number_of_players
local integer gold_bonus = 1 * number_of_players
local integer xp_base = 6 * number_of_players
local integer xp_bonus = 3 * number_of_players
local integer gold
local integer xp
loop
if hero[i] != null then
if i <= 5 then
if GetPlayerId(GetOwningPlayer(owner)) <= 5 then
set gold = gold_base
set xp = xp_base
else
set gold = gold_base + gold_bonus
set xp = xp_base + xp_bonus
endif
call AdjustPlayerStateBJ(gold / number_of_shamans, Player(i), PLAYER_STATE_RESOURCE_GOLD)
call AddHeroXP(hero[i], xp / number_of_shamans, true)
else
if GetPlayerId(GetOwningPlayer(owner)) <= 5 then
set gold = gold_base + gold_bonus
set xp = xp_base + xp_bonus
else
set gold = gold_base
set xp = xp_base
endif
call AdjustPlayerStateBJ(gold / number_of_druids, Player(i), PLAYER_STATE_RESOURCE_GOLD)
call AddHeroXP(hero[i], xp / number_of_druids, true)
endif
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
endfunction
private function score_dt_updater takes nothing returns nothing
set score_dt = score_dt * 0.99
//call message(R2S(score_dt))
endfunction
private function score takes nothing returns nothing
local timer t = GetExpiredTimer()
if IsUnitAliveBJ(owner) then
if GetPlayerId(GetOwningPlayer(owner)) < 6 then
set score_shamans = score_shamans + 1
//call MultiboardSetItemValue(mbi_score_shamans, I2S(score_shamans))
call board_update_score_shaman(score_shamans)
if score_shamans >= score_limit then
call DisableTrigger(GetTriggeringTrigger())
call end_game(1)
endif
else
set score_druids = score_druids + 1
//call MultiboardSetItemValue(mbi_score_druids, I2S(score_druids))
call board_update_score_druid(score_druids)
if score_druids >= score_limit then
call DisableTrigger(GetTriggeringTrigger())
call end_game(2)
endif
endif
endif
call TimerStart(t, score_dt, false, function score)
endfunction
private function player_leave_handler takes nothing returns nothing
local player leaver = GetTriggerPlayer()
local integer leaver_id = GetPlayerId(leaver)
local integer i = 0
local real dist = 99999
local real temp_dist
local integer next = 0
local integer xp
local integer gold
call message_left_game(leaver)
call board_update_player_left(leaver_id)
if hero[leaver_id] == owner then
//find the hero that is next to the leaver
loop
if i != leaver_id then
if hero[i] != null then
set temp_dist = get_unit_dist(hero[leaver_id], hero[i])
if temp_dist < dist then
set dist = temp_dist
set next = i
endif
endif
endif
//---
set i = i + 1
exitwhen i>=12
endloop
call set_owner(hero[i])
endif
//aus gruppen entfernen
call GroupRemoveUnit(heros, hero[leaver_id])
if leaver_id <= 5 then
call GroupRemoveUnit(shamans, hero[leaver_id])
set number_of_shamans = number_of_shamans - 1
else
call GroupRemoveUnit(druids, hero[leaver_id])
set number_of_druids = number_of_druids - 1
endif
//XP und Gold aufteilen
set xp = GetHeroXP(hero[leaver_id])
set gold = GetPlayerState( leaver, PLAYER_STATE_GOLD_GATHERED)
if leaver_id <= 5 then
set i = 0
loop
if hero[i] != null then
call AddHeroXP(hero[i], xp / number_of_shamans, true )
call SetPlayerState( Player(i), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD) + gold / number_of_shamans)
endif
//---
set i = i + 1
exitwhen i >= 6
endloop
else
set i = 6
loop
if hero[i] != null then
call AddHeroXP(hero[i], xp / number_of_druids, true )
call SetPlayerState( Player(i), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD) + gold / number_of_druids)
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
endif
call RemoveUnit(hero[leaver_id])
set hero[leaver_id] = null
endfunction
private function ping takes nothing returns nothing
call PingMinimapEx( GetUnitX(owner), GetUnitY(owner), 1.0, 0,255,0, false)
endfunction
function main_init takes nothing returns nothing
local timer tim
local trigger t
local integer i
local unit u
local multiboarditem mbitem = null
//call FogMaskEnableOff()
//call FogEnableOff()
set i = 0
loop
//wiederbeleben
set allowed_to_revive[i] = false
set revive_stone[i] = null
//Beute einstellen
//call SetPlayerState(Player(i),PLAYER_STATE_GIVES_BOUNTY,1)
//Held erstellen
if GetPlayerSlotState( Player(i)) == PLAYER_SLOT_STATE_PLAYING then
if i>5 then
set u = CreateUnit(Player(i), const.unittype_druid , GetPlayerStartLocationX(Player(6)),GetPlayerStartLocationY(Player(6)), 90.0)
call AddUnitAnimationProperties(u, "alternate", false)
set number_of_druids = number_of_druids + 1
call GroupAddUnit(shamans, u)
else
set u = CreateUnit(Player(i), const.unittype_shaman, GetPlayerStartLocationX(Player(0)),GetPlayerStartLocationY(Player(0)), 90.0)
set number_of_shamans = number_of_shamans + 1
call GroupAddUnit(druids, u)
endif
call SelectUnitForPlayerSingle(u, Player(i))
call PanCameraToTimedForPlayer(Player(i), GetUnitX(u),GetUnitY(u), 0.0)
call GroupAddUnit(heros, u)
set hero[i] = u
set kills[i] = 0
endif
//team-variablen füllen
if i <=5 then
call ForceAddPlayer(team1, Player(i))
else
call ForceAddPlayer(team2, Player(i))
endif
//--
set i = i + 1
exitwhen i >= 12
endloop
set i = 0
loop
if GetPlayerSlotState( Player(i)) == PLAYER_SLOT_STATE_PLAYING then
//StartGold:
if i <= 5 then
call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD, const.startgold / number_of_shamans)
else
call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD, const.startgold / number_of_druids)
endif
endif
//---
set i = i + 1
exitwhen i>= 12
endloop
//Trigger für das Killen von Helden
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction(t, function hero_killed )
//Trigger für Geld bekommen
call TimerStart( CreateTimer(), 2.0, true, function periodic_gold )
//Player Leaves
set t = CreateTrigger()
set i = 0
loop
call TriggerRegisterPlayerEventLeave(t, Player(i))
//---
set i = i + 1
exitwhen i>=12
endloop
call TriggerAddAction(t, function player_leave_handler)
//Player selects a revive stone
set t = CreateTrigger()
set i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
//---
set i = i + 1
exitwhen i>=12
endloop
call TriggerAddAction(t, function revive_stone_selected)
//ping owner Trigger
set t = CreateTrigger()
call TriggerRegisterTimerEvent(t,0.5,true)
call TriggerAddAction(t, function ping)
//Wasser transparent machen
call SetWaterBaseColor(0,0,0,255)
call PolledWait(2.0)
//owner per zufall auswählen
call set_owner(GroupPickRandomUnit(heros))
call PolledWait(28.0)
//Score Trigger
set tim = NewTimer()
call TimerStart(tim, score_dt, false, function score)
//score_dt update trigger
//set t = CreateTrigger()
//call TriggerRegisterTimerEvent(t, 1.0, true)
//call TriggerAddAction(t, function score_dt_updater)
endfunction
endlibrary
//===========================================================================
function InitTrig_Main takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library board initializer init requires helper
globals
//icons :
private constant string icon_ball = "ReplaceableTextures\\CommandButtons\\BTNOrbOfVenom.blp"
private constant string icon_shaman = "ReplaceableTextures\\CommandButtons\\BTNShaman.blp"
private constant string icon_druid = "ReplaceableTextures\\CommandButtons\\BTNDruidOfTheClaw.blp"
private constant string string_shaman = "|cff801111Shamans|r"
private constant string string_druid = "|cff156C06Druids|r"
//Board 1: nur score + revive
private multiboard board1
private multiboarditem b1_ball_shaman
private multiboarditem b1_ball_druid
private multiboarditem b1_score_shaman
private multiboarditem b1_score_druid
private multiboarditem b1_revive_shaman
private multiboarditem b1_revive_druid
//Board 2: score + kills + revive
private multiboard board2
private multiboarditem b2_ball_shaman
private multiboarditem b2_ball_druid
private multiboarditem b2_score_shaman
private multiboarditem b2_score_druid
private multiboarditem b2_revive_shaman
private multiboarditem b2_revive_druid
private multiboarditem array b2_kills
private multiboarditem array b2_player
private integer player_mb_status
endglobals
public function update_score_shaman takes integer score returns nothing
call MultiboardSetItemValue(b1_score_shaman, I2S(main_score_limit - score))
call MultiboardSetItemValue(b2_score_shaman, I2S(main_score_limit - score))
endfunction
public function update_score_druid takes integer score returns nothing
call MultiboardSetItemValue(b1_score_druid, I2S(main_score_limit - score))
call MultiboardSetItemValue(b2_score_druid, I2S(main_score_limit - score))
endfunction
public function update_revive_shaman takes integer seconds returns nothing
endfunction
public function update_revive_druid takes integer seconds returns nothing
endfunction
public function update_player_dead takes integer p, boolean dead returns nothing
if dead then
//native MultiboardSetItemsValueColor takes multiboard lb, integer red, integer green, integer blue, integer alpha returns nothing
call MultiboardSetItemValueColor(b2_player[p], 200, 0, 0, 0)
else
call MultiboardSetItemValueColor(b2_player[p], 0, 200, 0, 0)
endif
endfunction
public function update_player_left takes integer p returns nothing
call MultiboardSetItemValueColor(b2_player[p], 100,100,100, 0)
endfunction
public function update_kills takes integer p, integer kills returns nothing
call MultiboardSetItemValue(b2_kills[p], I2S(kills))
endfunction
public function update_set_owner takes integer p returns nothing
if p <= 5 then
call MultiboardSetItemStyle(b1_ball_druid, false, false)
call MultiboardSetItemStyle(b1_ball_shaman, false, true)
call MultiboardSetItemStyle(b2_ball_druid, false, false)
call MultiboardSetItemStyle(b2_ball_shaman, false, true)
else
call MultiboardSetItemStyle(b1_ball_druid, false, true)
call MultiboardSetItemStyle(b1_ball_shaman, false, false)
call MultiboardSetItemStyle(b2_ball_druid, false, true)
call MultiboardSetItemStyle(b2_ball_shaman, false, false)
endif
endfunction
private function control takes nothing returns nothing
// 2 -> 1 -> 0 -> 2
if player_mb_status == 1 then
if IsMultiboardMinimized(board1) then
set player_mb_status = 0
endif
elseif player_mb_status == 2 then
if IsMultiboardMinimized(board2) then
call MultiboardDisplay(board2,false)
call MultiboardDisplay(board1,true)
call MultiboardMinimize(board1,false )
set player_mb_status = 1
endif
elseif player_mb_status == 0 then
if IsMultiboardMinimized(board1) == false then
call MultiboardDisplay(board1,false)
call MultiboardDisplay(board2,true)
call MultiboardMinimize(board2,false)
set player_mb_status = 2
endif
endif
endfunction
private function init takes nothing returns nothing
local multiboarditem mbitem
local integer i
local integer row
local boolean shamans_own_the_ball
call TriggerSleepAction(0.)
//Multiboard1 init
set board1 = CreateMultiboard()
call MultiboardSetRowCount(board1, 2)
call MultiboardSetColumnCount(board1,3)
call MultiboardSetTitleText(board1, "Druids vs Shamans")
//1. Zeile
set b1_ball_shaman = MultiboardGetItem(board1,0,0)
call MultiboardSetItemStyle(b1_ball_shaman, false, false)
call MultiboardSetItemIcon(b1_ball_shaman, icon_ball)
call MultiboardSetItemWidth(b1_ball_shaman, 0.01)
set mbitem = MultiboardGetItem(board1,0,1)
call MultiboardSetItemValue(mbitem, string_shaman)
call MultiboardSetItemIcon(mbitem, icon_shaman)
call MultiboardSetItemWidth(mbitem, 0.1)
call MultiboardReleaseItem(mbitem)
set b1_score_shaman = MultiboardGetItem(board1,0,2)
call MultiboardSetItemStyle(b1_score_shaman, true, false)
call MultiboardSetItemWidth(b1_score_shaman, 0.05)
call MultiboardSetItemValue(b1_score_shaman, I2S(main_score_limit))
//2. Zeile
set b1_ball_druid = MultiboardGetItem(board1,1,0)
call MultiboardSetItemStyle(b1_ball_druid, false, false)
call MultiboardSetItemIcon(b1_ball_druid, icon_ball)
call MultiboardSetItemWidth(b1_ball_druid, 0.01)
set mbitem = MultiboardGetItem(board1,1,1)
call MultiboardSetItemValue(mbitem, string_druid)
call MultiboardSetItemIcon(mbitem, icon_druid)
call MultiboardSetItemWidth(mbitem, 0.1)
call MultiboardReleaseItem(mbitem)
set b1_score_druid = MultiboardGetItem(board1,1,2)
call MultiboardSetItemStyle(b1_score_druid, true, false)
call MultiboardSetItemWidth(b1_score_druid, 0.05)
call MultiboardSetItemValue(b1_score_druid, I2S(main_score_limit))
//Multiboard2 init
set board2 = CreateMultiboard()
call MultiboardSetRowCount(board2, 2+ main_number_of_druids + main_number_of_shamans)
call MultiboardSetColumnCount(board2,3)
call MultiboardSetTitleText(board2, "Druids vs Shamans")
//1. Zeile
set b2_ball_shaman = MultiboardGetItem(board2,0,0)
call MultiboardSetItemStyle(b2_ball_shaman, false, false)
call MultiboardSetItemIcon(b2_ball_shaman, icon_ball)
call MultiboardSetItemWidth(b2_ball_shaman, 0.01)
set mbitem = MultiboardGetItem(board2,0,1)
call MultiboardSetItemValue(mbitem, string_shaman)
call MultiboardSetItemIcon(mbitem, icon_shaman)
call MultiboardSetItemWidth(mbitem, 0.1)
call MultiboardReleaseItem(mbitem)
set b2_score_shaman = MultiboardGetItem(board2,0,2)
call MultiboardSetItemStyle(b2_score_shaman, true, false)
call MultiboardSetItemWidth(b2_score_shaman, 0.05)
call MultiboardSetItemValue(b2_score_shaman, I2S(main_score_limit))
//2. Zeile
set b2_ball_druid = MultiboardGetItem(board2,1 + main_number_of_shamans,0)
call MultiboardSetItemStyle(b2_ball_druid, false, false)
call MultiboardSetItemIcon(b2_ball_druid, icon_ball)
call MultiboardSetItemWidth(b2_ball_druid, 0.01)
set mbitem = MultiboardGetItem(board2,1 + main_number_of_shamans,1)
call MultiboardSetItemValue(mbitem, string_druid)
call MultiboardSetItemIcon(mbitem, icon_druid)
call MultiboardSetItemWidth(mbitem, 0.1)
call MultiboardReleaseItem(mbitem)
set b2_score_druid = MultiboardGetItem(board2,1 + main_number_of_shamans,2)
call MultiboardSetItemStyle(b2_score_druid, true, false)
call MultiboardSetItemWidth(b2_score_druid, 0.05)
call MultiboardSetItemValue(b2_score_druid, I2S(main_score_limit))
//Spieler
set row = 1
set i = 0
loop
if i == 6 then
set row = row + 1
endif
if GetPlayerSlotState( Player(i)) == PLAYER_SLOT_STATE_PLAYING then
//Multiboard2
set mbitem = MultiboardGetItem(board2,row,0)
call MultiboardSetItemStyle(mbitem, false, false)
call MultiboardSetItemWidth(mbitem, 0.02)
call MultiboardReleaseItem(mbitem)
set b2_player[i] = MultiboardGetItem(board2,row,1)
call MultiboardSetItemStyle(b2_player[i], true, false)
call MultiboardSetItemValue(b2_player[i], get_player_color(i)+ "#|r " + GetPlayerName(Player(i)))
call MultiboardSetItemWidth(b2_player[i], 0.08)
set b2_kills[i] = MultiboardGetItem(board2,row,2)
call MultiboardSetItemStyle(b2_kills[i], true, false)
call MultiboardSetItemValue(b2_kills[i], "0")
call update_player_dead(i, false)
set row = row + 1
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
call MultiboardDisplay(board1,false)
call MultiboardDisplay(board2,true)
set player_mb_status = 2
call TimerStart(CreateTimer(), 0.01, true, function control)
endfunction
endlibrary
//===========================================================================
function InitTrig_multiboardsystem takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library herorevivesystem initializer init requires helper, board
globals
private integer dead_shamans = 0
private integer dead_druids = 0
private real revive_time_shaman = 0
private real revive_time_druid = 0
private real array revive_stone_x
private real array revive_stone_y
private integer revive_stone_count
public boolean array dead
endglobals
private function revive_hero takes unit u, real x, real y returns nothing
call ReviveHero(u, x,y , true)
if GetLocalPlayer() == GetOwningPlayer(u) then
call ClearSelection()
call SelectUnit(u,true)
endif
call PanCameraToTimedForPlayer(GetOwningPlayer(u), x,y, 0.0)
call SetUnitState(u,UNIT_STATE_MANA, GetUnitState(u,UNIT_STATE_MAX_MANA))
call attach_bool(u, "dead", false)
call board_update_player_dead( GetPlayerId(GetOwningPlayer(u)), false)
endfunction
private function revive_shaman takes nothing returns nothing
local unit u
local real x = 0
local real y = 0
local real shaman_mid_x = 300
local real shaman_mid_y = 3400
local real druid_mid_x = 300
local real druid_mid_y = 3400
local integer n =0
local integer i =0
local integer j =0
local real rating = 0
local integer best = 0
local real best_rating = 0
local real dist1 = 0
local real dist2 = 0
local integer shaman_revive_stone = 0
local integer druid_revive_stone = 0
//calc druid mid
set n = 0
set i = 6
loop
set u = main_hero[i]
if u != null then
if not dead[i] then
set druid_mid_x = (druid_mid_x * n + GetUnitX(u) ) / (n+1)
set druid_mid_y = (druid_mid_y * n + GetUnitY(u) ) / (n+1)
set n = n + 1
endif
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
//calc shaman mid
set shaman_mid_x = druid_mid_x
set shaman_mid_y = druid_mid_y
set n = 0
set i = 0
loop
set u = main_hero[i]
if u != null then
if not dead[i] then
set shaman_mid_x = (shaman_mid_x * n + GetUnitX(u) ) / (n+1)
set shaman_mid_y = (shaman_mid_y * n + GetUnitY(u) ) / (n+1)
set n = n + 1
endif
endif
//---
set i = i + 1
exitwhen i >= 6
endloop
//find a good revivestone for shamans
set best_rating = 0.0
set best = 0
set i = 0
loop
set dist1 = get_dist(revive_stone_x[i], revive_stone_y[i], shaman_mid_x, shaman_mid_y)
set dist2 = get_dist(revive_stone_x[i], revive_stone_y[i], druid_mid_x, druid_mid_y)
if (dist1 < dist2) and (dist2 > 2000) then
if dist1 > 0 then
set rating = 1000 / dist1
else
set rating = 1000000
endif
else
set rating = 0
endif
set j = 6
loop
if not dead[j] then
if get_dist(GetUnitX(main_hero[j]), GetUnitX(main_hero[j]), revive_stone_x[i], revive_stone_y[i]) < 1200 then
set rating = 0
endif
endif
//---
set j = j + 1
exitwhen j >= 12
endloop
if rating > best_rating then
set best_rating = rating
set best = i
endif
//---
set i = i + 1
exitwhen i > revive_stone_count
endloop
set shaman_revive_stone = best
//revive heros
set i = 0
loop
set u = main_hero[i]
if u != null then
if dead[i] then
set dead[i] = false
if i < 6 then
call revive_hero(u, revive_stone_x[shaman_revive_stone], revive_stone_y[shaman_revive_stone])
else
call revive_hero(u, revive_stone_x[druid_revive_stone], revive_stone_y[druid_revive_stone])
endif
else
//call DisplayTimedTextToPlayer(Player(0),0,0,30.0, I2S(i) + " not dead ( life = " + R2S(GetUnitState(u, UNIT_STATE_LIFE)))
endif
else
//call DisplayTimedTextToPlayer(Player(0),0,0,30.0, I2S(i) + " = null")
endif
//---
set i = i + 1
exitwhen i >= 6
endloop
set dead_shamans = 0
//call DisplayTimedTextToPlayer(Player(0),0,0,30.0, "revive end : " + I2S(druid_revive_stone) + " / " + I2S(shaman_revive_stone) + " ) ")
endfunction
private function revive_druid takes nothing returns nothing
local unit u
local real x = 0
local real y = 0
local real shaman_mid_x = 300
local real shaman_mid_y = 3400
local real druid_mid_x = 300
local real druid_mid_y = 3400
local integer n =0
local integer i =0
local integer j =0
local real rating = 0
local integer best = 0
local real best_rating = 0
local real dist1 = 0
local real dist2 = 0
local integer shaman_revive_stone = 0
local integer druid_revive_stone = 0
//calc shaman mid
set n = 0
set i = 0
loop
set u = main_hero[i]
if u != null then
if not dead[i] then
set shaman_mid_x = (shaman_mid_x * n + GetUnitX(u) ) / (n+1)
set shaman_mid_y = (shaman_mid_y * n + GetUnitY(u) ) / (n+1)
set n = n + 1
endif
endif
//---
set i = i + 1
exitwhen i >= 6
endloop
//calc druid mid
set druid_mid_x = shaman_mid_x
set druid_mid_y = shaman_mid_y
set n = 0
set i = 6
loop
set u = main_hero[i]
if u != null then
if not dead[i] then
set druid_mid_x = (druid_mid_x * n + GetUnitX(u) ) / (n+1)
set druid_mid_y = (druid_mid_y * n + GetUnitY(u) ) / (n+1)
set n = n + 1
endif
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
//find a good revivestone for druids
set best_rating = 0.0
set best = 0
set i = 0
loop
set dist1 = get_dist(revive_stone_x[i], revive_stone_y[i], druid_mid_x, druid_mid_y)
set dist2 = get_dist(revive_stone_x[i], revive_stone_y[i], shaman_mid_x, shaman_mid_y)
if (dist1 < dist2) and (dist2 > 2000) then
if dist1 > 0 then
set rating = 1000 / dist1
else
set rating = 1000000
endif
else
set rating = 0
endif
set j = 0
loop
if not dead[j] then
if get_dist(GetUnitX(main_hero[j]), GetUnitX(main_hero[j]), revive_stone_x[i], revive_stone_y[i]) < 1200 then
set rating = 0
endif
endif
//---
set j = j + 1
exitwhen j >= 6
endloop
if rating > best_rating then
set best_rating = rating
set best = i
endif
//---
set i = i + 1
exitwhen i > revive_stone_count
endloop
set druid_revive_stone = best
//revive heros
set i = 6
loop
set u = main_hero[i]
if u != null then
if dead[i] then
set dead[i] = false
if i < 6 then
call revive_hero(u, revive_stone_x[shaman_revive_stone], revive_stone_y[shaman_revive_stone])
else
call revive_hero(u, revive_stone_x[druid_revive_stone], revive_stone_y[druid_revive_stone])
endif
else
//call DisplayTimedTextToPlayer(Player(0),0,0,30.0, I2S(i) + " not dead ( life = " + R2S(GetUnitState(u, UNIT_STATE_LIFE)))
endif
else
//call DisplayTimedTextToPlayer(Player(0),0,0,30.0, I2S(i) + " = null")
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
set dead_druids = 0
//call DisplayTimedTextToPlayer(Player(0),0,0,30.0, "revive end : " + I2S(druid_revive_stone) + " / " + I2S(shaman_revive_stone) + " ) ")
endfunction
private function death takes nothing returns nothing
local unit u = GetDyingUnit()
local integer i = 0
loop
if main_hero[i] == u then
call board_update_player_dead( i, true)
set dead[i] = true
if i < 6 then
set dead_shamans = dead_shamans + 1
set revive_time_shaman = revive_time_shaman + 15 / Pow(2,dead_shamans-1)
else
set dead_druids = dead_druids + 1
set revive_time_druid = revive_time_druid + 15 / Pow(2,dead_druids-1)
endif
endif
//---
set i = i + 1
exitwhen i >= 12
endloop
call attach_bool(u, "dead", true)
set u = null
endfunction
private function update takes nothing returns nothing
if revive_time_shaman > 0 then
set revive_time_shaman = revive_time_shaman - 0.1
//call BJDebugMsg("shamans revive in : " + R2S(revive_time_shaman))
if revive_time_shaman <= 0 then
call revive_shaman()
endif
endif
if revive_time_druid > 0 then
set revive_time_druid = revive_time_druid - 0.1
//call BJDebugMsg("druids revive in : " + R2S(revive_time_shaman))
if revive_time_druid <= 0 then
call revive_druid()
endif
endif
endfunction
private function filt takes nothing returns boolean
return GetUnitTypeId(GetFilterUnit()) == const.ut_revive_stone
endfunction
private function init takes nothing returns nothing
local group g = CreateGroup()
local unit u
local integer i = 0
local trigger t
//Trigger für das wiederbeleben
//set t = CreateTrigger()
//call TriggerRegisterTimerEvent(t, 30.0, true)
//call TriggerAddAction(t, function revive_all)
call GroupEnumUnitsOfPlayer(g, Player(PLAYER_NEUTRAL_PASSIVE), Condition(function filt))
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
//---
set revive_stone_x[i] = GetUnitX(u)
set revive_stone_y[i] = GetUnitY(u)
set i = i + 1
endloop
set revive_stone_count = i - 1
//DeathTrigger
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction(t, function death)
set i = 0
loop
set dead[i] = false
//---
set i = i + 1
exitwhen i >= 12
endloop
//Timer
call TimerStart(CreateTimer(), 0.1, true, function update)
endfunction
endlibrary
//===========================================================================
function InitTrig_hero_revive_system takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
//does not really require the caster system but all libraries which require this require the caster system and i am lazy
library attackdetectionsystem initializer init requires CasterSystem
globals
private group all_units
trigger trig_on_damage
private constant integer buffid = 'B001'
boolean was_dmg_done_by_attack = false
endglobals
function check_was_dmg_done_by_attack takes nothing returns boolean
if (GetUnitAbilityLevel(GetTriggerUnit(),buffid)>0) then
call UnitRemoveAbility(GetTriggerUnit(),buffid)
return true
endif
return false
endfunction
private function on_damage takes nothing returns nothing
if check_was_dmg_done_by_attack() then
set was_dmg_done_by_attack = true
else
set was_dmg_done_by_attack = false
endif
//call BJDebugMsg("damage")
endfunction
private function enum_add_unit takes nothing returns nothing
call TriggerRegisterUnitEvent( trig_on_damage, GetEnumUnit(), EVENT_UNIT_DAMAGED )
endfunction
private function add_unit takes nothing returns nothing
call TriggerRegisterUnitEvent( trig_on_damage, GetTriggerUnit(), EVENT_UNIT_DAMAGED )
call GroupAddUnit(all_units, GetTriggerUnit())
endfunction
private function init takes nothing returns nothing
local trigger t
local region r = CreateRegion()
set all_units = CreateGroup()
call GroupEnumUnitsInRect(all_units, bj_mapInitialPlayableArea, null)
//erstellte einheiten der gruppe hinzufügen:
set t = CreateTrigger()
call RegionAddRect(r, bj_mapInitialPlayableArea)
call TriggerRegisterEnterRegion(t, r, null)
call TriggerAddAction(t, function add_unit)
//on_damage_trigger
set trig_on_damage = CreateTrigger()
call ForGroup(all_units, function enum_add_unit)
call TriggerAddAction( trig_on_damage, function on_damage)
endfunction
endlibrary
//===========================================================================
function InitTrig_Attack_Detection_System takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library spellsystem initializer spellsystem_init needs const, helper
globals
integer spell_count = 0
endglobals
function register_spell_f takes integer spell_item, integer spell returns nothing
set spell_count = spell_count + 1
call StoreInteger(get_gc(), "spellsystem", "item_" + I2S(spell_item), spell )
endfunction
//! textmacro register_spell takes spell
call register_spell_f( const.spell_$spell$_item, const.spell_$spell$)
//! endtextmacro
function buy_spell takes nothing returns nothing
local integer spell_item = GetItemTypeId( GetManipulatedItem() )
local unit hero = GetTriggerUnit()
local integer spell = GetStoredInteger(get_gc(), "spellsystem", "item_" + I2S(spell_item))
local integer spell_level = GetUnitAbilityLevel(hero, spell)
if spell_level == 0 then
call UnitAddAbility(hero, spell)
else
if spell_level < 10 then
call SetUnitAbilityLevel(hero, spell, spell_level + 1)
else
call DisplayTimedTextToPlayer( GetOwningPlayer(hero), 0,0, 10.0, "|cffff0000max spell level reached!|r")
call AdjustPlayerStateBJ( 200, GetOwningPlayer(hero), PLAYER_STATE_RESOURCE_GOLD)
endif
endif
endfunction
function spellsystem_init takes nothing returns nothing
local trigger t
//Trigger für das erwerben einer Fähigkeit
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddAction(t, function buy_spell )
//spells eintragen:
//! runtextmacro register_spell("magic_hammer")
//! runtextmacro register_spell("cripple_arrow")
//! runtextmacro register_spell("inferno")
//! runtextmacro register_spell("shocknova")
//! runtextmacro register_spell("freeze")
//! runtextmacro register_spell("dark_velocity")
//! runtextmacro register_spell("jump")
//! runtextmacro register_spell("fireball")
//! runtextmacro register_spell("serpent_wards")
//! runtextmacro register_spell("magic_hook")
//! runtextmacro register_spell("healwave")
//! runtextmacro register_spell("purgewave")
//! runtextmacro register_spell("lightning")
endfunction
endlibrary
//===========================================================================
function InitTrig_Spellsystem takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=33
//TESH.alwaysfold=0
//UTF8
library stunsystem initializer init requires CasterSystem
globals
private constant integer stun_abil = 'A00H'
endglobals
private function stun_handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local unit target = GetTableUnit(table,"target")
local integer lvl = GetTableInt(table,"lvl")
//function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, unit target, boolean instant returns unit
call CasterCastAbilityLevel(Player(12), stun_abil, lvl, "thunderbolt", target, true)
//call BJDebugMsg("stunning with level " + I2S(lvl))
call CleanAttachedVars(t)
call ReleaseTimer(t)
set t = null
set target = null
endfunction
public function stun takes unit target, real duration returns nothing
local real dur = duration
local integer n = 20
local real timestep = 0.0
local real time = 0.0
local timer t = null
local string table = ""
//call BJDebugMsg("begin stun ( " + R2S(duration) + " )")
loop
set timestep = 0.01 * Pow(2,n)
if dur >= timestep then
set dur = dur - timestep
//#####
set t = NewTimer()
set table = GetAttachmentTable(t)
call SetTableObject(table,"target",target)
call SetTableInt(table,"lvl",n+1)
call TimerStart(t,time,false,function stun_handler)
//call BJDebugMsg("stunning unit in " + R2S(time) + "seconds with lvl " +I2S(n) )
//#####
set time = time + timestep
endif
//---
set n = n - 1
exitwhen n < 0
exitwhen dur < 0.01
endloop
set t = null
endfunction
private function init takes nothing returns nothing
call PreloadAbility(stun_abil)
endfunction
endlibrary
//===========================================================================
function InitTrig_Stunsystem takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=204
//TESH.alwaysfold=0
//UTF8
library helper initializer init requires TimerUtils, gc
globals
private string array player_color
endglobals
function angleoffsetX takes real x, real radians, real offset returns real
return x + Cos(radians) * offset
endfunction
function angleoffsetY takes real y, real radians, real offset returns real
return y + Sin(radians) * offset
endfunction
function IsXYInRect takes real x, real y, rect r returns boolean
if x > GetRectMinX(r) then
if x < GetRectMaxX(r) then
if y > GetRectMinY(r) then
if y < GetRectMaxY(r) then
return true
endif
endif
endif
endif
return false
endfunction
function IsUnitInRect takes unit u, rect r returns boolean
return IsXYInRect( GetUnitX(u), GetUnitY(u), r)
endfunction
function MoveUnit takes unit u, real x, real y returns nothing
if x > GetRectMaxX(GetPlayableMapRect()) then
set x = GetRectMaxX(GetPlayableMapRect())
endif
if x < GetRectMinX(GetPlayableMapRect()) then
set x = GetRectMinX(GetPlayableMapRect())
endif
if y > GetRectMaxY(GetPlayableMapRect()) then
set y = GetRectMaxY(GetPlayableMapRect())
endif
if y < GetRectMinY(GetPlayableMapRect()) then
set y = GetRectMinY(GetPlayableMapRect())
endif
call SetUnitX( u, x)
call SetUnitY( u, y)
endfunction
function get_dist takes real x1, real y1, real x2, real y2 returns real
return SquareRoot((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
endfunction
function get_unit_dist takes unit u1, unit u2 returns real
return get_dist(GetUnitX(u1),GetUnitY(u1),GetUnitX(u2),GetUnitY(u2))
endfunction
private struct TimedLightning
lightning l
timer t
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call DestroyLightning(.l)
endmethod
static method callback takes nothing returns nothing
local TimedLightning this = GetTimerData(GetExpiredTimer())
call this.destroy()
endmethod
static method create takes lightning l, real time returns TimedLightning
local TimedLightning this = TimedLightning.allocate()
set this.t = NewTimer()
set .l = l
call SetTimerData(.t, this)
call TimerStart(.t, time, false, function TimedLightning.callback)
return this
endmethod
endstruct
function DestroyLightning_timed takes lightning l, real time returns lightning
call TimedLightning.create(l, time)
return l
endfunction
private struct TimedUnit
unit u
timer t
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call RemoveUnit(.u)
endmethod
static method callback takes nothing returns nothing
local TimedUnit this = GetTimerData(GetExpiredTimer())
call this.destroy()
endmethod
static method create takes unit u, real time returns TimedUnit
local TimedUnit this = TimedUnit.allocate()
set this.t = NewTimer()
set .u = u
call SetTimerData(.t, this)
call TimerStart(.t, time, false, function TimedUnit.callback)
return this
endmethod
endstruct
function RemoveUnit_timed takes unit u, real time returns unit
call TimedUnit.create(u, time)
return u
endfunction
private struct TimedEffect
effect e
timer t
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call DestroyEffect(.e)
endmethod
static method callback takes nothing returns nothing
local TimedEffect this = GetTimerData(GetExpiredTimer())
call this.destroy()
endmethod
static method create takes effect e, real time returns TimedEffect
local TimedEffect this = TimedEffect.allocate()
set this.t = NewTimer()
set .e = e
call SetTimerData(.t, this)
call TimerStart(.t, time, false, function TimedEffect.callback)
return this
endmethod
endstruct
function DestroyEffect_timed takes effect e, real time returns nothing
call TimedEffect.create(e, time)
endfunction
globals
private location tempzloc = Location(0,0)
endglobals
function get_z takes real x, real y returns real
call MoveLocation(tempzloc, x, y)
return GetLocationZ(tempzloc)
endfunction
function GetUnitZ takes unit u returns real
return get_z(GetUnitX(u),GetUnitY(u)) + GetUnitFlyHeight(u)
endfunction
function GetUnitTerrainZ takes unit u returns real
return get_z(GetUnitX(u),GetUnitY(u))
endfunction
function SetUnitZ takes unit u, real z returns nothing
call SetUnitFlyHeight(u,z - GetUnitTerrainZ(u),0.0)
endfunction
function get_slope takes real x1, real y1, real x2, real y2 returns real
//Steigung
local real z1 = get_z(x1,y1)
local real z2 = get_z(x2,y2)
local real dist = SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
if dist == 0 then
return 0.0
else
return (z2-z1)/dist
endif
endfunction
globals
private unit pathable_check_unit = null
endglobals
function get_pathable_check_unit takes real x, real y returns unit
if pathable_check_unit == null then
set pathable_check_unit = CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE) ,'hfoo',x,y,0)
call ShowUnit(pathable_check_unit, false)
else
call SetUnitPosition(pathable_check_unit,x,y)
endif
return pathable_check_unit
endfunction
function is_point_pathable takes real x, real y returns boolean
//einheit createn und pos prüfen
local unit u = get_pathable_check_unit(x,y)
local real dx = x - GetUnitX(u)
local real dy = y - GetUnitY(u)
local real dd = dx*dx+dy*dy
return dd < 16
endfunction
//allows to change the flying height of an unit
function make_unit_flyable takes unit u returns nothing
call UnitAddAbility(u,'Arav')
call UnitRemoveAbility(u, 'Arav')
endfunction
//+ or -
function sign takes real x returns integer
if x > 0 then
return 1
elseif x < 0 then
return -1
else
return 0
endif
endfunction
function get_player_color takes integer p returns string
return player_color[p]
endfunction
private function init takes nothing returns nothing
set player_color[0] = "|cff" + "ff0303"
//blue
set player_color[1] = "|cff" + "0042ff"
//teal
set player_color[2] = "|cff" + "1ce6b9"
//purple
set player_color[3] = "|cff" + "540081"
//yellow
set player_color[4] = "|cff" + "fffc01"
//orange
set player_color[5] = "|cff" + "fe8a0e"
//lime green
set player_color[6] = "|cff" + "20c000"
//pink
set player_color[7] = "|cff" + "e55bb0"
//grey
set player_color[8] = "|cff" + "959697"
//bright blue
set player_color[9] = "|cff" + "7ebff1"
//dark green
set player_color[10] = "|cff" + "106246"
//brown
set player_color[11] = "|cff" + "4e2a04"
endfunction
endlibrary
//===========================================================================
function InitTrig_Helper takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library messages initializer messages_init
globals
string array player_name
endglobals
function message takes string msg returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 6.0, msg)
endfunction
function messageDur takes string msg, real dur returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, dur, msg)
endfunction
function message_kill takes unit killer, unit victim returns nothing
call message( player_name[GetPlayerId(GetOwningPlayer(killer))] + " fragged " + player_name[GetPlayerId(GetOwningPlayer(victim))] + "!")
endfunction
function message_left_game takes player p returns nothing
call message( player_name[GetPlayerId(p)] + " has left the game." )
endfunction
function message_spell_cant_be_used_with_flag takes unit u returns nothing
call DisplayTimedTextToPlayer(GetOwningPlayer(u),0,0,5.0, "|cffff0000This spell cannot be used carrying the flag!|r")
endfunction
function messages_init takes nothing returns nothing
local integer i
//red
set player_name[0] = "|cff" + "ff0303" + GetPlayerName(Player(0)) + "|r"
//blue
set player_name[1] = "|cff" + "0042ff" + GetPlayerName(Player(1)) + "|r"
//teal
set player_name[2] = "|cff" + "1ce6b9" + GetPlayerName(Player(2)) + "|r"
//purple
set player_name[3] = "|cff" + "540081" + GetPlayerName(Player(3)) + "|r"
//yellow
set player_name[4] = "|cff" + "fffc01" + GetPlayerName(Player(4)) + "|r"
//orange
set player_name[5] = "|cff" + "fe8a0e" + GetPlayerName(Player(5)) + "|r"
//lime green
set player_name[6] = "|cff" + "20c000" + GetPlayerName(Player(6)) + "|r"
//pink
set player_name[7] = "|cff" + "e55bb0" + GetPlayerName(Player(7)) + "|r"
//grey
set player_name[8] = "|cff" + "959697" + GetPlayerName(Player(8)) + "|r"
//bright blue
set player_name[9] = "|cff" + "7ebff1" + GetPlayerName(Player(9)) + "|r"
//dark green
set player_name[10] = "|cff" + "106246" + GetPlayerName(Player(10)) + "|r"
//brown
set player_name[11] = "|cff" + "4e2a04" + GetPlayerName(Player(11)) + "|r"
set i = 0
loop
//call message(player_name[i])
set i = i + 1
exitwhen i >= 12
endloop
endfunction
endlibrary
//===========================================================================
function InitTrig_Messages takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library const initializer const_init
struct const
//heros
static constant integer unittype_druid = 'H003'
static constant integer unittype_shaman = 'H004'
//starting gold
static constant integer startgold = 1200
//performance-constants:
static constant real dt = 0.05
//items:
static constant integer flag1 = 'I000'
static constant integer flag2 = 'I001'
//units:
static constant integer herochooser = 'e000'
static constant integer ut_revive_stone = 'n000'
//strings:
static string flag1_path = "Objects\\InventoryItems\\BattleStandard\\BattleStandard.mdl"
static string flag2_path = "Objects\\InventoryItems\\BattleStandard\\BattleStandard.mdl"
//rects:
//######## spells ###############
//magic hammer
static constant integer spell_magic_hammer = 'A000'
static constant integer spell_magic_hammer_item = 'I002'
//cripple arrow
static constant integer spell_cripple_arrow = 'A001'
static constant integer spell_cripple_arrow_item = 'I004'
//infero
static constant integer spell_inferno = 'A003'
static constant integer spell_inferno_item = 'I005'
//shocknova
static constant integer spell_shocknova = 'A004'
static constant integer spell_shocknova_item = 'I006'
//Freeze
static constant integer spell_freeze = 'A007'
static constant integer spell_freeze_item = 'I007'
//Dark Velocity
static constant integer spell_dark_velocity = 'A009'
static constant integer spell_dark_velocity_item = 'I008'
//Jump
static constant integer spell_jump = 'A00A'
static constant integer spell_jump_item = 'I009'
//Fireball
static constant integer spell_fireball = 'A00B'
static constant integer spell_fireball_item = 'I00A'
//serpent wards
static constant integer spell_serpent_wards = 'A00C'
static constant integer spell_serpent_wards_item = 'I00B'
//magic hook
static constant integer spell_magic_hook = 'A00D'
static constant integer spell_magic_hook_item = 'I00C'
//Heal Wave
static constant integer spell_healwave = 'A00O'
static constant integer spell_healwave_item = 'I00S'
//Purge Wave
static constant integer spell_purgewave = 'A00Q'
static constant integer spell_purgewave_item = 'I00T'
//lightning
static constant integer spell_lightning = 'A00W'
static constant integer spell_lightning_item = 'I00W'
endstruct
function const_init takes nothing returns nothing
endfunction
endlibrary
//===========================================================================
function InitTrig_Const takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=1
//TESH.alwaysfold=0
//UTF8
library gc initializer create_gc
globals
gamecache udg_gc
private hashtable ht
endglobals
function create_gc takes nothing returns nothing
set ht = InitHashtable()
call FlushGameCache(InitGameCache("peq.gc.lol"))
set udg_gc = InitGameCache("peq.gc.lol")
endfunction
constant function get_gc takes nothing returns gamecache
return udg_gc
endfunction
function h2i takes handle h returns integer
return GetHandleId(h)
endfunction
function b2i takes boolean b returns integer
if b then
return 1
else
return 0
endif
endfunction
function i2b takes integer i returns boolean
return (i != 0)
endfunction
function attach_int takes handle h, string name, integer val returns nothing
call SaveInteger(ht,GetHandleId(h),StringHash(name), val)
endfunction
function get_attached_int takes handle h, string name returns integer
return LoadInteger(ht, GetHandleId(h),StringHash(name))
endfunction
function attach_bool takes handle h, string name, boolean val returns nothing
call SaveBoolean(ht,GetHandleId(h),StringHash(name), val)
endfunction
function get_attached_bool takes handle h, string name returns boolean
return LoadBoolean(ht, GetHandleId(h),StringHash(name))
endfunction
function attach_real takes handle h, string name, real val returns nothing
call SaveReal(ht,GetHandleId(h),StringHash(name), val)
endfunction
function get_attached_real takes handle h, string name returns real
return LoadReal(ht, GetHandleId(h),StringHash(name))
endfunction
function attach_string takes handle h, string name, string val returns nothing
call SaveStr(ht,GetHandleId(h),StringHash(name), val)
endfunction
function get_attached_string takes handle h, string name returns string
return LoadStr(ht, GetHandleId(h),StringHash(name))
endfunction
endlibrary
//===========================================================================
function InitTrig_GC takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=144
//TESH.alwaysfold=0
//UTF8
library spellshocknova initializer init needs const, CasterSystem, helper
globals
//spell-options :
private constant real missile_speed = 523
private constant real missile_arc = 0.0
private constant real range = 800
private constant real missile_fly_height = 30
private constant integer cripple = 'A002'
private constant string missile_modelpath = "Abilities\\Spells\\Orc\\Shockwave\\ShockwaveMissile.mdl"
private constant real missile_scale = 1.0
private constant integer missile_red = 255
private constant integer missile_green = 255
private constant integer missile_blue = 255
private constant integer missile_alpha = 255
private constant integer number_of_missiles = 20
private constant real missile_size = 1.0
private constant real damage = 75
private constant real damage_per_lvl = 50
private constant real dt = 0.05
private constant integer step_dmg = 3
private unit temp_caster
private real temp_damage
private group temp_group
endglobals
private function damager takes nothing returns nothing
if IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(temp_caster)) then
if IsUnitInGroup(GetEnumUnit(),temp_group) == false then
//call BJDebugMsg(R2S(temp_damage))
if GetUnitFlyHeight(GetEnumUnit()) < 200 then
call GroupAddUnit(temp_group, GetEnumUnit())
call UnitDamageTarget(temp_caster, GetEnumUnit(), temp_damage, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FORCE, WEAPON_TYPE_WHOKNOWS)
endif
endif
endif
endfunction
private function calc takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local real start_x = GetTableReal(table,"start_x")
local real start_y = GetTableReal(table,"start_y")
local real time = GetTableReal(table,"time") + dt
local integer step = GetTableInt(table,"step") + 1
local integer lvl = GetTableInt(table, "lvl")
local group already_hit = GetTableGroup(table,"already_hit")
local integer i = 0
local unit missile
local real angle
local real x
local real y
local real endtime = range / missile_speed
local real p1 = (endtime - time) / endtime
local real p2 = time / endtime
local real size = missile_size* time / endtime
local real target_x
local real target_y
local group g
local location temp_point
if step > step_dmg then
set step = 0
//damage
set temp_point = Location(start_x,start_y)
set g = GetUnitsInRangeOfLocAll(p2*range+100, temp_point)
call RemoveLocation(temp_point)
set temp_point = null
set temp_group = already_hit
set temp_caster = GetTableUnit(table,"caster")
set temp_damage = damage + damage_per_lvl * lvl
call ForGroup(g, function damager)
call DestroyGroup(g)
set g = null
endif
set i = 0
set angle = 0
loop
//call ProjectileLaunchEx (GetOwningPlayer(caster), missile_modelpath, missile_scale, missile_red, missile_green, missile_blue, missile_alpha, missile_speed, missile_arc, x, y, missile_fly_height, x + Cos(angle)*range, y + Sin(angle)*range, missile_fly_height)
//call ProjectileLaunchKill(GetOwningPlayer(caster), missile_modelpath, missile_speed, missile_arc, x, y, missile_fly_height, x + Cos(angle)*range, y + Sin(angle)*range, missile_fly_height)
set target_x = GetTableReal(table, "missilie_target_x" + I2S(i))
set target_y = GetTableReal(table, "missilie_target_y" + I2S(i))
set missile = GetTableUnit(table, "missilie_unit" + I2S(i))
set x = start_x * p1 + target_x * p2
set y = start_y * p1 + target_y * p2
call CS_MoveUnit(missile, x, y)
call SetUnitScale(missile, size, size, size)
set i = i + 1
set angle = angle + 2 * bj_PI / number_of_missiles
exitwhen angle >= 2 * bj_PI
endloop
call SetTableInt(table,"step",step)
call SetTableReal(table,"time",time)
if time > endtime then
set i = 0
set angle = 0
loop
set missile = GetTableUnit(table, "missilie_unit" + I2S(i))
call RemoveUnit(missile)
set i = i + 1
set angle = angle + 2 * bj_PI / number_of_missiles
exitwhen angle >= 2 * bj_PI
endloop
call PauseTimer(t)
call ReleaseTimer(t)
call ClearTable(table)
endif
set missile = null
set already_hit = null
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local real angle
local real start_x = GetUnitX(caster)
local real start_y = GetUnitY(caster)
local unit missile
local timer t = NewTimer()
local string table = GetAttachmentTable(t)
local integer i = 0
local real target_x
local real target_y
local group already_hit = CreateGroup()
set angle = 0
loop
//call ProjectileLaunchEx (GetOwningPlayer(caster), missile_modelpath, missile_scale, missile_red, missile_green, missile_blue, missile_alpha, missile_speed, missile_arc, x, y, missile_fly_height, x + Cos(angle)*range, y + Sin(angle)*range, missile_fly_height)
//call ProjectileLaunchKill(GetOwningPlayer(caster), missile_modelpath, missile_speed, missile_arc, x, y, missile_fly_height, x + Cos(angle)*range, y + Sin(angle)*range, missile_fly_height)
set target_x = start_x + Cos(angle) * range
set target_y = start_y + Sin(angle) * range
set missile = CreateCaster(Rad2Deg(angle),start_x,start_y)
call AddSpecialEffectTarget(missile_modelpath, missile, "origin")
call SetTableObject(table, "missilie_unit" + I2S(i), missile)
call SetTableReal(table, "missilie_target_x" + I2S(i), target_x)
call SetTableReal(table, "missilie_target_y" + I2S(i), target_y)
call SetUnitScale(missile, 0, 0, 0)
set i = i + 1
set angle = angle + 2 * bj_PI / number_of_missiles
exitwhen angle >= 2 * bj_PI
endloop
call SetTableReal(table, "start_x", start_x)
call SetTableReal(table, "start_y", start_y)
call SetTableReal(table, "time", 0.0)
call SetTableInt(table, "step", 0)
call SetTableObject(table, "caster", caster)
call SetTableGroup(table, "already_hit", already_hit)
call SetTableInt(table, "lvl", GetUnitAbilityLevel(caster, const.spell_shocknova))
call TimerStart(t, dt, true, function calc)
set missile = null
set caster = null
set already_hit = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_shocknova, "spellshocknova_actions")
endfunction
endlibrary //spellcripplearrow
//===========================================================================
function InitTrig_Spell_Shocknova takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library spellserpentwards initializer init needs const, CasterSystem, helper
globals
//spell-options :
private integer array serpent_ward
private constant real range = 1400
private constant real ward_count = 10
private constant real duration = 15.0
private constant real dt = 0.1
endglobals
private function create_ward_handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local integer p = GetTableInt(table,"p")
local integer lvl = GetTableInt(table,"lvl")
local real x = GetTableReal(table,"x")
local real y = GetTableReal(table,"y")
local unit ward
set ward = CreateUnit(Player(p), serpent_ward[lvl],x,y, 0.0)
call UnitApplyTimedLife(ward, 'Bhwd', duration)
//call SetUnitAnimation(ward, "Birth")
call SetUnitAnimationByIndex(ward, 0)
call ClearTable(table)
call ReleaseTimer(t)
set ward = null
set t = null
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location target = GetSpellTargetLoc()
local integer lvl = GetUnitAbilityLevel(caster, const.spell_serpent_wards)
local real start_x = GetUnitX(caster)
local real start_y = GetUnitY(caster)
local real target_x = GetLocationX(target)
local real target_y = GetLocationY(target)
local real dist = get_dist(start_x,start_y, target_x,target_y)
local real dx = (target_x-start_x) / dist * range / ward_count
local real dy = (target_y-start_y) / dist * range / ward_count
local real x = start_x
local real y = start_y
local integer i = 0
local timer t
local string table
loop
set x = x + dx
set y = y + dy
set t = NewTimer()
set table = GetAttachmentTable(t)
call SetTableInt(table,"p", GetPlayerId(GetOwningPlayer(caster)))
call SetTableInt(table,"lvl", lvl)
call SetTableReal(table,"x",x)
call SetTableReal(table,"y",y)
call TimerStart(t, i*dt, false, function create_ward_handler)
//---
set i = i + 1
exitwhen i >= ward_count
endloop
call RemoveLocation(target)
set caster = null
set target = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_serpent_wards, "spellserpentwards_actions")
set serpent_ward[1] = 'o000'
set serpent_ward[2] = 'o001'
set serpent_ward[3] = 'o002'
set serpent_ward[4] = 'o003'
set serpent_ward[5] = 'o004'
set serpent_ward[6] = 'o005'
set serpent_ward[7] = 'o006'
set serpent_ward[8] = 'o007'
set serpent_ward[9] = 'o008'
set serpent_ward[10] = 'o009'
endfunction
endlibrary //spellserpentwards
//===========================================================================
function InitTrig_Spell_Serpent_Wards takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=84
//TESH.alwaysfold=0
//UTF8
library spelljump initializer init needs const, CasterSystem, helper, Jumpsystem, messages
globals
//spell-options :
private constant real min_height = 350
private constant real height_factor = 0.5
private constant real duration = 1.0
private constant real speed = 1200
private constant integer dummy_thunderclap = 'A00N'
private constant string dummy_thunderclap_order = "slow"
private constant real thunderclap_range = 250
private constant real thunderclap_damage_base = 50
private constant real thunderclap_damage_per_lvl = 50
private constant string thunderclap_effect_model = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
endglobals
private function end takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local unit caster = GetTableUnit(table,"caster")
local real x = GetTableReal(table,"x")
local real y = GetTableReal(table,"y")
local integer level = GetTableInt(table,"level")
local group g = CreateGroup()
local unit target
local real damage = thunderclap_damage_base + thunderclap_damage_per_lvl * level
//function CasterCastAbilityLevelPoint takes player owner, integer abilid, integer level, string order, real x, real y, boolean instant returns unit
//call CasterCastAbilityLevelPoint(GetOwningPlayer(caster), dummy_thunderclap, level, dummy_thunderclap_order, x, y, true)
call GroupEnumUnitsInRange(g, x,y, thunderclap_range, null)
loop
set target = FirstOfGroup(g)
exitwhen target == null
//----
if IsUnitEnemy(target, GetOwningPlayer(caster)) then
//call BJDebugMsg("damage : " + R2S(damage))
call UnitDamageTarget( caster, target, damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FORCE, WEAPON_TYPE_WHOKNOWS)
call CasterCastAbilityLevel(GetOwningPlayer(caster), dummy_thunderclap, level, dummy_thunderclap_order, target, true)
endif
call GroupRemoveUnit(g,target)
endloop
call DestroyEffect(AddSpecialEffectTarget(thunderclap_effect_model, caster, "origin"))
call CleanAttachedVars(t)
call ReleaseTimer(t)
call DestroyGroup(g)
set g = null
set target = null
set t = null
set caster = null
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location target = GetSpellTargetLoc()
local real dx = GetUnitX(caster) - GetLocationX(target)
local real dy = GetUnitY(caster) - GetLocationY(target)
local real distance = SquareRoot(dx*dx+dy*dy)
local real dur = 1.0
local real height = RMaxBJ(height_factor*distance,min_height)
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local integer i = 0
local timer t
local string table = ""
//if (caster != unit_with_flag1) and (caster != unit_with_flag2) then
call SetUnitX(caster, GetRectMaxX(GetPlayableMapRect()) )
call SetUnitY(caster, GetRectMaxY(GetPlayableMapRect()) )
loop
exitwhen is_point_pathable(GetLocationX(target), GetLocationY(target))
exitwhen i > 10
set i = i + 1
call MoveLocation(target, GetLocationX(target) + dx * 0.1, GetLocationY(target) + dy * 0.1)
endloop
call SetUnitX(caster, x)
call SetUnitY(caster, y)
set distance = SquareRoot(dx*dx+dy*dy)
set dur = duration + distance/speed
call UnitJump(caster, GetLocationX(target), GetLocationY(target), height, dur)
set t = NewTimer()
set table = GetAttachmentTable(t)
call SetTableObject(table,"caster",caster)
call SetTableInt(table,"level",GetUnitAbilityLevel(caster, const.spell_jump))
call SetTableReal(table,"x", GetLocationX(target))
call SetTableReal(table,"y", GetLocationY(target))
call TimerStart(t, dur, false, function end)
//else
// call message_spell_cant_be_used_with_flag(caster)
//endif
call RemoveLocation(target)
set t = null
set caster = null
set target = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_jump, "spelljump_actions")
call PreloadAbility(dummy_thunderclap)
endfunction
endlibrary //spellfreeze
//===========================================================================
function InitTrig_Spell_Jump takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library spellinferno initializer init needs const, CasterSystem, helper
globals
//spell-options :
private constant real missile_speed = 500
private constant real missile_angle_speed = 3.0
private constant real average_range = 700
private constant real delta_range = 75
private constant real damage_base = 15
private constant real damage_per_level = 10
private constant real missile_offset = 50
private constant real collision_range = 75
private constant real missile_fly_height = 60
private constant real missile_spawn_delay = 0.05
private constant real mana_per_cast = 1
private constant integer spell_order_id = 852662 //"acidbomb"
private constant real delta_angle = Deg2Rad(20.0)
private constant real missile_scale = 1.0
endglobals
private function collision takes nothing returns nothing
local unit target = GetTriggerUnit()
local unit missile
local unit caster
local string table
local integer level
if target != null then
set missile = GetTriggerCollisionMissile()
set table = I2S(CollisionMissile_GetTag(missile))
set level = GetTableInt(table, "level")
set caster = GetTableUnit(table, "caster")
//call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", caster, "overhead"))
if IsUnitEnemy(target,GetOwningPlayer(caster)) then
if GetUnitFlyHeight(target) < 200 then
call UnitDamageTarget(caster, target, damage_base + level*damage_per_level, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS)
endif
endif
endif
endfunction
private function cast takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local real angle = GetTableReal(table, "angle") + GetRandomReal(-delta_angle,delta_angle)
local unit caster = GetTableUnit(table, "caster")
local real start_x = GetUnitX(caster)
local real start_y = GetUnitY(caster)
local real angle_speed = GetRandomReal(-missile_angle_speed,missile_angle_speed)
local real range = average_range + GetRandomReal(-delta_range,delta_range)
local integer level = GetTableInt(table, "level")
local real mana = GetUnitState(caster, UNIT_STATE_MANA)
local unit missile
if (mana > mana_per_cast) and (GetUnitCurrentOrder(caster) == spell_order_id) then
set mana = mana - mana_per_cast
call SetUnitState(caster, UNIT_STATE_MANA, mana)
set missile = CollisionMissile_Create ( "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl" , start_x, start_y, Rad2Deg(angle), missile_speed, angle_speed, range, missile_fly_height, false, collision_range, function collision)
call SetUnitScale(missile, missile_scale, missile_scale, missile_scale)
call SetTableInt(table, "level", GetUnitAbilityLevel(caster, const.spell_cripple_arrow))
call SetTableObject(table, "caster", caster)
call CollisionMissile_SetTag(missile, S2I(table))
else
//stop casting
//call IssueImmediateOrder(caster,"stop")
call PauseUnit(caster,true)
call PauseUnit(caster,false)
call DestroyTable(GetAttachedString(caster,"spell_inferno_table"))
call AttachString(caster,"spell_inferno_table", null)
call CleanAttachedVars(t)
call ReleaseTimer(t)
endif
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location l_target = GetSpellTargetLoc()
//local unit u_target = GetSpellTargetUnit()
local real angle = Atan2( GetLocationY(l_target)- GetUnitY(caster), GetLocationX(l_target)- GetUnitX(caster))
local real start_x = GetUnitX(caster) + missile_offset * Cos(angle)
local real start_y = GetUnitY(caster) + missile_offset * Sin(angle)
local timer t
local string table = GetAttachedString(caster,"spell_inferno_table")
if table == "" then
set t = NewTimer()
set table = GetAttachmentTable(t)
call SetTableInt(table, "level", GetUnitAbilityLevel(caster, const.spell_inferno))
call SetTableObject(table, "caster", caster)
call SetTableReal(table, "angle", angle)
call TimerStart(t, missile_spawn_delay, true, function cast)
call AttachString(caster,"spell_inferno_table",table)
else
call SetTableInt(table, "level", GetUnitAbilityLevel(caster, const.spell_inferno))
call SetTableReal(table, "angle", angle)
endif
endfunction
public function actions_d takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location l_target = GetSpellTargetLoc()
//local unit u_target = GetSpellTargetUnit()
local real angle = Atan2( GetLocationY(l_target)- GetUnitY(caster), GetLocationX(l_target)- GetUnitX(caster))
local real start_x = GetUnitX(caster) + missile_offset * Cos(angle)
local real start_y = GetUnitY(caster) + missile_offset * Sin(angle)
local timer t
local string table = GetAttachedString(caster,"spell_inferno_table")
if table == null then
set t = NewTimer()
set table = GetAttachmentTable(t)
call SetTableInt(table, "level", GetUnitAbilityLevel(caster, const.spell_inferno))
call SetTableObject(table, "caster", caster)
call SetTableReal(table, "angle", angle)
call TimerStart(t, missile_spawn_delay, true, function cast)
call AttachString(caster,"spell_inferno_table",table)
else
call SetTableInt(table, "level", GetUnitAbilityLevel(caster, const.spell_inferno))
call SetTableReal(table, "angle", angle)
endif
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_inferno, "spellinferno_actions_d")
endfunction
endlibrary //spellinferno
//===========================================================================
function InitTrig_Spell_Inferno takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library spellmagichook initializer init needs const, CasterSystem, helper, stunsystem
globals
//spell-options :
private constant real speed1 = 650
private constant real speed2 = 1300
private constant string missile_model = "Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl"
private constant real dt1 = 0.07
private constant real dt2 = 0.02
private constant real scale = 1.2
private constant real animation_speed = 1.0
private constant real height = 50
private constant real extra_stun = 1.0
private constant integer spell_order_id = 852132 // autodispel
endglobals
private function phase2_handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local unit caster = GetTableUnit(table, "caster")
local unit target = GetTableUnit(table, "target")
local integer n = GetTableInt(table, "n")
local integer m = GetTableInt(table, "m") + 1
local unit u = GetTableUnit(table, "unit_" + I2S(m))
local effect e = GetTableEffect(table, "effect_" + I2S(m))
local real x = GetUnitX(u)
local real y = GetUnitY(u)
call DestroyEffect(e)
call RemoveUnit(u)
call SetUnitX(caster, x)
call SetUnitY(caster, y)
if m < n then
call SetTableInt(table, "m", m)
else
if IsUnitEnemy(target, GetOwningPlayer(caster)) then
call IssueTargetOrder(caster, "attack", target)
else
call PauseUnit(caster, true)
call PauseUnit(caster, false)
endif
call PauseTimer(t)
call CleanAttachedVars(t)
call ReleaseTimer(t)
endif
set t = null
set caster = null
set target = null
set u = null
set e = null
endfunction
private function phase1_handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local unit caster = GetTableUnit(table, "caster")
local unit target = GetTableUnit(table, "target")
local integer n = GetTableInt(table, "n") + 1
local real x = GetTableReal(table, "x")
local real y = GetTableReal(table, "y")
local real t_x = GetUnitX(target)
local real t_y = GetUnitY(target)
local real dist = get_dist(x,y, t_x,t_y)
local real dx = (t_x - x) * speed1 * dt1 / dist
local real dy = (t_y - y) * speed1 * dt1 / dist
local unit u
local effect e
local integer m
set x = x + dx
set y = y + dy
if (dist < 100) and (n > 1) then
call PauseTimer(t)
call SetTableInt(table,"m",0)
call TimerStart(t, dt2, true, function phase2_handler)
//stun target
call stunsystem_stun(target, n*dt2+extra_stun)
else
if (GetUnitCurrentOrder(caster) != spell_order_id) then
set m = 1
loop
set u = GetTableUnit(table, "unit_" + I2S(m))
set e = GetTableEffect(table, "effect_" + I2S(m))
call DestroyEffect(e)
call RemoveUnit(u)
//---
set m = m + 1
exitwhen m >= n
endloop
call PauseTimer(t)
//call IssueImmediateOrder(caster,"stop")
call CleanAttachedVars(t)
call ReleaseTimer(t)
else
set u = CreateCaster(0,x,y)
call SetUnitScale(u, scale,scale,scale)
call SetUnitTimeScale(u, animation_speed)
call SetUnitFlyHeight(u, height, 0)
set e = AddSpecialEffectTarget(missile_model, u, "origin")
call SetUnitAnimationByIndex(u, 1)
call SetTableObject(table, "unit_" + I2S(n), u)
call SetTableEffect(table, "effect_" + I2S(n), e)
call SetTableInt(table,"n",n)
call SetTableReal(table,"x",x)
call SetTableReal(table,"y",y)
endif
endif
set t = null
set caster = null
set target = null
set u = null
set e = null
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local unit target = GetSpellTargetUnit()
local timer t = NewTimer()
local string table = GetAttachmentTable(t)
call SetTableObject(table, "caster", caster)
call SetTableObject(table, "target", target)
call SetTableInt (table, "n" , 0)
call SetTableReal (table, "x" , GetUnitX(caster))
call SetTableReal (table, "y" , GetUnitY(caster))
call TimerStart(t, dt1, true, function phase1_handler)
set caster = null
set target = null
set t = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_magic_hook, "spellmagichook_actions")
endfunction
endlibrary //spellinferno
//===========================================================================
function InitTrig_Spell_Magic_Hook takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=141
//TESH.alwaysfold=0
//UTF8
library spellfreeze initializer init needs const, CasterSystem, helper
globals
private constant real nova_range = 75
private constant real dmg_base = 50
private constant real dmg_per_lvl = 50
private constant real effect_min_scale = 0.9
private constant real effect_max_scale = 1.3
private constant real spell_len = 500
private constant real dt = 0.05
private constant real duration1 = 0.5
private constant real duration2 = 0.4
private constant integer dummy_ability_frost = 'A008'
private constant integer dummy_unit = 'e004'
endglobals
private function freeze_unit takes unit caster, unit target, integer level returns nothing
local unit dummy = CreateUnit(GetOwningPlayer(caster), dummy_unit, GetUnitX(target), GetUnitY(target),0.0)
call SetUnitAbilityLevel(dummy, dummy_ability_frost, level)
call IssueTargetOrder(dummy, "coldarrowstarg", target)
call RemoveUnit_timed(dummy, 1.0)
set dummy = null
//call BJDebugMsg("freeze")
endfunction
private function unit_hit_handler takes nothing returns nothing
local string table = GetAttachmentTable(GetTriggeringTrigger())
local unit caster = GetTableUnit(table,"caster")
local unit u = GetTriggerUnit()
local integer lvl = GetTableInt(table,"lvl")
local real damage = dmg_base + dmg_per_lvl * lvl
if IsUnitEnemy(u, GetOwningPlayer(caster)) then
if GetUnitFlyHeight(u) < 200 then
call freeze_unit(caster,u,lvl)
call UnitDamageTarget(caster, u, damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_COLD,WEAPON_TYPE_WHOKNOWS)
endif
endif
set caster = null
set u = null
endfunction
private function nova takes unit caster, real x, real y returns nothing
local real scale = GetRandomReal( effect_min_scale, effect_max_scale)
local unit e = CreateCaster(GetRandomReal(0, 360), x , y)
call SetUnitScale(e, scale,scale,scale)
call DestroyEffect_timed(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", e, "origin"),1.0)
call RemoveUnit_timed(e,1.0)
set e = null
endfunction
private function handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local real start_x = GetTableReal(table,"start_x")
local real start_y = GetTableReal(table,"start_y")
local real p1_x = GetTableReal(table,"p1_x")
local real p1_y = GetTableReal(table,"p1_y")
local real p2_x = GetTableReal(table,"p2_x")
local real p2_y = GetTableReal(table,"p2_y")
local real target_x = GetTableReal(table,"target_x")
local real target_y = GetTableReal(table,"target_y")
local unit caster = GetTableUnit(table,"caster")
local unit selecter_dummy1 = GetTableUnit(table,"selecter_dummy1")
local unit selecter_dummy2 = GetTableUnit(table,"selecter_dummy2")
local integer lvl = GetTableInt(table,"lvl")
local real time = GetTableReal(table,"time") + dt
local real a1
local real a2
local real x
local real y
if time <= duration1 then
set a1 = (duration1 - time) / duration1
set a2 = time / duration1
set x = start_x*a1 + p1_x*a2
set y = start_y*a1 + p1_y*a2
call nova(caster,x,y)
call MoveUnit(selecter_dummy1,x,y)
set x = start_x*a1 + p2_x*a2
set y = start_y*a1 + p2_y*a2
call nova(caster,x,y)
call MoveUnit(selecter_dummy2,x,y)
elseif time <= duration1+duration2 then
set a1 = (duration2 - time + duration1) / duration2
set a2 = (time - duration1) / duration2
set x = p1_x*a1 + target_x*a2
set y = p1_y*a1 + target_y*a2
call nova(caster,x,y)
call MoveUnit(selecter_dummy1,x,y)
set x = p2_x*a1 + target_x*a2
set y = p2_y*a1 + target_y*a2
call nova(caster,x,y)
call MoveUnit(selecter_dummy2,x,y)
else
//end
call RemoveUnit(selecter_dummy1)
call RemoveUnit(selecter_dummy2)
call DestroyTrigger(GetTableTrigger(table,"trig"))
call CleanAttachedVars(t)
call PauseTimer(t)
call ReleaseTimer(t)
endif
call SetTableReal(table,"time",time)
set selecter_dummy1 = null
set selecter_dummy2 = null
set t = null
set caster = null
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location target = GetSpellTargetLoc()
local real target_x = GetLocationX(target)
local real target_y = GetLocationY(target)
local real start_x = GetUnitX(caster)
local real start_y = GetUnitY(caster)
local real mid_x = (target_x + start_x) / 2.
local real mid_y = (target_y + start_y) / 2.
local real dx1 = target_x - start_x
local real dy1 = target_y - start_y
local real len1 = SquareRoot(dx1*dx1 + dy1*dy1)
local real dx2 = -dy1
local real dy2 = dx1
local real p1_x = mid_x + dx2/2
local real p1_y = mid_y + dy2/2
local real p2_x = mid_x - dx2/2
local real p2_y = mid_y - dy2/2
local timer t = NewTimer()
local string table = GetAttachmentTable(t)
local trigger trig = CreateTrigger()
local unit selecter_dummy1 = CreateCaster(0.0,0,0)
local unit selecter_dummy2 = CreateCaster(0.0,0,0)
local string trig_table = GetAttachmentTable(trig)
call SetTableObject(trig_table, "caster", caster)
call SetTableInt(trig_table,"lvl",GetUnitAbilityLevel(caster, const.spell_freeze))
call TriggerRegisterUnitInRange(trig, selecter_dummy1, nova_range, null)
call TriggerRegisterUnitInRange(trig, selecter_dummy2, nova_range, null)
call TriggerAddAction(trig, function unit_hit_handler)
call TimerStart(t, dt, true, function handler)
call SetTableReal(table,"start_x",start_x)
call SetTableReal(table,"start_y",start_y)
call SetTableReal(table,"p1_x",p1_x)
call SetTableReal(table,"p1_y",p1_y)
call SetTableReal(table,"p2_x",p2_x)
call SetTableReal(table,"p2_y",p2_y)
call SetTableReal(table,"target_x",target_x)
call SetTableReal(table,"target_y",target_y)
call SetTableObject(table,"caster",caster)
call SetTableObject(table,"selecter_dummy1",selecter_dummy1)
call SetTableObject(table,"selecter_dummy2",selecter_dummy2)
call SetTableTrigger(table,"trig",trig)
call SetTableInt(table,"lvl",GetUnitAbilityLevel(caster, const.spell_freeze))
call SetTableReal(table,"time",0.0)
call RemoveLocation(target)
set trig = null
set selecter_dummy1 = null
set selecter_dummy1 = null
set target = null
set caster = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_freeze, "spellfreeze_actions")
endfunction
endlibrary //spellfreeze
//===========================================================================
function InitTrig_Spell_Freeze takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library spellfireball initializer init needs const, CasterSystem, helper
globals
//spell-options :
private real dt = 0.05
private real mana_per_second = 60.0
private real mana_per_second_and_level = 0.0
private real damage_per_second = 75.0
private real damage_per_second_and_level = 65.0
private string missile_modelpath = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
private real missile_speed = 800.0
private real missile_arc = 0.15
private real range = 600
private real max_time = 3.0
private string caster_effect_model = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
private string target_effect_model = "Abilities\\Spells\\Other\\SoulBurn\\SoulBurnbuff.mdl"
private real missile_explode_scale = 1.5
private string missile_explode_model = "Abilities\\Weapons\\SteamTank\\SteamTankImpact.mdl"
endglobals
private function fireball_explode takes nothing returns nothing
local unit fireball = GetDyingUnit()
local unit explosion = CreateCaster(0.0, GetUnitX(fireball), GetUnitY(fireball) )
call SetUnitScale(explosion, missile_explode_scale, missile_explode_scale, missile_explode_scale)
call DestroyEffect_timed(AddSpecialEffectTarget(missile_explode_model, explosion, "origin"),1.0)
call RemoveUnit_timed(explosion,1.0)
endfunction
private function handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local unit caster = GetTableUnit(table, "caster")
local unit target = GetTableUnit(table, "target")
local real time = GetTableReal(table, "time") + dt
local integer lvl = GetTableInt (table, "lvl")
local real mana = GetUnitState(caster, UNIT_STATE_MANA)
local real mana_used = dt*mana_per_second + dt*lvl*mana_per_second_and_level
local real damage
local unit missile
local trigger trig
call SetTableReal(table, "time", time)
if (mana > mana_used) and (GetUnitCurrentOrder(caster) == 852215) and (get_unit_dist(caster, target) < range) and ( time <= max_time )then
call SetUnitState(caster, UNIT_STATE_MANA, mana- mana_used)
else
set damage = time*damage_per_second + time*lvl*damage_per_second_and_level
set missile = DamagingProjectileLaunchTarget(caster, missile_modelpath, missile_speed, missile_arc, GetUnitX(caster), GetUnitY(caster), 50.0, target, 50.0, damage, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FIRE)
set trig = CreateTrigger()
call TriggerRegisterUnitEvent(trig, missile, EVENT_UNIT_DEATH)
call TriggerAddAction(trig, function fireball_explode )
call DestroyEffect( GetTableEffect(table,"e_target") )
call DestroyEffect( GetTableEffect(table,"e_caster") )
call PauseTimer(t)
call ReleaseTimer(t)
call ClearTable(table)
call attach_string(caster, "spellfireball_table", "")
endif
set trig = null
set t = null
set target = null
set caster = null
set missile = null
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local unit target = GetSpellTargetUnit()
local timer t = NewTimer()
local string table = GetAttachmentTable(t)
local effect e_caster = AddSpecialEffectTarget(caster_effect_model, caster, "weapon")
local effect e_target = AddSpecialEffectTarget(target_effect_model, target, "overhead")
local string old_table = get_attached_string(caster, "spellfireball_table")
local unit old_caster
local unit old_target
local integer old_lvl
local real old_time
local timer old_t
local trigger trig
local real damage
local unit missile
if (old_table != "") and (old_table != null) then
set old_caster = GetTableUnit(old_table, "caster")
set old_target = GetTableUnit(old_table, "target")
set old_lvl = GetTableInt (old_table, "lvl")
set old_time = GetTableReal (old_table, "time")
set old_t = GetTableTimer(old_table, "timer")
set damage = old_time*damage_per_second + old_time*old_lvl*damage_per_second_and_level
set missile = DamagingProjectileLaunchTarget(old_caster, missile_modelpath, missile_speed, missile_arc, GetUnitX(old_caster), GetUnitY(old_caster), 50.0, old_target, 50.0, damage, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FIRE)
set trig = CreateTrigger()
call TriggerRegisterUnitEvent(trig, missile, EVENT_UNIT_DEATH)
call TriggerAddAction(trig, function fireball_explode )
call DestroyEffect( GetTableEffect(old_table,"e_target") )
call DestroyEffect( GetTableEffect(old_table,"e_caster") )
call PauseTimer(old_t)
call ReleaseTimer(old_t)
call ClearTable(old_table)
call attach_string(old_caster, "spellfireball_table", "")
endif
call SetTableObject(table, "caster", caster)
call SetTableObject(table, "target", target)
call SetTableObject(table, "e_target", e_target)
call SetTableObject(table, "e_caster", e_caster)
call SetTableObject(table, "timer", t)
call SetTableReal (table, "time" , 0.0)
call SetTableInt (table, "lvl" , GetUnitAbilityLevel(caster, const.spell_fireball) )
call attach_string(caster, "spellfireball_table", table)
call TimerStart(t, dt, true, function handler)
set t = null
set target = null
set caster = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_fireball, "spellfireball_actions")
endfunction
endlibrary //spellfireball
//===========================================================================
function InitTrig_Spell_Fireball_old takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
library spellfireball initializer init requires CasterSystem, const, helper
globals
//spell-options :
private constant real dt = 0.05
private constant real dt2 = 0.035
private constant real mana_per_second = 50.0
private constant real mana_per_second_and_level = 0.0
private constant real damage_per_second = 75.0
private constant real damage_per_second_and_level = 65.0
private constant string missile_modelpath = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
private constant real missile_speed = 800.0
private constant real missile_arc = 0.15
private constant real range = 700
private constant real max_time = 3.0
private constant string caster_effect_model = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
private constant string target_effect_model = "Abilities\\Spells\\Other\\SoulBurn\\SoulBurnbuff.mdl"
private constant real missile_explode_scale = 1.5
private constant string missile_explode_model = "Abilities\\Weapons\\SteamTank\\SteamTankImpact.mdl"
private constant real missile_scale_per_second = 1.0
private constant real missile_height = 25
endglobals
private struct data_struct
unit caster
unit target
unit missile
effect e
effect target_e
effect caster_e1
effect caster_e2
timer t
real angle
real time = 0.0
real chargetime = 0.0
real x
real y
integer lvl
boolean force_shoot = false
endstruct
private function handler_fly takes nothing returns nothing
local data_struct data = get_attached_int(GetExpiredTimer(), "spellfireball_data")
local real dx = GetUnitX(data.target) - data.x
local real dy = GetUnitY(data.target) - data.y
local real len = SquareRoot(dx*dx + dy*dy)
local real d1
local real d2
local real a
local real z
local real dmg
if len < 50 then
//explode
call SetUnitFlyHeight(data.missile, 0, 0)
set dmg = data.time*damage_per_second + data.time*data.lvl*damage_per_second_and_level
call UnitDamageTarget(data.caster, data.target, dmg, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(data.e)
call DestroyEffect_timed(AddSpecialEffectTarget(missile_explode_model, data.missile, "origin"),1.0)
call RemoveUnit_timed(data.missile,1.0)
call attach_int(data.caster, "spellfireball_data",0)
call attach_int(data.t, "spellfireball_data",0)
call DestroyTimer(data.t)
call data.destroy()
else
set data.x = data.x + dx / len * missile_speed * dt2
set data.y = data.y + dy / len * missile_speed * dt2
set d1 = get_unit_dist(data.missile, data.target)
set d2 = get_unit_dist(data.caster, data.target)
set a = (d1 / d2)*2 - 1
set z = (1 - a*a) * d2 * missile_arc + missile_height
//update
call SetUnitFlyHeight(data.missile, z, 0)
call SetUnitX(data.missile, data.x)
call SetUnitY(data.missile, data.y)
endif
endfunction
private function handler_channel takes nothing returns nothing
local data_struct data = get_attached_int(GetExpiredTimer(), "spellfireball_data")
local real mana_used = dt*mana_per_second + dt*data.lvl*mana_per_second_and_level
local real mana = GetUnitState(data.caster, UNIT_STATE_MANA)
local real scale
set data.time = data.time + dt
if ((mana > mana_used) and (GetUnitCurrentOrder(data.caster) == 852215) and (get_unit_dist(data.caster, data.target) < range) and ( data.time <= max_time )) and (not data.force_shoot) then
call SetUnitState(data.caster, UNIT_STATE_MANA, mana- mana_used)
set scale = missile_scale_per_second * data.time
call SetUnitScale(data.missile, scale, scale, scale)
else
call DestroyEffect(data.caster_e1)
call DestroyEffect(data.caster_e2)
call DestroyEffect(data.target_e)
call PauseTimer(data.t)
call TimerStart(data.t, dt2, true, function handler_fly)
endif
endfunction
public function actions takes nothing returns nothing
local data_struct data = data_struct.create()
local data_struct old_data
set data.caster = GetSpellAbilityUnit()
set data.lvl = GetUnitAbilityLevel(data.caster, const.spell_fireball)
set data.target = GetSpellTargetUnit()
set data.angle = Atan2(GetUnitY(data.target) - GetUnitY(data.caster), GetUnitX(data.target) - GetUnitX(data.caster))
set data.x = angleoffsetX(GetUnitX(data.caster), data.angle, 50)
set data.y = angleoffsetY(GetUnitY(data.caster), data.angle, 50)
set data.time = 0.
set data.force_shoot = false
set data.missile = CreateCaster(data.angle, data.x, data.y)
set data.e = AddSpecialEffectTarget(missile_modelpath, data.missile, "origin")
set data.target_e = AddSpecialEffectTarget(target_effect_model, data.target, "overhead")
set data.caster_e1 = AddSpecialEffectTarget(caster_effect_model, data.caster, "left hand")
set data.caster_e2 = AddSpecialEffectTarget(caster_effect_model, data.caster, "right hand")
call SetUnitFlyHeight(data.missile, 50, 0)
set old_data = get_attached_int(data.caster, "spellfireball_data")
if old_data != 0 then
//if the caster is already channeling, foce him to shoot his old fireball
set old_data.force_shoot = true
endif
set data.t = CreateTimer()
call attach_int(data.caster, "spellfireball_data", data)
call attach_int(data.t, "spellfireball_data", data)
call TimerStart(data.t, dt, true, function handler_channel)
endfunction
private function init takes nothing returns nothing
call OnAbilityEffect( const.spell_fireball, "spellfireball_actions")
endfunction
endlibrary
//===========================================================================
function InitTrig_Spell_Fireball takes nothing returns nothing
endfunction
//UTF8
library spellpurgewave initializer init needs const, CasterSystem, helper
//scope spellcripplearrow
globals
//spell-options :
private constant real missile_speed = 800
private constant real missile_angle_speed = 0.0
private constant real range = 1000
private constant real missile_offset = 50
private constant real collision_range = 200
private constant real missile_fly_height = 30
private constant integer purge = 'A00P'
private constant real damage_base = 50
private constant real damage_per_lvl = 50
private constant string missile_model = "Abilities\\Weapons\\WingedSerpentMissile\\WingedSerpentMissile.mdl"
private constant real missile_scale = 4.0
endglobals
private function collision takes nothing returns nothing
local unit target = GetTriggerUnit()
local unit missile
local unit caster
local string table
local integer level
if target != null then
set missile = GetTriggerCollisionMissile()
set table = I2S(CollisionMissile_GetTag(missile))
set level = GetTableInt(table, "level")
set caster = GetTableUnit(table, "caster")
//call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", caster, "overhead"))
if GetUnitFlyHeight(target) < 200 then
call CasterCastAbilityLevel(GetOwningPlayer(caster), purge, level, "purge", target, false)
if IsUnitEnemy(target,GetOwningPlayer(caster)) then
call UnitDamageTarget(caster, target, damage_base + damage_per_lvl*level, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS )
//call CollisionMissile_Destroy(missile)
//call DestroyTable(table)
endif
endif
endif
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location l_target = GetSpellTargetLoc()
//local unit u_target = GetSpellTargetUnit()
local real angle = Atan2( GetLocationY(l_target)- GetUnitY(caster), GetLocationX(l_target)- GetUnitX(caster))
local real start_x = GetUnitX(caster) + missile_offset * Cos(angle)
local real start_y = GetUnitY(caster) + missile_offset * Sin(angle)
local unit missile
local integer table = NewTableIndex()
local string s_table = I2S(table)
//####################
set missile = CollisionMissile_Create ( missile_model , start_x, start_y, Rad2Deg(angle), missile_speed, missile_angle_speed, range, missile_fly_height, true, collision_range, function collision)
call SetTableInt(s_table, "level", GetUnitAbilityLevel(caster, const.spell_purgewave))
call SetTableObject(s_table, "caster", caster)
call CollisionMissile_SetTag(missile, table)
call SetUnitScale(missile, missile_scale, missile_scale, missile_scale)
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_purgewave, "spellpurgewave_actions")
call PreloadAbility(purge)
endfunction
//endscope //spellcripplearrow
endlibrary //spellPurgeWave
//===========================================================================
function InitTrig_Spell_PurgeWave takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library spellcripplearrow initializer init needs const, CasterSystem, helper
//scope spellcripplearrow
globals
//spell-options :
private constant real missile_speed = 800
private constant real missile_angle_speed = 0.0
private constant real range = 2000
private constant real missile_offset = 50
private constant real collision_range = 75
private constant real missile_fly_height = 30
private constant integer cripple = 'A002'
private string missile_model = "Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl"
endglobals
private function collision takes nothing returns nothing
local unit target = GetTriggerUnit()
local unit missile
local unit caster
local string table
local integer level
if target != null then
set missile = GetTriggerCollisionMissile()
set table = I2S(CollisionMissile_GetTag(missile))
set level = GetTableInt(table, "level")
set caster = GetTableUnit(table, "caster")
//call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", caster, "overhead"))
if IsUnitEnemy(target,GetOwningPlayer(caster)) then
call CasterCastAbilityLevel(GetOwningPlayer(caster), cripple, level, "cripple", target, false)
//call CollisionMissile_Destroy(missile)
//call DestroyTable(table)
endif
endif
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location l_target = GetSpellTargetLoc()
//local unit u_target = GetSpellTargetUnit()
local real angle = Atan2( GetLocationY(l_target)- GetUnitY(caster), GetLocationX(l_target)- GetUnitX(caster))
local real start_x = GetUnitX(caster) + missile_offset * Cos(angle)
local real start_y = GetUnitY(caster) + missile_offset * Sin(angle)
local unit missile
local integer table = NewTableIndex()
local string s_table = I2S(table)
//####################
set missile = CollisionMissile_Create ( missile_model , start_x, start_y, Rad2Deg(angle), missile_speed, missile_angle_speed, range, missile_fly_height, true, collision_range, function collision)
call SetTableInt(s_table, "level", GetUnitAbilityLevel(caster, const.spell_cripple_arrow))
call SetTableObject(s_table, "caster", caster)
call CollisionMissile_SetTag(missile, table)
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_cripple_arrow, "spellcripplearrow_actions")
call PreloadAbility(cripple)
endfunction
//endscope //spellcripplearrow
endlibrary //spellcripplearrow
//===========================================================================
function InitTrig_Spell_Cripple_Arrow takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
// !!! BUGGED !!!
//THIS SPELL IS BUGGED
//-movement speed is not calculated properly
library spelldarkvelocity initializer init needs const, CasterSystem, helper
globals
//spell-options :
private constant real duration = 3
private constant real duration_per_lvl = 1.5
private constant real velocity = 0.8
private constant real dt = 0.01
endglobals
private function spell_handler takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local real time = GetTableReal(table,"time") + dt
local real endtime = GetTableReal(table,"end_time")
local unit target = GetTableUnit(table,"target")
local real facing = GetTableReal(table,"facing")
local real speed = GetTableReal(table,"speed")
local real speed2 = GetUnitMoveSpeed(target)
local real slow = GetTableReal(table,"slow")
local real speed3 = speed2 + slow
local real facing2 = GetUnitFacing(target)
local real d_angle = Angles_GetAngleDifference(facing,facing2)
local real x
local real y
local real z
local unit missile
if GetRandomInt(1,5) == 1 then
set x = GetUnitX(target) + GetRandomReal(-50,50)
set y = GetUnitY(target) + GetRandomReal(-50,50)
set z = GetRandomReal(5,150)
set missile = ProjectileLaunchKill( Player(0), "Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl", 500, 0.0, x, y, z, angleoffsetX(x,Deg2Rad(facing+180),600), angleoffsetY(y,Deg2Rad(facing+180),600), z)
endif
if time < endtime then
call SetUnitMoveSpeed(target, speed3 - speed3*velocity*CosBJ(d_angle))
call SetTableReal(table,"slow", speed3*velocity*CosBJ(d_angle))
call SetTableReal(table,"time", time)
else
call SetUnitMoveSpeed(target, speed3)
call ClearTable(table)
call ReleaseTimer(t)
endif
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local unit target = GetSpellTargetUnit()
local integer lvl = GetUnitAbilityLevel(caster, const.spell_dark_velocity)
local timer t = NewTimer()
local string table = GetAttachmentTable(t)
local real speed = GetUnitMoveSpeed(target)
call SetTableReal (table, "facing" , GetUnitFacing(target))
call SetTableReal (table, "time" , 0.0)
call SetTableReal (table, "end_time", duration + duration_per_lvl*lvl)
call SetTableObject(table, "target" , target)
call SetTableReal (table, "speed" , speed - speed*velocity)
call SetTableReal (table, "slow" , speed*velocity)
call SetUnitMoveSpeed(target, speed - speed*velocity)
call TimerStart(t, dt, true, function spell_handler)
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_dark_velocity, "spelldarkvelocity_actions")
endfunction
endlibrary //spellfreeze
//===========================================================================
function InitTrig_Spell_Dark_Velocity takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library spelllightning initializer init needs const, CasterSystem, helper
globals
private constant real dur = 4.0
private constant real dmg_base = 10.0
private constant real dmg_per_lvl = 10.0
private constant real end_dmg_base = 0.0
private constant real end_dmg_per_lvl = 20.0
private constant real dt = 0.5
private constant string model = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
private constant string model_end = "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdl"
private constant integer buffid = 'B003'
endglobals
private function dot takes nothing returns nothing
local timer t = GetExpiredTimer()
local string table = GetAttachmentTable(t)
local unit caster = GetTableUnit(table, "caster")
local unit target = GetTableUnit(table, "target")
local integer lvl = GetTableInt(table,"lvl")
local real time = GetTableReal(table, "time") + dt
local real ang = 0
if (time <= dur) and IsUnitAliveBJ(target) then
call SetTableReal(table, "time", time)
call UnitDamageTarget(caster, target, dmg_base + dmg_per_lvl*lvl, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FORCE, WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget(model, target, "left hand"))
call DestroyEffect(AddSpecialEffectTarget(model, target, "right hand"))
//call DestroyEffect(AddSpecialEffectTarget(model, target, "head"))
call DestroyEffect(AddSpecialEffectTarget(model, target, "chest"))
call DestroyEffect(AddSpecialEffectTarget(model, target, "origin"))
else
call UnitAddType(target, UNIT_TYPE_ANCIENT)
call SetTableReal(table, "time", time)
call UnitDamageTarget(caster, target, end_dmg_base + end_dmg_per_lvl*lvl, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_FORCE, WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget(model, target, "left hand"))
call DestroyEffect(AddSpecialEffectTarget(model, target, "right hand"))
//call DestroyEffect(AddSpecialEffectTarget(model, target, "head"))
call DestroyEffect(AddSpecialEffectTarget(model, target, "chest"))
call DestroyEffect(AddSpecialEffectTarget(model, target, "origin"))
loop
call DestroyEffect_timed(AddSpecialEffect(model_end,angleoffsetX( GetUnitX(target),ang,50),angleoffsetY( GetUnitY(target),ang,50) ),1.0)
//---
set ang=ang + 2* bj_PI / 8
exitwhen ang > 2* bj_PI
endloop
call ClearTable(table)
call PauseTimer(t)
call ReleaseTimer(t)
endif
set t = null
endfunction
public function actions takes nothing returns nothing
local unit target = GetSpellTargetUnit()
local unit caster = GetSpellAbilityUnit()
local timer t = NewTimer()
local string table = GetAttachmentTable(t)
call SetTableObject(table, "caster", caster)
call SetTableObject(table, "target", target)
call SetTableReal(table, "time", 0.0)
call SetTableInt(table, "lvl", GetUnitAbilityLevel(caster, const.spell_lightning))
call TimerStart(t, dt, true, function dot)
call UnitRemoveType(target, UNIT_TYPE_ANCIENT)
call UnitAddAbility(target, buffid)
//call SetUnitAbilityLevel(target, buffid, GetUnitAbilityLevel(caster, const.spell_lightning))
set t = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_lightning, "spelllightning_actions")
endfunction
endlibrary //spelllightning
//===========================================================================
function InitTrig_Spell_Lightning takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library spellfreeze initializer init needs const, CasterSystem, helper
globals
//spell-options :
private real damage_aoe = 500
private real damage_base = 50
private real damage_per_level = 50
private real effect_min_scale = 1.0
private real effect_max_scale = 4.0
private real effect_aoe = 400
private integer effect_count = 18
private integer dummy_ability_frost = 'A008'
private integer dummy_unit = 'e004'
private unit temp_caster
private integer temp_lvl
endglobals
private function filter takes nothing returns boolean
return IsUnitEnemy( GetFilterUnit(), GetOwningPlayer(temp_caster))
endfunction
private function freeze_unit takes unit target, integer level returns nothing
local unit dummy = CreateUnit(GetOwningPlayer(temp_caster), dummy_unit, GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()),0.0)
call SetUnitAbilityLevel(dummy, dummy_ability_frost, level)
call IssueTargetOrder(dummy, "coldarrowstarg", target)
call RemoveUnit_timed(dummy, 1.0)
set dummy = null
endfunction
private function damager takes nothing returns nothing
local real damage = damage_base + temp_lvl*damage_per_level
local unit dummy = CreateUnit(GetOwningPlayer(temp_caster), dummy_unit, GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()),0.0)
call UnitDamageTarget(temp_caster, GetEnumUnit(), damage, false, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_COLD,WEAPON_TYPE_WHOKNOWS)
call IssueTargetOrder(dummy, "coldarrowstarg", GetEnumUnit())
call SetUnitAbilityLevel(dummy, dummy_ability_frost, temp_lvl)
call RemoveUnit_timed(dummy, 1.0)
endfunction
public function actions takes nothing returns nothing
local unit caster = GetSpellAbilityUnit()
local location mid = GetSpellTargetLoc()
local real mid_x = GetLocationX(mid)
local real mid_y = GetLocationY(mid)
local real x
local real y
local integer i = 0
local real angle
local real range
local unit e
local real scale
local group g
local boolexpr be = Condition(function filter)
set temp_caster = caster
set temp_lvl = GetUnitAbilityLevel(caster, const.spell_freeze)
//damager
set g = CreateGroup()
call GroupEnumUnitsInRange(g, mid_x, mid_y, damage_aoe, be)
call ForGroup(g, function damager)
call DestroyGroup(g)
call DestroyBoolExpr(be)
set g = null
set be = null
loop
set angle = GetRandomReal(0, 2*bj_PI)
set range = SquareRoot(GetRandomReal(0.01,effect_aoe*effect_aoe))
set x = angleoffsetX(mid_x,angle,range)
set y = angleoffsetY(mid_y,angle,range)
set scale = GetRandomReal( effect_min_scale, effect_max_scale)
set e = CreateCaster(GetRandomReal(0, 360), x , y)
call SetUnitScale(e, scale,scale,scale)
call DestroyEffect_timed(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", e, "origin"),1.0)
call RemoveUnit_timed(e,1.0)
//----
set i = i + 1
exitwhen i >= effect_count
endloop
call RemoveLocation(mid)
set mid = null
set caster = null
endfunction
public function init takes nothing returns nothing
call OnAbilityEffect( const.spell_freeze, "spellfreeze_actions")
endfunction
endlibrary //spellfreeze
//===========================================================================
function InitTrig_old_Spell_Freeze takes nothing returns nothing
endfunction
//ENDUTF8
//TESH.scrollpos=0
//TESH.alwaysfold=0
//UTF8
library manafire initializer init requires CasterSystem
globals
private constant integer itemid = 'I00P'
private constant integer manaburnspell = 'A014'
private constant real dt = 0.05
private constant string e_model = "Abilities\\Spells\\Human\\ManaFlare\\ManaFlareBase.mdl"
endglobals
private struct data_struct
timer t
unit u
unit dummy
effect e
boolean disabled
endstruct
private function handler takes nothing returns nothing
local data_struct data = get_attached_int(GetExpiredTimer(), "manafire_data")
call SetUnitX(data.dummy, GetUnitX(data.u))
call SetUnitY(data.dummy, GetUnitY(data.u))
call SetUnitFlyHeight(data.dummy, GetUnitFlyHeight(data.u) + 50, 0)
if get_attached_bool(data.u, "dead") then
if not data.disabled then
call IssueImmediateOrderBJ( data.dummy, "manaflareoff" )
set data.disabled = true
endif
else
if data.disabled then
call IssueImmediateOrderBJ( data.dummy, "manaflareon" )
set data.disabled = false
endif
endif
endfunction
private function pickup takes nothing returns nothing
local unit dummy
local unit u = GetManipulatingUnit()
local data_struct data
if GetItemTypeId(GetManipulatedItem()) == itemid then
set dummy = CreateCaster(0,GetUnitX(u), GetUnitY(u))
call SetUnitOwner(dummy, GetOwningPlayer(u), true)
call UnitAddAbility(dummy, manaburnspell)
call IssueImmediateOrderBJ( dummy, "manaflareon" )
set data = data_struct.create()
set data.t = NewTimer()
set data.u = u
set data.dummy = dummy
set data.disabled = false
set data.e = AddSpecialEffectTarget(e_model, data.u, "overhead")
call attach_int(u, "manafire_data", data)
call attach_int(data.t, "manafire_data", data)
call TimerStart(data.t, dt, true, function handler)
endif
set dummy = null
set u = null
endfunction
private function drop takes nothing returns nothing
local data_struct data = get_attached_int(GetManipulatingUnit(), "manafire_data")
if GetItemTypeId(GetManipulatedItem()) == itemid then
call DestroyEffect(data.e)
call RemoveUnit(data.dummy)
call PauseTimer(data.t)
call ReleaseTimer(data.t)
call data.destroy()
endif
endfunction
private function init takes nothing returns nothing
local trigger t
//Trigger für Item aufnehmen
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddAction(t, function pickup)
//Trigger für Item droppen
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerAddAction(t, function drop)
endfunction
endlibrary
//===========================================================================
function InitTrig_Manafire takes nothing returns nothing
endfunction
//ENDUTF8
library divineprotecter initializer init requires attackdetectionsystem, helper
globals
private constant integer itemid = 'I011'
private constant real max_dmg_ratio = 0.1
private constant string effectmodel = "Abilities\\Spells\\Human\\Defend\\DefendCaster.mdl"
endglobals
private function damage takes nothing returns nothing
local unit attacker = GetEventDamageSource()
local unit victim = GetTriggerUnit()
local real dmg = GetEventDamage()
local real maxdmg
local real life
if UnitHasItemOfTypeBJ(victim, itemid) then
set maxdmg = GetUnitState(victim, UNIT_STATE_MAX_LIFE) * max_dmg_ratio
if dmg > maxdmg then
set life = GetUnitState(victim, UNIT_STATE_LIFE)
call SetUnitState(victim, UNIT_STATE_LIFE, life + dmg - maxdmg )
call DestroyEffect(AddSpecialEffectTarget(effectmodel, victim, "origin"))
endif
endif
//-_-
set attacker = null
set victim = null
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function damage)
endfunction
endlibrary
//===========================================================================
function InitTrig_Divine_Protecter takes nothing returns nothing
endfunction
//UTF8
library blood initializer init requires attackdetectionsystem
globals
private string array blood_effect
endglobals
private function create_blood takes nothing returns nothing
if was_dmg_done_by_attack then
call DestroyEffect(AddSpecialEffectTarget(blood_effect[GetRandomInt(0,11)], GetTriggerUnit(), "origin"))
endif
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function create_blood)
set blood_effect[0] = "Objects\\Spawnmodels\\Orc\\Orcblood\\BattrollBlood.mdl"
set blood_effect[1] = "Objects\\Spawnmodels\\Other\\BeastmasterBlood\\BeastmasterBlood.mdl"
set blood_effect[2] = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
set blood_effect[3] = "Objects\\Spawnmodels\\Human\\HumanBlood\\HeroBloodElfBlood.mdl"
set blood_effect[4] = "Objects\\Spawnmodels\\Orc\\Orcblood\\HeroShadowHunterBlood.mdl"
set blood_effect[5] = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodKnight.mdl"
set blood_effect[6] = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodMortarTeam.mdl"
set blood_effect[7] = "Objects\\Spawnmodels\\Orc\\Orcblood\\OrcBloodHellScream.mdl"
set blood_effect[8] = "Objects\\Spawnmodels\\Orc\\Orcblood\\OrcBloodHeroTaurenChieftain.mdl"
set blood_effect[9] = "Objects\\Spawnmodels\\Orc\\Orcblood\\OrcBloodWitchDoctor.mdl"
set blood_effect[10] = "Objects\\Spawnmodels\\Orc\\Orcblood\\OrdBloodWyvernRider.mdl"
set blood_effect[11] = "Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl"
endfunction
endlibrary
//===========================================================================
function InitTrig_blood takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library frenzyclaw initializer init requires attackdetectionsystem
globals
private constant integer bloodlust = 'A00T'
private constant integer buffid = 'B002'
endglobals
private function damage takes nothing returns nothing
local integer lvl = 1
local unit u = GetEventDamageSource()
if was_dmg_done_by_attack then
if UnitHasItemOfTypeBJ(u, 'I00H') then
if GetUnitAbilityLevel(u,buffid) > 0 then
set lvl = 1 + get_attached_int(u, "frenzy_claw_level")
else
set lvl = 1
endif
call attach_int(u, "frenzy_claw_level", lvl)
//function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, unit target, boolean instant returns unit
call CasterCastAbilityLevel(GetOwningPlayer(u), bloodlust, lvl, "852101", u, true)
endif
endif
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function damage)
call PreloadAbility(bloodlust)
endfunction
endlibrary
//===========================================================================
function InitTrig_frenzy_claw takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library darkclaw initializer init requires attackdetectionsystem
globals
private constant integer faeriefire = 'A012'
private constant integer buffid = 'B004'
endglobals
private struct cast_data_struct
integer level
player owner
unit target
endstruct
private function cast takes nothing returns nothing
local timer t = GetExpiredTimer()
local cast_data_struct cast_data = get_attached_int(t, "cast_data")
call CasterCastAbilityLevel(cast_data.owner, faeriefire, cast_data.level, "faeriefire", cast_data.target, true)
call cast_data.destroy()
call ReleaseTimer(t)
set t = null
endfunction
private function damage takes nothing returns nothing
local integer lvl = 1
local unit u = GetTriggerUnit()
local timer t
local cast_data_struct cast_data
if was_dmg_done_by_attack then
if UnitHasItemOfTypeBJ(GetEventDamageSource(), 'I00M') then
if GetUnitAbilityLevel(u,buffid) > 0 then
set lvl = 1 + get_attached_int(u, "dark_claw_level")
else
set lvl = 1
endif
call attach_int(u, "dark_claw_level", lvl)
//function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, unit target, boolean instant returns unit
set t = NewTimer()
set cast_data = cast_data.create()
call attach_int(t, "cast_data", cast_data)
set cast_data.level = lvl
set cast_data.owner = GetOwningPlayer(GetEventDamageSource())
set cast_data.target = u
call TimerStart(t, 0.01, false, function cast)
endif
endif
set t = null
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function damage)
call PreloadAbility(faeriefire)
endfunction
endlibrary
//===========================================================================
function InitTrig_dark_claw takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library frostclaw initializer init requires attackdetectionsystem
globals
private constant integer nova = 'A013'
endglobals
private struct cast_data_struct
player owner
unit target
endstruct
private function cast takes nothing returns nothing
local timer t = GetExpiredTimer()
local cast_data_struct cast_data = get_attached_int(t, "cast_data")
call CasterCastAbilityLevel(cast_data.owner, nova, 1, "frostnova", cast_data.target, true)
call cast_data.destroy()
call ReleaseTimer(t)
set t = null
endfunction
private function damage takes nothing returns nothing
local integer lvl = 1
local unit u = GetTriggerUnit()
local timer t
local cast_data_struct cast_data
if was_dmg_done_by_attack then
if UnitHasItemOfTypeBJ(GetEventDamageSource(), 'I00O') then
//function CasterCastAbilityLevel takes player owner, integer abilid, integer level, string order, unit target, boolean instant returns unit
set t = NewTimer()
set cast_data = cast_data.create()
call attach_int(t, "cast_data", cast_data)
set cast_data.owner = GetOwningPlayer(GetEventDamageSource())
set cast_data.target = u
call TimerStart(t, 0.01, false, function cast)
endif
endif
set t = null
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function damage)
call PreloadAbility(nova)
endfunction
endlibrary
//===========================================================================
function InitTrig_frost_claw takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library moonclaw initializer init requires attackdetectionsystem, helper
globals
private constant string effectmodel = "Abilities\\Spells\\Human\\Feedback\\SpellBreakerAttack.mdl"
private constant real burned_mana = 20.
endglobals
private function damage takes nothing returns nothing
local integer lvl = 1
local unit attacker = GetEventDamageSource()
local unit u = GetTriggerUnit()
local real mana
local real dmana
if was_dmg_done_by_attack then
if UnitHasItemOfTypeBJ(attacker, 'I00I') then
call DestroyEffect_timed(AddSpecialEffectTarget(effectmodel, u, "chest"),1.0 )
set mana = GetUnitState(u, UNIT_STATE_MANA)
if mana > burned_mana then
set dmana = burned_mana
else
set dmana = mana
endif
call SetUnitState(u, UNIT_STATE_MANA, mana - dmana)
call UnitDamageTarget(attacker, u, dmana, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
endif
endif
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function damage)
endfunction
endlibrary
//===========================================================================
function InitTrig_moon_claw takes nothing returns nothing
endfunction
//ENDUTF8
//UTF8
library clawofnature initializer init requires attackdetectionsystem, helper
globals
private constant string effectmodel = "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl"
private constant real dmg_per_sec = 5
private constant real duration = 10
private constant real dt = 1.0
endglobals
private struct data_struct
unit attacker
unit target
timer t
real time
endstruct
private function handler takes nothing returns nothing
local data_struct data = get_attached_int(GetExpiredTimer(), "data")
call DestroyEffect(AddSpecialEffectTarget(effectmodel, data.target, "chest"))
call UnitDamageTarget(data.attacker, data.target, dmg_per_sec / dt, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_POISON, WEAPON_TYPE_WHOKNOWS)
set data.time = data.time + dt
if (data.time > duration) or IsUnitDeadBJ(data.target) then
call PauseTimer(data.t)
call DestroyTimer(data.t)
call data.destroy()
endif
endfunction
private function damage takes nothing returns nothing
local integer lvl = 1
local unit attacker = GetEventDamageSource()
local unit u = GetTriggerUnit()
local data_struct data
if was_dmg_done_by_attack then
if UnitHasItemOfTypeBJ(attacker, 'I00R') then
set data = data_struct.create()
set data.t = CreateTimer()
set data.attacker = attacker
set data.target = u
set data.time = 0.0
call attach_int(data.t, "data", data)
call TimerStart(data.t, dt, true, function handler)
endif
endif
endfunction
private function init takes nothing returns nothing
call TriggerAddAction(trig_on_damage, function damage)
endfunction
endlibrary
//===========================================================================
function InitTrig_claw_of_nature takes nothing returns nothing
endfunction
//ENDUTF8