Name | Type | is_array | initial_value |
native UnitAlive takes unit id returns boolean//Remove this if you already had one
//! zinc
library ReAmminsChild
/*-----------------------------------------------------------------------------------/
/- v1.0.2
/- JC Helas & KitsuneTailsPrower
/-
/- Description:
/- Releases sa tons of lightning ball that will spread
/- above and attack near enemy.
/-
/- How to Import:
/- 1. Goto File>Preferences>General
/- 2. Mark check the "Automatically create unknown varaibles while pasting data.
/- 3. Copy the imported dummy.mdx and configure the respective dummy units for dummy caster and dummy recycler
/- 4. Then copy the folder and paste on your map.
/-
/-
/-
/-----------------------------------------------------------------------------------*/
{
private
{
/*- Determine the ability ID of Re'ammin's Child -*/
constant integer SPELL_ID = 'A000' ;
/*- Determine the base amount of balls -*/
constant integer BALL_AMT = 13 ;
/*- Determine the addtional amount of balls per level -*/
constant integer BALL_AMTL= 2 ;
/*- Determine the base duration of balls -*/
constant real BALL_DUR = 10.0 ;
/*- Determine the addtional duration of balls per level -*/
constant real BALL_DURLVL = 5.0 ;
/*- Determine the base attack interval of balls -*/
constant real BALL_INTER = 1.25 ;
/*- Determine the deductional attack interval of balls per level -*/
constant real BALL_INTERLV= 0.125 ;
/*- Determine the targets that will be struck by lightning -*/
constant integer LIGHTNING_SEARCH_FILTER = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_IMMUNE;
/*- Determine the targets that will be hit by drop AoE damage -*/
constant integer DROP_SEARCH_FILTER = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_NON_IMMUNE;
/*- Determine the minimum damage of balls -*/
constant real DAMAGE_MIN = 30.0 ;
/*- Determine the maximum damage of balls -*/
constant real DAMAGE_MAX = 75.0 ;
/*- Determine the additonal damage of ball by caster int percent -*/
constant real DAMAGE_INT = 15.0 ;
/*- Determine the mana depletion of balls -*/
constant real MANA_DAMAGE = 50.0 ;
/*- Determine the additonal mana depletion of ball by caster int percent -*/
constant real MANA_DAMAGE_INT = 1.0 ;
/*- Determine the duration of lightnings -*/
constant real LIGHTNING_D = 0.25 ;
/*- Should the lightning strikes deal AoE damage. If false it only damages the target-*/
constant boolean USE_DAMAGE_AOE = false;
/*- Determine the targets that will be hit by lightning AoE damage if USE_DAMAGE_AOE is set to true -*/
constant integer DAMAGE_SEARCH_FILTER = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_NON_IMMUNE;
/*- Determine the area of effect per lightning strike if USE_DAMAGE_AOE is set to true-*/
constant real DAMAGE_AOE = 100.0 ;
/*- Determine the area of effect for drop-*/
constant real DROP_DAMAGE_AOE = 100.0 ;
/*- Determine the ability ID for the stuns -*/
constant integer STUN_ID = 'A001' ;
/*- Should the lightning strikes stun?-*/
constant boolean USE_STUN = true;
/*- Should the drop stun?-*/
constant boolean DROP_USE_STUN = true;
/*- Determine the search radius of each ball -*/
constant real SEARCH_AOE = 300.0 ;
/*- Determine the speed of balls to their distination -*/
constant real SPEED = 5.0 ;
/*- Determine the speed of dropping balls -*/
constant real SPEED_DROP = 15.0 ;
/*- Determine the maximum distance of each ball -*/
constant real DISTANCE = 300.0 ;
/*- Determine the minimum height of each ball -*/
constant real MIN_Z = 100.0 ;
/*- Determine the maximum height of each ball -*/
constant real MAX_Z = 700.0 ;
/*- Determine the starting size of balls -*/
constant real MIN_SIZE = 0.10 ;
/*- Determine the maximum size of balls -*/
constant real MAX_SIZE = 2.0 ;
/*- Determine the starting distance of ball to caster -*/
constant real SUMMON_DIST = 50.0 ;
/*- Determine the attack type of each damage -*/
constant attacktype A_TYPE= ATTACK_TYPE_NORMAL ;
/*- Determine the damage type of each damage -*/
constant damagetype D_TYPE= DAMAGE_TYPE_MAGIC ;
/*- Determine the model attachment of ball model to dummy -*/
constant string BALL_ATCH = "origin" ;
/*- Determine the model of balls -*/
constant string BALL_MODEL= "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl";
/*- Determine the effect for the lightning strikes on the target -*/
constant string STRIKE_FX = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl";
/*- Determine the lightning ground impact effect -*/
constant string GROUND_FX = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl";
/*- Determine the type of lightning bolt -*/
constant string LIGHTNING = "CLPB" ;
struct data
{
player owner;
unit caster,dummy;
real angle,rate,speed,dur,interval,inte,dx,dy,dist,z,dmgint,manadmgint;
effect fx;
lightning l;
boolean aoe;
}
struct lightningdata
{
lightning l;
real d;
}
constant real periodic=0.031250;
constant group grp=CreateGroup();
constant timer tmr=CreateTimer();
integer ix=0;
integer ic[];
data link=0;
constant timer ltmr=CreateTimer();
integer lix=0;
integer lic[];
//! textmacro Destroy takes NAME,IX,IC,THIS,TMR
function Destroy$NAME$(integer i) -> integer
{
$THIS$ this=$IC$[i];
$THIS$.destroy(this);
$IC$[i]=$IC$[$IX$];
$IX$=$IX$-1;
if($IX$==0)
{
PauseTimer($TMR$);
}
return i-1;
}
//! endtextmacro
//! textmacro Create takes NAME,IX,IC,THIS,TMR,CODE
function Create$NAME$() -> $THIS$
{
$THIS$ this=$THIS$.create();
$IX$+=1;
$IC$[$IX$]=this;
if($IX$==1)
{
TimerStart($TMR$,periodic,true,$CODE$);
}
return this;
}
//! endtextmacro
//! runtextmacro Destroy("Light","lix","lic","lightningdata","ltmr")
function onLightningLoop()
{
integer i=1;
real r;
lightningdata this;
while(i<=lix)
{
this=lic[i];
this.d=this.d-periodic;
if(this.d>0)
{
r=(1.0/LIGHTNING_D)*this.d;
SetLightningColor(this.l,r,r,r,r);
}
else
{
i=DestroyLight(i);
}
i+=1;
}
}
//! runtextmacro Create("Light","lix","lic","lightningdata","ltmr","function onLightningLoop")
function onLightning(lightning l,real d)
{
lightningdata this=CreateLight();
this.l=l;
this.d=d;
}
//! runtextmacro Destroy("Data","ix","ic","data","tmr")
function inflictAoEDamage(unit c, real x, real y, real damage, real manadamage, boolean stun) {
real cx=GetUnitX(c);
real cy=GetUnitY(c);
player owner=GetOwningPlayer(c);
group g=CreateGroup();
unit t;
GroupEnumUnitsInRange(g,x,y,DAMAGE_AOE,null);
t=FirstOfGroup(g);
while (t!=null) {
t=FirstOfGroup(g);
if(UnitFilter(t,owner,DAMAGE_SEARCH_FILTER)) {
UnitDamageTarget(c,t,damage,false,false,A_TYPE,D_TYPE,null);
SetUnitState(t,UNIT_STATE_MANA,GetUnitState(t,UNIT_STATE_MANA) - manadamage);
if (stun) {
//If you have a stun system in your map feel free to use it here
DummyCaster['A001'].castTarget(owner,1,OrderId("thunderbolt"),cx,cy,t);
}
}
GroupRemoveUnit(g,t);
}
DestroyGroup(g);
g=null;
t=null;
}
function onLoop()
{
data this;
integer i=1;
real x,y,s,sin;
unit t;
while(i<=ix)
{
this=ic[i];
x=this.dx;
y=this.dy;
if(this.rate<100.0)
{
this.rate=this.rate+this.speed;
sin=Sin(((90.0/100.0)*this.rate)*bj_DEGTORAD);
s=(sin*MAX_SIZE);
x=x+(sin*this.dist)*Cos(this.angle*bj_DEGTORAD);
y=y+(sin*this.dist)*Sin(this.angle*bj_DEGTORAD);
SetUnitFlyHeight(this.dummy,sin*this.z,0.0);
SetUnitScale(this.dummy,s,s,s);
SetUnitX(this.dummy,x);
SetUnitY(this.dummy,y);
}
else
{
this.dur=this.dur-periodic;
if(this.dur>0.0)
{
this.inte=this.inte-periodic;
if(this.inte<=0)
{
this.inte=this.interval;
link=this;
GroupEnumUnitsInRange(grp,x,y,SEARCH_AOE,Filter(function()
{
unit t=GetFilterUnit();
real x,y;
if(UnitFilter(t,link.owner,LIGHTNING_SEARCH_FILTER))
{
x=GetUnitX(t);y=GetUnitY(t);
if (USE_DAMAGE_AOE) {
inflictAoEDamage(link.caster,x,y,GetRandomReal(DAMAGE_MIN,DAMAGE_MAX)+link.dmgint,MANA_DAMAGE+link.manadmgint,USE_STUN);
DestroyEffect(AddSpecialEffect(STRIKE_FX,x,y));
} else {
UnitDamageTarget(link.caster,t,GetRandomReal(DAMAGE_MIN,DAMAGE_MAX)+link.dmgint,false,false,A_TYPE,D_TYPE,null);
SetUnitState(t,UNIT_STATE_MANA,GetUnitState(t,UNIT_STATE_MANA) - MANA_DAMAGE -link.manadmgint);
DestroyEffect(AddSpecialEffect(STRIKE_FX,x,y));
if (USE_STUN) {
//If you have a stun system in your map feel free to use it here
DummyCaster['A001'].castTarget(link.owner,1,OrderId("thunderbolt"),x,y,t);
}
}
//UnitDamagePoint(link.caster,0.0,DAMAGE_AOE,x,y,GetRandomReal(DAMAGE_MIN,DAMAGE_MAX)+link.dmgint,true,true,A_TYPE,D_TYPE,null);
MoveLightningEx(link.l,false,GetUnitX(link.dummy),GetUnitY(link.dummy),GetUnitFlyHeight(link.dummy),x,y,GetUnitFlyHeight(t));
onLightning(link.l,LIGHTNING_D);
GroupClear(grp);
}
}));
GroupClear(grp);
}
}
else
{
this.z=this.z-SPEED_DROP;
SetUnitFlyHeight(this.dummy,this.z,0.0);
if(this.z<=0.0)
{
x=GetUnitX(this.dummy);y=GetUnitY(this.dummy);
link=this;
GroupEnumUnitsInRange(grp,x,y,DROP_DAMAGE_AOE,Filter(function()
{
unit t=GetFilterUnit();
if(UnitFilter(t,link.owner,DROP_SEARCH_FILTER))
{
UnitDamageTarget(link.caster,t,GetRandomReal(DAMAGE_MIN,DAMAGE_MAX)+link.dmgint,false,false,A_TYPE,D_TYPE,null);
if (DROP_USE_STUN) {
//If you have a stun system in your map feel free to use it here
DummyCaster['A001'].castTarget(link.owner,1,OrderId("thunderbolt"),0.,0.,t);
}
}
}));
DestroyEffect(AddSpecialEffect(GROUND_FX,x,y));
GroupClear(grp);
DestroyEffect(this.fx);
DestroyLightning(this.l);
DummyAddRecycleTimer(this.dummy,1.0);
//KillUnit(this.dummy);
this.caster=null;
this.dummy=null;
this.owner=null;
i=DestroyData(i);
}
}
}
i+=1;
}
}
//! runtextmacro Create("Data","ix","ic","data","tmr","function onLoop")
function onCast() -> boolean
{
unit u;
player p;
real x1,y1,x2,y2,a,d,inter,dmg,manadmg;
integer i,lvl;
data this;
if(GetSpellAbilityId()==SPELL_ID)
{
u=GetTriggerUnit();
p=GetOwningPlayer(u);
lvl=GetUnitAbilityLevel(u,SPELL_ID);
i=BALL_AMT+(BALL_AMTL*lvl);
d=BALL_DUR+(BALL_DURLVL*lvl);
inter=BALL_INTER-(BALL_INTERLV*lvl);
if(IsUnitType(u,UNIT_TYPE_HERO))
{
dmg=(GetHeroInt(u,true)/100.0)*DAMAGE_INT;
manadmg=(GetHeroInt(u,true)/100.0)*MANA_DAMAGE_INT;
}
else
{
dmg=DAMAGE_INT;
manadmg=MANA_DAMAGE_INT;
}
x1=GetUnitX(u);
y1=GetUnitY(u);
a=360.0/i;
while(i>0)
{
x2=x1+SUMMON_DIST*Cos((a*i)*bj_DEGTORAD);
y2=y1+SUMMON_DIST*Sin((a*i)*bj_DEGTORAD);
this=CreateData();
this.dx=x2;
this.dy=y2;
this.dur=d;
this.rate=0.0;
this.dmgint=dmg;
this.manadmgint=manadmg;
this.interval=inter;
this.inte=GetRandomReal(0.125,inter);
this.speed=(100.0/DISTANCE)*SPEED;
this.angle=a*i;
this.caster=u;
this.owner=p;
this.dummy=GetRecycledDummy(x2,y2,0.,a*a);//CreateUnit(DUM_OWNER,DUM_ID,x2,y2,a*i);
this.fx=AddSpecialEffectTarget(BALL_MODEL,this.dummy,BALL_ATCH);
this.l=AddLightningEx(LIGHTNING,false,0,0,0,0,0,0);
SetLightningColor(this.l,1,1,1,0);
SetUnitScale(this.dummy,MIN_SIZE,MIN_SIZE,MIN_SIZE);
//UnitAddAbility(this.dummy,'Amrf');UnitRemoveAbility(this.dummy,'Amrf');
this.dist=GetRandomReal(1.0,DISTANCE);
this.z=GetRandomReal(MIN_Z,MAX_Z);
i-=1;
}
u=null;
}
return false;
}
function onInit()
{
trigger t=CreateTrigger();
integer i=0;
TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT);
TriggerAddCondition(t,Filter(function onCast));
t=null;
}
}
}
//! endzinc
library DummyRecycler /*
// DummyRecycler v1.25
// by Flux
//
// A system that recycles dummy units while considering their facing angle.
// It can be used as attachment dummies for visual effects or as dummy caster.
//
// Why is recycling a unit important?
// Because creating a unit is is one of the slowest function in the game
// and there are reports that will always leave a permanent tiny bit of
// memory (0.04 KB).
// On average, retrieving a pending Dummy is approximately 4x faster compared
// to creating a new one and recycling a Dummy compared to removing it is
// approximately 1.3x faster.
// Furthermore, if you're using a lot of "Unit has entered map" events,
// using this system will even result to even more better performance
// because retrieving Dummy units does not cause that event to run.
*/ requires /*
nothing
*/ optional Table/*
if not found, this system will use a hashtable. Hashtables are limited to
255 per map.
*/ optional WorldBounds /*
if not found, this system will initialize its own Map Boundaries.
//
//
// Features:
//
// -- Dummy Sharing
// When a Dummy List gets low on unit count, it will borrow Dummy Units
// from the Dummy List with the highest unit count. The transfer is not
// instant because the shared Dummy Unit has to turn to the appropriate
// angle of its new Dummy List before it can be recycled.
// See BORROW_REQUEST.
//
// -- Self-balancing recycling algorithm
// Recycled Dummy Units will be thrown to the List having the least number
// of Dummy Units.
//
// -- Recycling least used
// Allows recycling a Dummy from the Dummy List with the highest
// unit count. It is useful when the facing angle of the Dummy Unit
// does not matter.
// See GetRecycledDummyAnyAngle.
//
// -- Self-adaptation
// When there are no free Dummy Units from a Dummy List, it will end up creating
// a new unit instead but that unit will be permanently added as a Dummy
// Unit to be recycled increasing the overall total Dummy Unit count.
//
// -- Count control
// Allows limiting the overall number of Dummy Units.
// See MAX_DUMMY_COUNT.
//
// -- Delayed Recycle
// Allows recycling Dummy Units after some delay to allocate time for the
// death animation of Special Effects to be seen.
// See DummyAddRecycleTimer.
//
// ******************************************************************
// ***************************** API: *******************************
// ******************************************************************
//
// function GetRecycledDummy takes real x, real y, real z, real facing returns unit
// - Retrieve an unused Dummy Unit from the List.
// - The equivalent of CreateUnit.
// - To use as a Dummy Caster, follow it with PauseUnit(dummy, false).
//
// function GetRecycledDummyAnyAngle takes real x, real y, real z returns unit
// - Use this function if the facing angle of the Dummy doesn't matter to you.
// - It will return a unit from the list having the highest number of unused Dummy Units.
// - To use as a Dummy Caster, follow it with PauseUnit(dummy, false).
//
// function RecycleDummy takes unit u returns nothing
// - Recycle the Dummy unit for it to be used again later.
// - The equivalent of RemoveUnit.
//
// function DummyAddRecycleTimer takes unit u, real time returns nothing
// - Recycle the Dummy unit after a certain time.
// - Use this to allocate time for the the death animation of an effect attached to the
// Dummy Unit to finish..
// - The equivalent of UnitApplyTimedLife.
//
// function ShowDummy takes unit u, boolean flag returns nothing
// - Shows/hides Dummy Unit without conflicting with the Locust ability.
//
//--------------------
// CREDITS
//--------------------
// Bribe - for the MissileRecycler (vJASS) where I got this concept from
// http://www.hiveworkshop.com/forums/jass-resources-412/system-missilerecycler-206086/
// - for the optional Table
// http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
// Vexorian - for the Attachable and Pitch Animation Model (dummy.mdx)
// http://www.wc3c.net/showthread.php?t=101150
// Maker and IcemanBo - for the unit permanent 0.04 KB memory leak of units.
// http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/memory-leaks-263410/
// Nestharus - for the data structure
// http://www.hiveworkshop.com/forums/2809461-post7.html
// - for the optional WorldBounds
// http://githubusercontent.com/nestharus/JASS/master/jass/Systems/WorldBounds/script.j
// =============================================================== //
// ====================== CONFIGURATION ========================== //
// =============================================================== */
globals
//The rawcode of the Dummy Unit
private constant integer DUMMY_ID = 'h000'
//The owner of the Dummy Unit
private constant player OWNER = Player(14)
//The number of indexed angle. The higher the value the:
// - Lesser the turning time for the Dummy Units.
// - Higher the total number of Dummy Units created at Map Initialization.
// Recommended Value: 10 (Max difference of 18 degrees)
private constant integer ANGLES_COUNT = 10
//The number of Dummy units per ANGLES_COUNT. The higher the value the:
// - Higher the number of units that can be recycled per angle, when
// no more units are in queue, the system will resort to use CreateUnit.
// - Higher the total number of Dummy Units created at Map Initialization.
// Recommended Value: 3 to 5 (for less overhead in Map Loading Screen)
private constant integer STORED_UNIT_COUNT = 3
//The maximum number of Dummy units that can exist. When the system resort
//to using CreateUnit, the unit will be permanently added to the Dummy
//List. To avoid spamming Dummy Units and having too much free Dummy
//Units to allocate, the maximum number of Dummy Units is capped.
// Recommended Value: 80 to 120
private constant integer MAX_DUMMY_COUNT = 100
//When a certain angle have less than BORROW_REQUEST units in its list,
//it will start to borrow Dummy Units from the list with the highest
//Dummy Unit count.
// Recommended Value: Half of maximum STORED_UNIT_COUNT
private constant integer BORROW_REQUEST = 5
//It will only return a Dummy if the current dummy is close
//to it's appropriate facing angle. This is to avoid returning
//a Dummy which is still turning to face it's list angle.
private constant real ANGLE_TOLERANCE = 10.0
//An additional option to automatically hide recycled dummy units in the
//corner of the map camera bounds
private constant boolean HIDE_ON_MAP_CORNER = true
endglobals
//Every time a new dummy unit is retrieved, it will apply this resets
//If it is redundant/you dont need it, remove it.
//! textmacro DUMMY_UNIT_RESET
call SetUnitScale(bj_lastCreatedUnit, 1, 0, 0)
call SetUnitVertexColor(bj_lastCreatedUnit, 255, 255, 255, 255)
call SetUnitAnimationByIndex(bj_lastCreatedUnit, 90)
call ShowDummy(bj_lastCreatedUnit, true)
//! endtextmacro
// =============================================================== //
// ==================== END CONFIGURATION ======================== //
// =============================================================== //
globals
private integer dummyCount = ANGLES_COUNT*STORED_UNIT_COUNT
private real array angle
private integer array count
private integer array countHead
private integer array countNext
private integer array countPrev
private integer array next
private integer array prev
private unit array dummy
private integer upper
private integer lower
private integer lastInstance
private constant real FACING_OFFSET = 180.0/ANGLES_COUNT
endglobals
static if HIDE_ON_MAP_CORNER and not LIBRARY_WorldBounds then
private module BoundsInit
readonly static real x
readonly static real y
private static method onInit takes nothing returns nothing
local rect map = GetWorldBounds()
set thistype.x = GetRectMaxX(map)
set thistype.y = GetRectMaxY(map)
call RemoveRect(map)
set map = null
endmethod
endmodule
private struct Bounds extends array
implement BoundsInit
endstruct
endif
private module M
static if LIBRARY_Table then
static Table tb
else
static hashtable hash = InitHashtable()
endif
private static method onInit takes nothing returns nothing
local real add = 360.0/ANGLES_COUNT
local real a = 0
local integer this = ANGLES_COUNT
local integer head = 0
local integer cHead = JASS_MAX_ARRAY_SIZE - 1 //avoid allocation collision
local integer i = R2I(MAX_DUMMY_COUNT/ANGLES_COUNT + 0.5)
set upper = STORED_UNIT_COUNT
set lower = STORED_UNIT_COUNT
static if LIBRARY_Table then
set tb = Table.create()
endif
//Initialize countHeads
loop
exitwhen i < 0
set countNext[cHead] = cHead
set countPrev[cHead] = cHead
set countHead[i] = cHead
set cHead = cHead - 1
set i = i - 1
endloop
set cHead = countHead[STORED_UNIT_COUNT] //All heads will be inserted here initially
//Create the Dummy units
loop
exitwhen a >= 360
//Initialize head
set next[head] = head
set prev[head] = head
set count[head] = STORED_UNIT_COUNT
set angle[head] = a
//Insert head in the Count List
set countNext[head] = cHead
set countPrev[head] = countPrev[cHead]
set countNext[countPrev[head]] = head
set countPrev[countNext[head]] = head
set i = 0
loop
exitwhen i >= STORED_UNIT_COUNT
//Queued Linked List
set next[this] = head
set prev[this] = prev[head]
set next[prev[this]] = this
set prev[next[this]] = this
static if HIDE_ON_MAP_CORNER then
static if LIBRARY_WorldBounds then
set dummy[this] = CreateUnit(OWNER, DUMMY_ID, WorldBounds.maxX, WorldBounds.maxY, a)
else
set dummy[this] = CreateUnit(OWNER, DUMMY_ID, Bounds.x, Bounds.y, a)
endif
else
set dummy[this] = CreateUnit(OWNER, DUMMY_ID, 0, 0, a)
endif
call PauseUnit(dummy[this], true)
static if LIBRARY_Table then
set tb[GetHandleId(dummy[this])] = this
else
call SaveInteger(hash, GetHandleId(dummy[this]), 0, this)
endif
set this = this + 1
set i = i + 1
endloop
set head = head + 1
set a = a + add
endloop
set lastInstance = this
endmethod
endmodule
private struct S extends array
implement M
endstruct
private function GetHead takes integer facing returns integer
if facing < 0 or facing >= 360 then
set facing = facing - (facing/360)*360
if facing < 0 then
set facing = facing + 360
endif
endif
return R2I((facing*ANGLES_COUNT/360.0))
endfunction
function ShowDummy takes unit u, boolean flag returns nothing
if IsUnitHidden(u) == flag then
call ShowUnit(u, flag)
if flag and GetUnitTypeId(u) == DUMMY_ID then
call UnitRemoveAbility(u, 'Aloc')
call UnitAddAbility(u, 'Aloc')
endif
endif
endfunction
function GetRecycledDummy takes real x, real y, real z, real facing returns unit
local integer head = GetHead(R2I(facing + FACING_OFFSET))
local integer this = next[head]
local integer cHead
//If there are Dummy Units in the Queue List already facing close to the appropriate angle
if this != head and RAbsBJ(GetUnitFacing(dummy[this]) - angle[head]) <= ANGLE_TOLERANCE then
//Remove from the Queue List
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
//For double free protection
set next[this] = -1
//Unit Properties
set bj_lastCreatedUnit = dummy[this]
call SetUnitX(bj_lastCreatedUnit, x)
call SetUnitY(bj_lastCreatedUnit, y)
call SetUnitFacing(bj_lastCreatedUnit, facing)
call SetUnitFlyHeight(bj_lastCreatedUnit, z, 0)
//! runtextmacro DUMMY_UNIT_RESET()
//Update Count and Bounds
set count[head] = count[head] - 1
//------------------------------------------------
// Unit Sharing
//------------------------------------------------
if count[head] < BORROW_REQUEST and count[countNext[countHead[upper]]] > count[head] then
set count[head] = count[head] + 1
set this = next[countNext[countHead[upper]]]
call SetUnitFacing(dummy[this], angle[head])
//Remove
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
//Add to the Current List
set next[this] = head
set prev[this] = prev[head]
set next[prev[this]] = this
set prev[next[this]] = this
set head = countNext[countHead[upper]]
set count[head] = count[head] - 1
endif
//---------------------------
//Update Count Lists
//---------------------------
//Remove from the current Count List
set countNext[countPrev[head]] = countNext[head]
set countPrev[countNext[head]] = countPrev[head]
//Add to the new Count List
set cHead = countHead[count[head]]
set countNext[head] = cHead
set countPrev[head] = countPrev[cHead]
set countNext[countPrev[head]] = head
set countPrev[countNext[head]] = head
//---------------------------
// Update Bounds
//---------------------------
set cHead = countHead[upper]
if countNext[cHead] == cHead then
set upper = upper - 1
endif
if count[head] < lower then
set lower = count[head]
endif
else
set bj_lastCreatedUnit = CreateUnit(OWNER, DUMMY_ID, x, y, facing)
call PauseUnit(bj_lastCreatedUnit, true)
call SetUnitFlyHeight(bj_lastCreatedUnit, z, 0)
if dummyCount < MAX_DUMMY_COUNT then
set this = lastInstance
//For double free protection
set next[this] = -1
set dummy[this] = bj_lastCreatedUnit
static if LIBRARY_Table then
set S.tb[GetHandleId(bj_lastCreatedUnit)] = this
else
call SaveInteger(S.hash, GetHandleId(bj_lastCreatedUnit), 0, this)
endif
set lastInstance = lastInstance + 1
endif
set dummyCount = dummyCount + 1
endif
return bj_lastCreatedUnit
endfunction
function RecycleDummy takes unit u returns nothing
static if LIBRARY_Table then
local integer this = S.tb[GetHandleId(u)]
else
local integer this = LoadInteger(S.hash, GetHandleId(u), 0)
endif
local integer head
local integer cHead
//If the unit is a legit Dummy Unit
if this > 0 and next[this] == -1 then
//Find where to insert based on the list having the least number of units
set head = countNext[countHead[lower]]
set next[this] = head
set prev[this] = prev[head]
set next[prev[this]] = this
set prev[next[this]] = this
//Update Status
call SetUnitFacing(u, angle[head])
call PauseUnit(u, true)
call SetUnitOwner(u, OWNER, false)
static if HIDE_ON_MAP_CORNER then
static if LIBRARY_WorldBounds then
call SetUnitX(u, WorldBounds.maxX)
call SetUnitY(u, WorldBounds.maxY)
else
call SetUnitX(u, Bounds.x)
call SetUnitY(u, Bounds.y)
endif
else
call SetUnitScale(u, 0, 0, 0)
call SetUnitVertexColor(u, 0, 0, 0, 0)
endif
set count[head] = count[head] + 1
//---------------------------
// Update Count Lists
//---------------------------
//Remove
set countNext[countPrev[head]] = countNext[head]
set countPrev[countNext[head]] = countPrev[head]
//Add to the new Count List
set cHead = countHead[count[head]]
set countNext[head] = cHead
set countPrev[head] = countPrev[cHead]
set countNext[countPrev[head]] = head
set countPrev[countNext[head]] = head
//---------------------------
// Update Bounds
//---------------------------
set cHead = countHead[lower]
if countNext[cHead] == cHead then
set lower = lower + 1
endif
if count[head] > upper then
set upper = count[head]
endif
elseif this == 0 then
call RemoveUnit(u)
debug elseif next[this] != -1 then
debug call BJDebugMsg("|cffffcc00[DummyRecycler]:|r Attempted to recycle a pending/free Dummy Unit.")
endif
endfunction
private function Expires takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
static if LIBRARY_Table then
call RecycleDummy(S.tb.unit[id])
call S.tb.unit.remove(id)
else
call RecycleDummy(LoadUnitHandle(S.hash, id, 0))
call FlushChildHashtable(S.hash, id)
endif
call DestroyTimer(t)
set t = null
endfunction
function DummyAddRecycleTimer takes unit u, real time returns nothing
local timer t = CreateTimer()
static if LIBRARY_Table then
set S.tb.unit[GetHandleId(t)] = u
else
call SaveUnitHandle(S.hash, GetHandleId(t), 0, u)
endif
call TimerStart(t, time, false, function Expires)
set t = null
endfunction
function GetRecycledDummyAnyAngle takes real x, real y, real z returns unit
return GetRecycledDummy(x, y, z, angle[countNext[countHead[upper]]])
endfunction
// runtextmacro DUMMY_DEBUG_TOOLS()
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DummyCaster /* v2.0.0.1
*************************************************************************************
*
* Dummy caster for casting spells
*
* Spells must have 0 cooldown, 92083 range, and cost 0 mana. Spells must be instant and
* can't share the same order as other spells on the dummy caster.
*
*************************************************************************************
*
* */uses/*
* */ optional UnitIndexer, /* hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
*
************************************************************************************
* SETTINGS
*/
globals
constant integer UNITS_DUMMY_CASTER = 'h001'
/*************************************************************************************
*
* PLAYER_OWNER
*
* Owner of dummy caster
*
*************************************************************************************/
private constant player PLAYER_OWNER = Player(15)
endglobals
/*
************************************************************************************
*
* Dummy at position 32256,32256
*
* struct DummyCaster extends array
*
* method cast takes player castingPlayer, integer abilityLevel, integer order, real x, real y returns boolean
* - call DummyCaster[abilityId].cast(...)
* method castTarget takes player castingPlayer, integer abilityLevel, integer order, ,real dummycaster_px, real dummycaster_py widget t returns boolean
* - call DummyCaster[abilityId].castTarget(...)
* method castPoint takes player castingPlayer, integer abilityLevel, integer order, real dummycaster_px, real dummycaster_py, real x, real y returns boolean
* - call DummyCaster[abilityId].castPoint(...)
*
************************************************************************************/
globals
private unit u
endglobals
private module N
private static method onInit takes nothing returns nothing
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled=false
set u=CreateUnit(PLAYER_OWNER,UNITS_DUMMY_CASTER,0,0,0)
set UnitIndexer.enabled=true
else
set u=CreateUnit(PLAYER_OWNER,UNITS_DUMMY_CASTER,0,0,0)
endif
call SetUnitPosition(u,32256,32256)
endmethod
endmodule
struct DummyCaster extends array
implement N
private static method prep takes integer a, player p, integer l returns nothing
call UnitAddAbility(u, a)
if (1 < l) then
call SetUnitAbilityLevel(u, a, l)
endif
if (null != p) then
call SetUnitOwner(u, p, false)
endif
endmethod
private static method finish takes integer a returns nothing
call SetUnitOwner(u, PLAYER_OWNER, false)
call UnitRemoveAbility(u, a)
endmethod
method unit takes nothing returns unit
return u
endmethod
method cast takes player p, integer level, integer order, real x, real y returns boolean
local boolean b
call SetUnitX(u, x)
call SetUnitY(u, y)
call prep(this, p, level)
set b = IssueImmediateOrderById(u,order)
call finish(this)
call SetUnitPosition(u, 32256, 32256)
return b
endmethod
method castTarget takes player p, integer level, integer order, real dummycaster_px, real dummycaster_py, unit t returns boolean
local boolean b
call SetUnitX(u, dummycaster_px)
call SetUnitY(u, dummycaster_py)
call prep(this, p, level)
call UnitShareVision(t,p,true)
set b = IssueTargetOrderById(u,order,t)
call UnitShareVision(t,p,false)
call finish(this)
call SetUnitPosition(u, 32256, 32256)
return b
endmethod
method castPoint takes player p, integer level, integer order, real dummycaster_px, real dummycaster_py, real x, real y returns boolean
local boolean b
call SetUnitX(u, dummycaster_px)
call SetUnitY(u, dummycaster_py)
call prep(this, p, level)
set b = IssuePointOrderById(u,order,x,y)
call finish(this)
call SetUnitPosition(u, 32256, 32256)
return b
endmethod
endstruct
endlibrary
//TESH.scrollpos=174
//TESH.alwaysfold=0
library FilteringSystem /* v3.4.0 */
/*
************************************************************************************************************************
* Filtering System's API v3.4.0
* by The Wrecker
*
* Credits:
* - God : God supports anyone.
* - Nestharus : Algorithm of this system is
* shaped in time by ideas of him, and as you
* see, the algorithm is perfect; many other
* thanks to him for many other useful hints.
* THIS SYSTEM OWES ITS QUALITY TO Nestharus.
* - Magtheridon96 : His hints made the way
* to create this system easier and more
* efficient, many thanks to him. His
* advocacy for this system was awesome:
* [url]http://www.hiveworkshop.com/forums/jass-resources-412/filtering-system-240887/index7.html#post2471786[/url]
*
* by TheWrecker
*
* [url]http://www.hiveworkshop.com/forums/jass-resources-412/filtering-system-240887/[/url]
*
* Contents:
*
* - Functions
* - How to use Filters
* - How to use Filtering System
* - Settings
* - Full Example
* - Side Functions
* - Constants (filters)
*
************************************************************************************************************************
* Functions:
*
* - function UnitFilter takes unit whichUnit, player whichPlayer, integer filter returns boolean
*
* + It will check if 'whichUnit' meets given conditions or not.
* + 'whichPlayer' is only required when Alliance and Visibility filters
* are applied and must be passed 'null' when not using Alliance and
* Visibility filters.
* + 'filter' is an integer explained in section "How to use Filters".
*
* - function ItemFilter takes item whichItem, integer filter returns boolean
*
* + It checks if 'whichItem' passes given filters or not.
* + 'filter' is an integer explained in section "How to use Filters".
*
* - function PlayerFilter takes player whichPlayer, player otherPlayer, integer filter returns boolean
*
* + It checks whether 'whichPlayer' meets given filters or not.
* + 'otherPlayer' is the other player used to check two-player related
* filters: Shared Units, Shared Vision, Alliance.
* if not using the above filters, you can pass 'null' as 'otherPlayer'.
* + 'filter' is an integer explained in section "How to use Filters".
*
************************************************************************************************************************
* How to use Filters:
*
* - 'filter' is an hexadecimal integer which is made like this:
* Filter1 + Filter2 + Filter3 + ...
* + You don't have to do any mathematics, only type your
* desired filters' names like above.
*
* - Filters in Filtring System are in 3 groups: Unit, Item, Player.
* + Use each group only with its related filtering function.
*
* - Filter rules are as below:
* <Filter1 and Filter2 are opposites like Dead and Alive>
* + Filter1: Units matching it will pass.
* + Filter1 + Filter 2: NO UNIT WILL PASS.
* + nothing: All units will pass.
* + If you didn't get what above means take a look to section
* "Full Example"
*
************************************************************************************************************************
* How to use Filtering System:
*
* - vJass and Jass:
* + A simple line:
* if [Unit/Player/Item]Filter(argument1,argument2[if exists],'filter') then
* //Scripts
* endif
*
* - GUI:
* + A Custom Script (New Action -> General -> Custom Script) line:
* Custom Script : if [Unit/Player/Item]Filter(argument1,argument2[if exists],'filter') then
* //Scripts
* Custom Script : endif
*
************************************************************************************************************************
* Settings:
*
* - Ward and Dummy classificators:
*
* */globals/*
*
* CONFIGURABLE PART
*
* */
constant integer ABILITY_WARD_CLASSIFIER = 'Alit'/*
* This system checks for a spell to realize the fact that a unit is
* a ward or not, because perhaps you add a ward classification to a unit
* to remove its spell icons, but that unit is not really a ward, so instead
* of checking for classification we use a spell to define ward classification;
* change it to your desired spell or leave it as it is.
*
* */
constant integer ABILITY_DUMMY_CLASSIFIER = 'Aloc'/*
* This system checks for a spell to realize the fact that a unit is
* a dummy or not, change this to your desired spell or leave it as it is, note
* that this system doesn't do anything about dummies, in fact when it finds this
* spell in a unit, it completely ignores that unit and that unit will not pass
* the filtering, so if you want a specific unit to not pass this filtering, add
* this spell to it.
*
* END OF CONFIGURABLE PART
*
************************************************************************************************************************
* Full Example:
*
* - Alive, enemy ranged heroes:
* + if UnitFilter(Target,Caster,FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_HERO + FS_UNIT_RANGED) then
* + NOTE : ORDER OF FILTERS IS NOT IMPORTANT.
*
* - Non-Summoned undead units:
* + if UnitFilter(Target,null,FS_UNIT_UNDEAD + FS_UNIT_NON_SUMMONED) then
*
* - All units:
* + if UnitFilter(Target,null,0) then
* + Pay attention to zero (0).
*
* - No unit:
* + if UnitFilter(Target,null,FS_UNIT_ALIVE + FS_UNIT_DEAD) then
* + 'FS_UNIT_HERO + FS_UNIT_NON_HERO','FS_UNIT_ALLY + FS_UNIT_ENEMY' and
* other opposites can be placed as 'FS_UNIT_ALIVE + FS_UNIT_DEAD'.
*
* - Ally computer players with shared vision:
* + if PlayerFilter(Player1,Player2,FS_PLAYER_ALLY + FS_PLAYER_COMPUTER + FS_PLAYER_VISION) then
*
* - Sellable, Campaign class items which are not owned:
* + if ItemFilter(Item,FS_ITEM_SELLABLE + FS_ITEM_CAMPAIGN + FS_ITEM_NON_OWNED) then
*
************************************************************************************************************************
* Side Functions:
*
* Because of the unique algorithm of this system, there are unpredicted functions
* that this system can have, one of them is known and others may be found later.
*
* - Mixing the filters into single filter (Constraints):
* (found by Magtheridon96)
*
* This is the method of mixing some filters and converting them into a
* single filter to use that single filter instead of using many filters
* more and more again. An example should show you the way:
*
* integer USUAL = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_ORGANIC
*
* this way, you will type in 'USUAL' everytime your filter contain these
* three filters instead of typing all three of them.
*
* + Be sure that no filter is repeated two times in a single
* constraint.
* + If sum of some constraints contain repeated filters, be sure
* to substract that filter until there is only one filter of that
* type left, an example is needed:
*
* USUAL = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_ORGANIC
* HERO_2 = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_IMMUNE
* UNDEAD_9 = FS_UNIT_ALIVE + FS_UNIT_UNDEAD
* USUAL_HERO = USUAL + FS_UNIT_HERO
*
* If you want to use USUAL + HERO_2 + UNDEAD_9, be sure to
* use it this way (FS_UNIT_ALIVE is repeated 3 times,
* FS_UNIT_ENEMY is repeated 2 times):
* USUAL + HERO_2 + UNDEAD_9 - 2*FS_UNIT_ALIVE - FS_UNIT_ENEMY
*
* To use this method, you have to define your own constraints using
* this way:
*
* globals
* constant integer CONSTRAINT_NAME = COND1 + COND2 + ...
* endglobals
*
* If you are GUI, you have to put these three lines in three adjacent
* Custom Script lines.
*
************************************************************************************************************************
* Constants (filters):
* - These are the filters available:
*
* FS_UNIT_ENEMY
* FS_UNIT_ALLY
* FS_UNIT_ALIVE
* FS_UNIT_DEAD
* FS_UNIT_ORGANIC
* FS_UNIT_STRUCTURE
* FS_UNIT_MECHANICAL
* FS_UNIT_HERO
* FS_UNIT_NON_HERO
* FS_UNIT_IMMUNE //magic immunity, ofcourse!
* FS_UNIT_NON_IMMUNE
* FS_UNIT_SUMMONED
* FS_UNIT_NON_SUMMONED
* FS_UNIT_VISIBLE
* FS_UNIT_INVISIBLE
* FS_UNIT_WARD
* FS_UNIT_NON_WARD
* FS_UNIT_ANCIENT
* FS_UNIT_NON_ANCIENT
* FS_UNIT_GROUND
* FS_UNIT_FLYING
* FS_UNIT_MELEE
* FS_UNIT_RANGED
* FS_UNIT_UNDEAD
* FS_UNIT_NON_UNDEAD
*
* FS_ITEM_OWNED
* FS_ITEM_NON_OWNED
* FS_ITEM_RUNE //includes runes, tomes, powerups, etc.
* FS_ITEM_NON_RUNE
* FS_ITEM_SELLABLE
* FS_ITEM_NON_SELLABLE
* FS_ITEM_PAWNABLE
* FS_ITEM_NON_PAWNABLE
* FS_ITEM_PERMANENT
* FS_ITEM_NON_PERMANENT
* FS_ITEM_CHARGED
* FS_ITEM_NON_CHARGED
* FS_ITEM_POWERUP
* FS_ITEM_NON_POWERUP
* FS_ITEM_ARTIFACT
* FS_ITEM_NON_ARTIFACT
* FS_ITEM_PURCHASABLE
* FS_ITEM_NON_PURCHASABLE
* FS_ITEM_CAMPAIGN
* FS_ITEM_NON_CAMPAIGN
* FS_ITEM_MISC
* FS_ITEM_NON_MISC
* FS_ITEM_VISIBLE
* FS_ITEM_HIDDEN
*
* FS_PLAYER_ENEMY
* FS_PLAYER_ALLY
* FS_PLAYER_USER
* FS_PLAYER_COMPUTER
* FS_PLAYER_PLAYING
* FS_PLAYER_LEFT //also includes non-used slots.
* FS_PLAYER_NEUTRAL
* FS_PLAYER_NON_NEUTRAL
* FS_PLAYER_VISION //shared vision.
* FS_PLAYER_NON_VISION
* FS_PLAYER_CONTROL //shared unit control.
* FS_PLAYER_NON_CONTROL
*
************************************************************************************************************************
* -----END OF API-----
*/
constant integer FS_UNIT_ENEMY = 0x1
constant integer FS_UNIT_ALLY = 0x2
constant integer FS_UNIT_ALIVE = 0x4
constant integer FS_UNIT_DEAD = 0x8
constant integer FS_UNIT_ORGANIC = 0x10
constant integer FS_UNIT_STRUCTURE = 0x20
constant integer FS_UNIT_MECHANICAL = 0x40
constant integer FS_UNIT_HERO = 0x80
constant integer FS_UNIT_NON_HERO = 0x100
constant integer FS_UNIT_IMMUNE = 0x200
constant integer FS_UNIT_NON_IMMUNE = 0x400
constant integer FS_UNIT_SUMMONED = 0x800
constant integer FS_UNIT_NON_SUMMONED = 0x1000
constant integer FS_UNIT_VISIBLE = 0x2000
constant integer FS_UNIT_INVISIBLE = 0x4000
constant integer FS_UNIT_WARD = 0x8000
constant integer FS_UNIT_NON_WARD = 0x10000
constant integer FS_UNIT_ANCIENT = 0x20000
constant integer FS_UNIT_NON_ANCIENT = 0x40000
constant integer FS_UNIT_GROUND = 0x80000
constant integer FS_UNIT_FLYING = 0x100000
constant integer FS_UNIT_MELEE = 0x200000
constant integer FS_UNIT_RANGED = 0x400000
constant integer FS_UNIT_UNDEAD = 0x800000
constant integer FS_UNIT_NON_UNDEAD = 0x1000000
constant integer FS_UNIT_NON_STRUCTURE = 0x2000000
constant integer FS_ITEM_OWNED = 0x1
constant integer FS_ITEM_NON_OWNED = 0x2
constant integer FS_ITEM_RUNE = 0x4
constant integer FS_ITEM_NON_RUNE = 0x8
constant integer FS_ITEM_SELLABLE = 0x10
constant integer FS_ITEM_NON_SELLABLE = 0x20
constant integer FS_ITEM_PAWNABLE = 0x40
constant integer FS_ITEM_NON_PAWNABLE = 0x80
constant integer FS_ITEM_PERMANENT = 0x100
constant integer FS_ITEM_NON_PERMANENT = 0x200
constant integer FS_ITEM_CHARGED = 0x400
constant integer FS_ITEM_NON_CHARGED = 0x800
constant integer FS_ITEM_POWERUP = 0x1000
constant integer FS_ITEM_NON_POWERUP = 0x2000
constant integer FS_ITEM_ARTIFACT = 0x4000
constant integer FS_ITEM_NON_ARTIFACT = 0x8000
constant integer FS_ITEM_PURCHASABLE = 0x10000
constant integer FS_ITEM_NON_PURCHASABLE = 0x20000
constant integer FS_ITEM_CAMPAIGN = 0x40000
constant integer FS_ITEM_NON_CAMPAIGN = 0x80000
constant integer FS_ITEM_MISC = 0x100000
constant integer FS_ITEM_NON_MISC = 0x200000
constant integer FS_ITEM_VISIBLE = 0x400000
constant integer FS_ITEM_HIDDEN = 0x800000
constant integer FS_PLAYER_ENEMY = 0x1
constant integer FS_PLAYER_ALLY = 0x2
constant integer FS_PLAYER_USER = 0x4
constant integer FS_PLAYER_COMPUTER = 0x8
constant integer FS_PLAYER_PLAYING = 0x10
constant integer FS_PLAYER_LEFT = 0x20
constant integer FS_PLAYER_NEUTRAL = 0x40
constant integer FS_PLAYER_NON_NEUTRAL = 0x80
constant integer FS_PLAYER_VISION = 0x100
constant integer FS_PLAYER_NON_VISION = 0x200
constant integer FS_PLAYER_CONTROL = 0x400
constant integer FS_PLAYER_NON_CONTROL = 0x800
endglobals
function UnitFilter takes unit whichUnit, player whichPlayer, integer filter returns boolean
set filter = filter + 0x1
if filter > 0x2000 then
// NEW, NON-STRUCTURE
if filter > 0x2000000 then
set filter = filter - 0x2000000
if IsUnitType(whichUnit, UNIT_TYPE_STRUCTURE) then
return false
endif
endif
if filter > 0x1000000 then
set filter = filter - 0x1000000
if IsUnitType(whichUnit, UNIT_TYPE_UNDEAD) then
return false
endif
endif
if filter > 0x800000 then
set filter = filter - 0x800000
if not IsUnitType(whichUnit, UNIT_TYPE_UNDEAD) then
return false
endif
endif
if filter > 0x400000 then
set filter = filter - 0x40000
if not IsUnitType(whichUnit, UNIT_TYPE_RANGED_ATTACKER) then
return false
endif
endif
if filter > 0x200000 then
set filter = filter - 0x200000
if not IsUnitType(whichUnit, UNIT_TYPE_MELEE_ATTACKER) then
return false
endif
endif
if filter > 0x100000 then
set filter = filter - 0x100000
if not IsUnitType(whichUnit, UNIT_TYPE_FLYING) then
return false
endif
endif
if filter > 0x80000 then
set filter = filter - 0x80000
if not IsUnitType(whichUnit, UNIT_TYPE_GROUND) then
return false
endif
endif
if filter > 0x40000 then
set filter = filter - 0x40000
if IsUnitType(whichUnit, UNIT_TYPE_ANCIENT) then
return false
endif
endif
if filter > 0x20000 then
set filter = filter - 0x20000
if not IsUnitType(whichUnit, UNIT_TYPE_ANCIENT) then
return false
endif
endif
if filter > 0x10000 then
set filter = filter - 0x10000
if GetUnitAbilityLevel(whichUnit,ABILITY_WARD_CLASSIFIER)!=0 then
return false
endif
endif
if filter > 0x8000 then
set filter = filter - 0x8000
if GetUnitAbilityLevel(whichUnit,ABILITY_WARD_CLASSIFIER)==0 then
return false
endif
endif
if filter > 0x4000 then
set filter = filter - 0x4000
if IsUnitVisible(whichUnit,whichPlayer) then
return false
endif
endif
if filter > 0x2000 then
set filter = filter - 0x2000
if not IsUnitVisible(whichUnit,whichPlayer) then
return false
endif
endif
endif
if filter < 0x2001 then
if filter > 0x1000 then
set filter = filter - 0x1000
if IsUnitType(whichUnit, UNIT_TYPE_SUMMONED) then
return false
endif
endif
if filter > 0x800 then
set filter = filter - 0x800
if not IsUnitType(whichUnit, UNIT_TYPE_SUMMONED) then
return false
endif
endif
if filter > 0x400 then
set filter = filter - 0x400
if IsUnitType(whichUnit, UNIT_TYPE_MAGIC_IMMUNE) then
return false
endif
endif
if filter > 0x200 then
set filter = filter - 0x200
if not IsUnitType(whichUnit, UNIT_TYPE_MAGIC_IMMUNE) then
return false
endif
endif
if filter > 0x100 then
set filter = filter - 0x100
if IsUnitType(whichUnit, UNIT_TYPE_HERO) then
return false
endif
endif
if filter > 0x80 then
set filter = filter - 0x80
if not IsUnitType(whichUnit, UNIT_TYPE_HERO) then
return false
endif
endif
if filter > 0x40 then
set filter = filter - 0x40
if not IsUnitType(whichUnit,UNIT_TYPE_MECHANICAL) then
return false
endif
endif
if filter > 0x20 then
set filter = filter - 0x20
if not IsUnitType(whichUnit,UNIT_TYPE_STRUCTURE) then
return false
endif
endif
if filter > 0x10 then
set filter = filter - 0x10
if IsUnitType(whichUnit,UNIT_TYPE_STRUCTURE) or IsUnitType(whichUnit,UNIT_TYPE_MECHANICAL) then
return false
endif
endif
if filter > 0x8 then
set filter = filter - 0x8
if GetWidgetLife(whichUnit)>0.405 and IsUnitType(whichUnit,UNIT_TYPE_DEAD)==false then
return false
endif
endif
if filter > 0x4 then
set filter = filter - 0x4
if GetWidgetLife(whichUnit)<=0.405 or IsUnitType(whichUnit,UNIT_TYPE_DEAD) then
return false
endif
endif
if filter > 0x2 then
set filter = filter - 0x2
if IsUnitEnemy(whichUnit,whichPlayer) then
return false
endif
endif
if filter > 0x1 then
set filter = filter - 0x1
if not IsUnitEnemy(whichUnit,whichPlayer) then
return false
endif
endif
endif
if GetUnitAbilityLevel(whichUnit,ABILITY_DUMMY_CLASSIFIER)!=0 then
return false
endif
return true
endfunction
function ItemFilter takes item whichItem, integer filter returns boolean
set filter = filter + 0x1
if filter > 0x2000 then
if filter > 0x800000 then
set filter = filter - 0x800000
if not IsItemVisible(whichItem) then
return false
endif
endif
if filter > 0x400000 then
set filter = filter - 0x40000
if IsItemVisible(whichItem) then
return false
endif
endif
if filter > 0x200000 then
set filter = filter - 0x200000
if GetItemType(whichItem)==ITEM_TYPE_MISCELLANEOUS then
return false
endif
endif
if filter > 0x100000 then
set filter = filter - 0x100000
if GetItemType(whichItem)!=ITEM_TYPE_MISCELLANEOUS then
return false
endif
endif
if filter > 0x80000 then
set filter = filter - 0x80000
if GetItemType(whichItem)==ITEM_TYPE_CAMPAIGN then
return false
endif
endif
if filter > 0x40000 then
set filter = filter - 0x40000
if GetItemType(whichItem)!=ITEM_TYPE_CAMPAIGN then
return false
endif
endif
if filter > 0x20000 then
set filter = filter - 0x20000
if GetItemType(whichItem)==ITEM_TYPE_PURCHASABLE then
return false
endif
endif
if filter > 0x10000 then
set filter = filter - 0x10000
if GetItemType(whichItem)!=ITEM_TYPE_PURCHASABLE then
return false
endif
endif
if filter > 0x8000 then
set filter = filter - 0x8000
if GetItemType(whichItem)==ITEM_TYPE_ARTIFACT then
return false
endif
endif
if filter > 0x4000 then
set filter = filter - 0x4000
if GetItemType(whichItem)!=ITEM_TYPE_ARTIFACT then
return false
endif
endif
if filter > 0x2000 then
set filter = filter - 0x2000
if GetItemType(whichItem)==ITEM_TYPE_POWERUP then
return false
endif
endif
endif
if filter < 0x2001 then
if filter > 0x1000 then
set filter = filter - 0x1000
if GetItemType(whichItem)!=ITEM_TYPE_POWERUP then
return false
endif
endif
if filter > 0x800 then
set filter = filter - 0x800
if GetItemType(whichItem)==ITEM_TYPE_CHARGED then
return false
endif
endif
if filter > 0x400 then
set filter = filter - 0x400
if GetItemType(whichItem)!=ITEM_TYPE_CHARGED then
return false
endif
endif
if filter > 0x200 then
set filter = filter - 0x200
if GetItemType(whichItem)==ITEM_TYPE_PERMANENT then
return false
endif
endif
if filter > 0x100 then
set filter = filter - 0x100
if GetItemType(whichItem)!=ITEM_TYPE_PERMANENT then
return false
endif
endif
if filter > 0x80 then
set filter = filter - 0x80
if IsItemPawnable(whichItem) then
return false
endif
endif
if filter > 0x40 then
set filter = filter - 0x40
if not IsItemPawnable(whichItem) then
return false
endif
endif
if filter > 0x20 then
set filter = filter - 0x20
if IsItemSellable(whichItem) then
return false
endif
endif
if filter > 0x10 then
set filter = filter - 0x10
if not IsItemSellable(whichItem) then
return false
endif
endif
if filter > 0x8 then
set filter = filter - 0x8
if IsItemPowerup(whichItem) then
return false
endif
endif
if filter > 0x4 then
set filter = filter - 0x4
if not IsItemPowerup(whichItem) then
return false
endif
endif
if filter > 0x2 then
set filter = filter - 0x2
if IsItemOwned(whichItem) then
return false
endif
endif
if filter > 0x1 then
set filter = filter - 0x1
if not IsItemOwned(whichItem) then
return false
endif
endif
endif
return true
endfunction
function PlayerFilter takes player whichPlayer, player otherPlayer, integer filter returns boolean
if filter > 0x800 then
set filter = filter - 0x800
if GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_CONTROL) then
return false
endif
endif
if filter > 0x400 then
set filter = filter - 0x400
if not GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_CONTROL) then
return false
endif
endif
if filter > 0x200 then
set filter = filter - 0x200
if GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_VISION) then
return false
endif
endif
if filter > 0x100 then
set filter = filter - 0x100
if not GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_VISION) then
return false
endif
endif
if filter > 0x80 then
set filter = filter - 0x80
if (whichPlayer==Player(12) or whichPlayer==Player(13) or whichPlayer==Player(14) or whichPlayer==Player(15)) then
return false
endif
endif
if filter > 0x40 then
set filter = filter - 0x40
if (not(whichPlayer==Player(12) or whichPlayer==Player(13) or whichPlayer==Player(14) or whichPlayer==Player(15))) then
return false
endif
endif
if filter > 0x20 then
set filter = filter - 0x20
if GetPlayerSlotState(whichPlayer)!=PLAYER_SLOT_STATE_LEFT then
return false
endif
endif
if filter > 0x10 then
set filter = filter - 0x10
if GetPlayerSlotState(whichPlayer)!=PLAYER_SLOT_STATE_PLAYING then
return false
endif
endif
if filter > 0x8 then
set filter = filter - 0x8
if GetPlayerController(whichPlayer)!=MAP_CONTROL_COMPUTER then
return false
endif
endif
if filter > 0x4 then
set filter = filter - 0x4
if GetPlayerController(whichPlayer)!=MAP_CONTROL_USER then
return false
endif
endif
if filter > 0x2 then
set filter = filter - 0x2
if IsPlayerEnemy(whichPlayer,otherPlayer) then
return false
endif
endif
if filter > 0x1 then
set filter = filter - 0x1
if IsPlayerAlly(whichPlayer,otherPlayer) then
return false
endif
endif
return true
endfunction
endlibrary
//TESH.scrollpos=24
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.1.0.1
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must either
* return a boolean (false) or nothing. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
* - Don't destroy a trigger unless you really know what you're doing.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent takes playerunitevent whichEvent, code whichFunction returns nothing
* - Registers code that will execute when an event fires.
* - function RegisterPlayerUnitEventForPlayer takes playerunitevent whichEvent, code whichFunction, player whichPlayer returns nothing
* - Registers code that will execute when an event fires for a certain player.
* - function GetPlayerUnitEventTrigger takes playerunitevent whichEvent returns trigger
* - Returns the trigger corresponding to ALL functions of a playerunitevent.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function GetPlayerUnitEventTrigger takes playerunitevent p returns trigger
return t[GetHandleId(p)]
endfunction
endlibrary
//TESH.scrollpos=60
//TESH.alwaysfold=0
struct test
private static constant integer Creeps_Amount = 5
private static constant real Revive_Duration = 2.0
private static constant real Periodic = 0.031250
private static constant timer tmr = CreateTimer()
private static integer ix = 0
private static integer array ic
private unit u
private real d
private static method onLoop takes nothing returns nothing
local thistype this
local integer i=1
local real x
local real y
local real a
loop
exitwhen i>ix
set this=ic[i]
set d=d-Periodic
if d<=0.0 then
set x=GetStartLocationX(0)
set y=GetStartLocationY(0)
if IsUnitType(u,UNIT_TYPE_HERO) then
call ReviveHero(u,x,y,true)
else
set a=GetRandomReal(0,360)
call CreateUnit(GetOwningPlayer(u),GetUnitTypeId(u),x+800*Cos(a*bj_DEGTORAD),y+800*Sin(a*bj_DEGTORAD),a)
call RemoveUnit(u)
endif
set u=null
call deallocate()
set ic[i]=ic[ix]
set ix=ix-1
set i=i-1
if ix==0 then
call PauseTimer(tmr)
endif
endif
set i=i+1
endloop
endmethod
private static method onDeath takes nothing returns nothing
local thistype this
local unit u=GetTriggerUnit()
if GetUnitAbilityLevel(u,'Aloc')==0 and not IsUnitType(u,UNIT_TYPE_SUMMONED) then
set this=allocate()
set ix=ix+1
set ic[ix]=this
set .u=u
set d=Revive_Duration
if ix==1 then
call TimerStart(tmr,Periodic,true,function thistype.onLoop)
endif
endif
endmethod
private static method onInit takes nothing returns nothing
local real x=GetStartLocationX(0)
local real y=GetStartLocationY(0)
local integer i=1
local player p=Player(0)
call CreateUnit(p,'Hblm',x,y,GetRandomReal(0,360))
call CreateItem('ciri',x,y)
set p=Player(PLAYER_NEUTRAL_AGGRESSIVE)
loop
exitwhen i>Creeps_Amount
call CreateItem('ciri',x,y)
call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(0*bj_DEGTORAD),y+800*Sin(0*bj_DEGTORAD),GetRandomReal(1,360))
call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(90*bj_DEGTORAD),y+800*Sin(90*bj_DEGTORAD),GetRandomReal(1,360))
call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(180*bj_DEGTORAD),y+800*Sin(180*bj_DEGTORAD),GetRandomReal(1,360))
call CreateUnit(p,ChooseRandomCreep(GetRandomInt(1,5)),x+800*Cos(270*bj_DEGTORAD),y+800*Sin(270*bj_DEGTORAD),GetRandomReal(1,360))
set i=i+1
endloop
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,function thistype.onDeath)
set p=null
endmethod
endstruct