Name | Type | is_array | initial_value |
Amaterasu_AT | attacktype | No | |
Amaterasu_Backlash | real | Yes | |
Amaterasu_Base_Radius | real | Yes | |
Amaterasu_BurnSFX | string | No | |
Amaterasu_Damage | real | Yes | |
Amaterasu_DamageIncPerSecond | real | Yes | |
Amaterasu_Dissipation | boolean | Yes | |
Amaterasu_DissipationFactor | real | No | |
Amaterasu_DissipationTime | real | No | |
Amaterasu_DT | damagetype | No | |
Amaterasu_Dummy | unit | Yes | |
Amaterasu_Expand_Radius | real | Yes | |
Amaterasu_FinalDamage | real | Yes | |
Amaterasu_PainSFX | string | No | |
Amaterasu_PainSFXAttach | string | No | |
Amaterasu_Radius | real | Yes | |
Amaterasu_SFX_Form | effect | Yes | |
Amaterasu_Target | unit | No | |
AncientWendigo | unit | No | |
BetterLoot | integer | No | |
BossLoot | integer | No | |
Crossbow1 | unit | No | |
Crossbow2 | unit | No | |
CrystalDragon | unit | No | |
Deathknight1 | unit | No | |
Deathknight2 | unit | No | |
Demonoverlord | unit | No | |
Dharol1 | unit | No | |
Dharol2 | unit | No | |
Dialog | dialog | No | |
Dialog2 | dialog | No | |
Dipper_Phases | integer | Yes | |
Double | button | No | |
Dragon1 | group | No | |
Dragon2 | group | No | |
Dragon3 | group | No | |
Dragon4 | group | No | |
DwarfWizard | unit | No | |
FFA | button | No | |
Flame | button | No | |
floatingtext1 | texttag | No | |
floatingtext2 | texttag | No | |
floatingtext3 | texttag | No | |
floatingtext4 | texttag | No | |
Frost | button | No | |
FrostySnowman | unit | No | |
GhostofChristmaspast | unit | No | |
GroupBlue | group | No | |
GroupPurple | group | No | |
GroupRed | group | No | |
GroupTeal | group | No | |
HASH | hashtable | No | |
Human | button | No | |
Hydralisk1 | unit | No | |
Hydralisk2 | unit | No | |
Icetrolljugg1 | unit | No | |
Icetrolljugg2 | unit | No | |
LC_Cloud | unit | No | |
LC_TimerN | integer | No | |
LC_Timers | timer | Yes | |
LichKing | unit | No | |
Normal | button | No | |
Quests1 | quest | No | |
Quests2 | quest | No | |
Quests3 | quest | No | |
Raceoptions | dialog | No | |
Randomhints | integer | No | |
randomjump | integer | No | |
Randomloot | integer | No | |
Randommusic | integer | No | |
Randompresentloot | integer | No | |
Randompresents | integer | No | |
Randompresents1 | integer | No | |
Randompresents2 | integer | No | |
Randompresents3 | integer | No | |
Randomteams | integer | No | |
RandomTele | integer | No | |
Santa | unit | No | |
SantasHiredArms1 | unit | No | |
SantasHiredArms2 | unit | No | |
Skaven | button | No | |
Spell__Ability | abilcode | No | |
Spell__AutoAddTargets | boolean | No | |
Spell__BuffAbility | abilcode | No | |
Spell__BuffOrder | ordercode | No | |
Spell__Caster | unit | No | |
Spell__CasterOwner | player | No | |
Spell__CastPoint | location | No | |
Spell__Channeling | boolean | No | |
Spell__Completed | boolean | No | |
Spell__DummyOwner | player | No | |
Spell__DummyType | unitcode | No | |
Spell__Duration | real | No | |
Spell__DurationPerLevel | real | No | |
Spell__Expired | boolean | No | |
Spell__Filter_AllowAlly | boolean | No | |
Spell__Filter_AllowDead | boolean | No | |
Spell__Filter_AllowEnemy | boolean | No | |
Spell__Filter_AllowFlying | boolean | No | |
Spell__Filter_AllowHero | boolean | No | |
Spell__Filter_AllowLiving | boolean | No | |
Spell__Filter_AllowMagicImmune | boolean | No | |
Spell__Filter_AllowMechanical | boolean | No | |
Spell__Filter_AllowNonHero | boolean | No | |
Spell__Filter_AllowStructure | boolean | No | |
Spell__Hash | hashtable | No | |
Spell__Index | integer | No | |
Spell__InRange | real | No | |
Spell__InRangeCount | integer | No | |
Spell__InRangeGroup | group | No | |
Spell__InRangeMax | integer | No | |
Spell__InRangePoint | location | No | |
Spell__InRangeUnit | unit | No | |
Spell__InRangeUnits | unit | Yes | |
Spell__Interval | real | No | |
Spell__Level | integer | No | |
Spell__LevelMultiplier | real | No | |
Spell__Running | boolean | No | |
Spell__StartDuration | boolean | No | |
Spell__Target | unit | No | |
Spell__TargetGroup | group | No | |
Spell__TargetPoint | location | No | |
Spell__Time | real | No | |
Spell__Trigger_InRangeFilter | trigger | No | |
Spell__Trigger_OnCast | trigger | No | |
Spell__Trigger_OnChannel | trigger | No | |
Spell__Trigger_OnEffect | trigger | No | |
Spell__Trigger_OnFinish | trigger | No | |
Spell__Trigger_OnLoop | trigger | No | |
Spell__UseTargetGroup | boolean | No | |
Spell__WakeTargets | boolean | No | |
Spell_i_Abil | abilcode | Yes | |
Spell_i_AllowAlly | boolean | Yes | |
Spell_i_AllowDead | boolean | Yes | |
Spell_i_AllowEnemy | boolean | Yes | |
Spell_i_AllowFlying | boolean | Yes | |
Spell_i_AllowHero | boolean | Yes | |
Spell_i_AllowLiving | boolean | Yes | |
Spell_i_AllowMagicImmune | boolean | Yes | |
Spell_i_AllowMechanical | boolean | Yes | |
Spell_i_AllowNonHero | boolean | Yes | |
Spell_i_AllowStructure | boolean | Yes | |
Spell_i_AutoAddTargets | boolean | Yes | |
Spell_i_BuffAbil | abilcode | Yes | |
Spell_i_BuffOrder | ordercode | Yes | |
Spell_i_Caster | unit | Yes | |
Spell_i_Channeling | boolean | Yes | |
Spell_i_Completed | boolean | Yes | |
Spell_i_Duration | real | Yes | |
Spell_i_EventType | integer | Yes | |
Spell_i_GroupN | integer | No | |
Spell_i_GroupStack | group | Yes | |
Spell_i_Head | integer | Yes | |
Spell_i_InRangeFilter | trigger | Yes | |
Spell_i_Instances | integer | No | |
Spell_i_LastTime | real | Yes | |
Spell_i_Level | integer | Yes | |
Spell_i_Linked | boolean | Yes | |
Spell_i_OnCastStack | trigger | Yes | |
Spell_i_OnChannelStack | trigger | Yes | |
Spell_i_OnEffectStack | trigger | Yes | |
Spell_i_OnFinishStack | trigger | Yes | |
Spell_i_OnLoopStack | trigger | Yes | |
Spell_i_PreloadDummy | unit | No | |
Spell_i_Recycle | integer | No | |
Spell_i_RecycleList | integer | Yes | |
Spell_i_Stack | integer | Yes | |
Spell_i_StackN | integer | No | |
Spell_i_StackRef | integer | Yes | |
Spell_i_Target | unit | Yes | |
Spell_i_TargetGroup | group | Yes | |
Spell_i_TargetX | real | Yes | |
Spell_i_TargetY | real | Yes | |
Spell_i_Time | real | Yes | |
Spell_i_Timer | timer | No | |
Spell_i_UseTG | boolean | Yes | |
T_Window3 | timerdialog | No | |
Timer1 | timer | No | |
Timer2 | timer | No | |
Timer3 | timer | No | |
Twindow1 | timerdialog | No | |
Twindow2 | timerdialog | No | |
twoversustwo | button | No | |
visblue | fogmodifier | No | |
vispurple | fogmodifier | No | |
visred | fogmodifier | No | |
visteal | fogmodifier | No | |
VL_Ability | abilcode | No | |
VL_AbilityCurse | abilcode | No | |
VL_AbilityHeal | abilcode | No | |
VL_AbilityLvl | integer | Yes | |
VL_AoE | real | Yes | |
VL_Buff | buffcode | No | |
VL_C_Amount | integer | No | |
VL_C_Even | real | No | |
VL_C_GrowRate | real | Yes | |
VL_C_GrowTime | real | No | |
VL_C_MoveRate | real | Yes | |
VL_C_SFX | string | No | |
VL_C_Speed | real | No | |
VL_Caster | unit | Yes | |
VL_CounterDuration | real | Yes | |
VL_CurrentAoE | real | Yes | |
VL_Debuff | buffcode | No | |
VL_Degree | real | No | |
VL_Dummy | unitcode | No | |
VL_DummyCaster | unit | No | |
VL_Duration | real | Yes | |
VL_GroupEnemy | group | Yes | |
VL_L | lightning | Yes | |
VL_L_Amount | integer | No | |
VL_L_CheckSFX | boolean | Yes | |
VL_L_Counter | real | Yes | |
VL_L_Direction | real | No | |
VL_L_Distance | real | No | |
VL_L_Duration | real | No | |
VL_L_Height | real | No | |
VL_L_ID | integer | No | |
VL_L_SFX | lightningtype | No | |
VL_L_SFX_EndPoint | string | No | |
VL_LoopInt | integervar | No | |
VL_MaxIndex | integer | No | |
VL_MaxLevel | integer | No | |
VL_NodeNext | integer | Yes | |
VL_NodePrev | integer | Yes | |
VL_Owner | player | Yes | |
VL_PeriodicTimer | real | No | |
VL_RecycledSize | integer | No | |
VL_RecycledStack | integer | Yes | |
VL_SFX | string | No | |
VL_Spell_ID | integer | No | |
VL_SpellCount | integer | No | |
VL_TargetLoc | location | Yes | |
VL_TempInt | integervar | No | |
VL_TempLoc | location | No | |
VL_TempReal | real | No | |
VL_TempUnit | unit | No | |
Werewolf1 | unit | No | |
Werewolf2 | unit | No | |
Werewolf3 | unit | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Volatile Light
v2.01
By KILLCIDE
Making this spell gave me so many problems ._. this spell went through A LOT (an understatement) of changes
Requirements:
--------
- dummy.mdx
Credits:
-------
- Vexorian for dummy.mdx
How to Install:
--------------
1. Under Preferences, make sure you have "Automatically create unknown variables while pasting trigger data" checked
2. Import dummy.mdx, then copy and paste the dummy unit, three abilities, and two buffs into your map
NOTE: If you already have dummy.mdx imported into your map, you DO NOT have to reimport it
If you already have a global dummy unit in your map, you can skip this step
3. Copy and paste the Volatile Light folder into your map
4. Go to the VL Config trigger, and change the Ability, Dummy, AbilityCurse, AbilityHeal, Debuff, & Buff variables to the
corresponding objects you just imported
NOTE: Make sure that AbilityCurse & AbilityHeal have the correct buff data fields!
Changelog:
---------
- v2.01 (March 18, 2016): Added an optional Volatile Light folder that is integrated with GUI Spell System
Fixed inaccuracy of GrowRate incrementing inside the circle creation loop
Removed unnecesary NodeLast[] variable for linked list; last spell instance now stores into NodePrev[0]
Removed If/Then/Else that would set NodeLast = NodePrev[Spell_ID] if NodeLast == Spell_ID
- v2.00 (January 25, 2016): Changed data structure to linked listing
Fixed bug of debuff effect not being removed on dead enemy units until the end of the duration
- v1.03 (December 04, 2015): Changed Owner[] variable to now use Triggering Player instead of Owner of (Unit)
Changed spell to now use one global dummy caster instead of one dummy caster per spell instance
Changed loop to check if it is time to deindex before starting
Changed name of VL Init trigger to VL Cast
Removed unnecessary function call when turning off VL Loop (Turn off (This trigger) -> (Turn off VL Loop))
- v1.02 (November 26, 2015): Changed the way the lightning effects are created
Changed names of some variables
Removed the Lightning Effects ability
Removed unneccesary variables
- v1.01 (October 1, 2015): Added a configurable to change the origin and angle of the lightning effects
Fixed GrowSpeed to GrowTime (lets you decide how long it will take for effects to reach max radius)
Removed KillUnit function and replaced it with RemoveUnit
Removed VL Dummy Cleaner trigger
- v1.00 (September 29, 2015): Uploaded onto Hive
//===CONFIGURABLES:
constant function LC_SpellId takes nothing returns integer
return 'A00H' //Raw code for the Hero ability
endfunction
constant function LC_DummySpellId takes nothing returns integer
return 'A00F' //Raw code for the Lightning Strike ability
endfunction
constant function LC_CloudUnit takes nothing returns integer
return 'h00F' //Raw code for the Cloud Unit
endfunction
constant function LC_Damage takes integer i returns real
return i * 45. //This is the ability level multiply by base damage
endfunction
constant function LC_Range takes nothing returns real
return 500. //Maximum range is 3000 or you can adjust it via object editor
endfunction
constant function LC_Duration takes nothing returns real
return 20. //This is the duration of the cloud and spell
endfunction
constant function LC_TimerSpeed takes nothing returns real
return 0.05
endfunction
constant function LC_ATT takes nothing returns attacktype
return ATTACK_TYPE_MAGIC
endfunction
constant function LC_DAM takes nothing returns damagetype
return DAMAGE_TYPE_LIGHTNING
endfunction
//===END OF CONFIGURABLES===
function LC_RTimer takes timer t returns nothing
if t != null then
call PauseTimer(t)
set udg_LC_Timers[udg_LC_TimerN] = t
set udg_LC_TimerN = udg_LC_TimerN + 1
endif
endfunction
//and get a timer
function LC_NTimer takes nothing returns timer
if udg_LC_TimerN == 0 then
return CreateTimer()
endif
set udg_LC_TimerN = udg_LC_TimerN - 1
return udg_LC_Timers[udg_LC_TimerN]
endfunction
function LC_FilterThem takes nothing returns boolean
local unit u = GetFilterUnit()
local boolean b = GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, GetOwningPlayer(udg_LC_Cloud)) and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false
set u = null
return b
endfunction
function LC_Loop takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer parent = GetHandleId(t)
local integer cloudkey
local unit caster = LoadUnitHandle(udg_HASH, parent, 1)
local unit cloud = LoadUnitHandle(udg_HASH, parent, 2)
local real dur = LoadReal(udg_HASH, parent, 3)
local real range = LoadReal(udg_HASH, parent, 4)
set cloudkey = GetHandleId(cloud)
set udg_LC_Cloud = cloud //should be transfered to a global variable
if dur > 0 and GetWidgetLife(caster) > 0.405 then
call SaveReal(udg_HASH, parent, 3 , dur - LC_TimerSpeed())
call SetUnitX(cloud, GetUnitX(caster))
call SetUnitY(cloud, GetUnitY(caster))
call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(cloud), GetUnitY(cloud), range, Filter(function LC_FilterThem))
call IssueTargetOrder(cloud, "chainlightning" , FirstOfGroup(bj_lastCreatedGroup)) //852119
else
call UnitApplyTimedLife(cloud, 'BTLF', 0.01)
call LC_RTimer(t)
call FlushChildHashtable(udg_HASH, parent)
call FlushChildHashtable(udg_HASH, cloudkey)
endif
set t = null
set cloud = null
set caster = null
endfunction
function LC_Cast takes nothing returns boolean
local timer t
local unit caster
local unit cloud
local integer cloudkey
local integer parent
local integer abilitylevel
if GetSpellAbilityId()==LC_SpellId() then
set caster = GetTriggerUnit()
set abilitylevel = GetUnitAbilityLevel(caster, LC_SpellId())
set t = LC_NTimer()
set parent = GetHandleId(t)
set cloud = CreateUnit(GetTriggerPlayer(), LC_CloudUnit() , GetUnitX(caster), GetUnitY(caster), 0)
set cloudkey = GetHandleId(cloud)
//===This portion saves the caster so that he will deal damage, not the cloud
call SaveUnitHandle(udg_HASH, cloudkey, 1, caster)
call SaveReal(udg_HASH, cloudkey, 2 , LC_Damage(abilitylevel))
//===This portion saves the caster/cloud/duration and range
call SaveUnitHandle(udg_HASH, parent, 1, caster)
call SaveUnitHandle(udg_HASH, parent, 2, cloud)
call SaveReal(udg_HASH, parent, 3, LC_Duration()) //See Function
call SaveReal(udg_HASH, parent, 4, LC_Range()) //See Function
call TimerStart(t, LC_TimerSpeed(), true, function LC_Loop)
elseif GetSpellAbilityId()==LC_DummySpellId() then
set cloudkey = GetHandleId(GetTriggerUnit())
call UnitDamageTarget(LoadUnitHandle(udg_HASH, cloudkey, 1), GetSpellTargetUnit(), LoadReal(udg_HASH, cloudkey, 2), false, false, LC_ATT(), LC_DAM(), null)
endif
set t = null
set caster = null
set cloud = null
return false
endfunction
function InitTrig_LightningCloud takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function LC_Cast))
set udg_HASH = InitHashtable()
set t = null
endfunction
function SpellIndexGetVars takes integer i returns nothing
set udg_Spell__Ability = udg_Spell_i_Abil[udg_Spell_i_Head[i]]
set udg_Spell__Index = i
set udg_Spell__Caster = udg_Spell_i_Caster[i]
set udg_Spell__CasterOwner = GetOwningPlayer(udg_Spell__Caster)
set udg_Spell__Level = udg_Spell_i_Level[i]
set udg_Spell__LevelMultiplier = udg_Spell__Level //Spell__LevelMultiplier is a real variable.
set udg_Spell__Target = udg_Spell_i_Target[i]
//Magic to ensure the locations never leak.
call MoveLocation(udg_Spell__CastPoint, GetUnitX(udg_Spell__Caster), GetUnitY(udg_Spell__Caster))
if udg_Spell__Target == null then
call MoveLocation(udg_Spell__TargetPoint, udg_Spell_i_TargetX[i], udg_Spell_i_TargetY[i])
else
call MoveLocation(udg_Spell__TargetPoint, GetUnitX(udg_Spell__Target), GetUnitY(udg_Spell__Target))
endif
set udg_Spell__TargetGroup = udg_Spell_i_TargetGroup[i]
set udg_Spell__Completed = udg_Spell_i_Completed[i]
set udg_Spell__Channeling = udg_Spell_i_Channeling[i]
endfunction
function SpellSetFilters takes integer i returns nothing
set udg_Spell_i_AllowEnemy[i] = udg_Spell__Filter_AllowEnemy
set udg_Spell_i_AllowAlly[i] = udg_Spell__Filter_AllowAlly
set udg_Spell_i_AllowDead[i] = udg_Spell__Filter_AllowDead
set udg_Spell_i_AllowLiving[i] = udg_Spell__Filter_AllowLiving
set udg_Spell_i_AllowMagicImmune[i] = udg_Spell__Filter_AllowMagicImmune
set udg_Spell_i_AllowMechanical[i] = udg_Spell__Filter_AllowMechanical
set udg_Spell_i_AllowStructure[i] = udg_Spell__Filter_AllowStructure
set udg_Spell_i_AllowFlying[i] = udg_Spell__Filter_AllowFlying
set udg_Spell_i_AllowHero[i] = udg_Spell__Filter_AllowHero
set udg_Spell_i_AllowNonHero[i] = udg_Spell__Filter_AllowNonHero
endfunction
function SpellIndexDestroy takes integer i returns nothing
local integer indexOf
local integer index
if udg_Spell_i_RecycleList[i] >= 0 then
return
endif
//If the caster is still channeling on the spell, don't destroy until it's finished:
if not udg_Spell_i_Channeling[i] then
set index = udg_Spell_i_Head[i]
set udg_Spell_i_RecycleList[i] = udg_Spell_i_Recycle
set udg_Spell_i_Recycle = i
//Reset things to defaults:
set udg_Spell_i_Time[i] = 0.00
set udg_Spell_i_LastTime[i] = 0.00
set udg_Spell_i_Duration[i] = 0.00
set udg_Spell_i_Completed[i] = false
set udg_Spell_i_Caster[i] = null
set udg_Spell_i_Target[i] = null
set udg_Spell_i_OnLoopStack[i] = null
//Recycle any applicable target unit group.
if udg_Spell_i_TargetGroup[i] != null then
call GroupClear(udg_Spell_i_TargetGroup[i])
set udg_Spell_i_GroupStack[udg_Spell_i_GroupN] = udg_Spell_i_TargetGroup[i]
set udg_Spell_i_GroupN = udg_Spell_i_GroupN + 1
set udg_Spell_i_TargetGroup[i] = null
endif
//Clear any user-specified data in the hashtable:
call FlushChildHashtable(udg_Spell__Hash, i)
//call BJDebugMsg("Destroying index: " + I2S(i))
endif
set indexOf = udg_Spell_i_StackRef[i]
if indexOf >= 0 then
set index = udg_Spell_i_StackN - 1
set udg_Spell_i_StackN = index
set udg_Spell_i_StackRef[udg_Spell_i_Stack[index]] = indexOf
set udg_Spell_i_Stack[indexOf] = udg_Spell_i_Stack[index]
if index == 0 then
//If no more spells require the timer, pause it.
call PauseTimer(udg_Spell_i_Timer)
endif
set udg_Spell_i_StackRef[i] = -1
endif
endfunction
function SpellTriggerExecute takes integer i, trigger t returns real
local real d = udg_Spell_i_Duration[i]
local boolean b = false
set udg_Spell__Duration = d
set udg_Spell__Time = 0.00
if t != null then
set udg_Spell__Trigger_OnLoop = null
set udg_Spell__Expired = d <= 0.00 //If the duration is <= 0, the spell has expired.
call SpellIndexGetVars(i)
if TriggerEvaluate(t) then
call TriggerExecute(t)
endif
if udg_Spell__Trigger_OnLoop != null then
set udg_Spell_i_OnLoopStack[i] = udg_Spell__Trigger_OnLoop
endif
//The remaining lines in this function process the duration specified by the user.
if udg_Spell__StartDuration then
set udg_Spell__StartDuration = false
set udg_Spell__Duration = udg_Spell_i_Duration[udg_Spell_i_Head[i]] + udg_Spell_i_LastTime[udg_Spell_i_Head[i]]*udg_Spell__LevelMultiplier
elseif (udg_Spell__Expired and d > 0.00) or (udg_Spell__Duration <= 0.00) then
set udg_Spell__Duration = 0.00
return udg_Spell__Time
//The user manually expired the spell or the spell duration ended on its own.
endif
if d != udg_Spell__Duration then
//A new duration has been assigned
set d = udg_Spell__Duration
set b = true
endif
set udg_Spell__Duration = 0.00
if udg_Spell__Time == 0.00 then
if udg_Spell_i_LastTime[i] == 0.00 then
if udg_Spell_i_Time[udg_Spell_i_Head[i]] > 0.00 then
//The user specified a default interval to follow:
set udg_Spell__Time = udg_Spell_i_Time[udg_Spell_i_Head[i]]
else
//Set the spell time to the minimum.
set udg_Spell__Time = udg_Spell__Interval
endif
else
//Otherwise, set it to what it was before.
set udg_Spell__Time = udg_Spell_i_LastTime[i]
endif
//else, the user is specifying a new time for the spell.
endif
set udg_Spell_i_LastTime[i] = udg_Spell__Time //Whatever the case, remember this time for next time.
if b then
//The duration was just assigned
set udg_Spell_i_Duration[i] = d
else
//The duration has been ongoing
set udg_Spell_i_Duration[i] = d - udg_Spell__Time
endif
endif
return udg_Spell__Time
endfunction
//===========================================================================
// Runs every Spell__Interval seconds and handles all of the timed events.
//
function SpellTimerLoop takes nothing returns nothing
local integer i = udg_Spell_i_StackN
local integer node
local real time
set udg_Spell__Running = true
//Run stack top to bottom to avoid skipping slots when destroying.
loop
set i = i - 1
exitwhen i < 0
set node = udg_Spell_i_Stack[i]
set time = udg_Spell_i_Time[node] - udg_Spell__Interval
if time <= 0.00 then
set time = SpellTriggerExecute(node, udg_Spell_i_OnLoopStack[node])
endif
if time <= 0.00 then
call SpellIndexDestroy(node)
else
set udg_Spell_i_Time[node] = time
endif
endloop
set udg_Spell__Running = false
endfunction
//===========================================================================
// This is the meat of the system as it handles the event responses.
//
function RunSpellEvent takes nothing returns boolean
local boolean b
local integer aid = GetSpellAbilityId()
local integer head = LoadInteger(udg_Spell__Hash, 0, aid)
local integer i
local integer id
local trigger t
local playerunitevent eid
if head == 0 then
//Nothing for this ability has been registered. Skip the sequence.
return false
endif
set eid = ConvertPlayerUnitEvent(GetHandleId(GetTriggerEventId()))
set udg_Spell__Caster = GetTriggerUnit()
set id = GetHandleId(udg_Spell__Caster)
set i = LoadInteger(udg_Spell__Hash, aid, id)
if i == 0 then
//This block will almost always happen with the OnChannel event. In the
//case of Charge Gold and Lumber, only an OnEffect event will run.
set i = udg_Spell_i_Recycle
if i == 0 then
//Create a new, unique index
set i = udg_Spell_i_Instances + 1
set udg_Spell_i_Instances = i
else
//Repurpose an existing one
set udg_Spell_i_Recycle = udg_Spell_i_RecycleList[i]
endif
//call BJDebugMsg("Creating index: " + I2S(i))
set udg_Spell_i_RecycleList[i] = -1
set udg_Spell_i_StackRef[i] = -1
set udg_Spell_i_Head[i] = head
if eid == EVENT_PLAYER_UNIT_SPELL_CHANNEL then
set udg_Spell_i_Channeling[i] = true
call SaveInteger(udg_Spell__Hash, aid, id, i)
set t = udg_Spell_i_OnChannelStack[head]
else //eid == EVENT_PLAYER_UNIT_SPELL_EFFECT
set t = udg_Spell_i_OnEffectStack[head]
endif
set udg_Spell_i_Caster[i] = udg_Spell__Caster
set udg_Spell_i_Level[i] = GetUnitAbilityLevel(udg_Spell__Caster, aid)
set udg_Spell_i_Target[i] = GetSpellTargetUnit()
set udg_Spell_i_TargetX[i] = GetSpellTargetX()
set udg_Spell_i_TargetY[i] = GetSpellTargetY()
set udg_Spell_i_OnLoopStack[i] = udg_Spell_i_OnLoopStack[head]
if udg_Spell_i_UseTG[head] then
//Get a recycled unit group or create a new one.
set id = udg_Spell_i_GroupN - 1
if id >= 0 then
set udg_Spell_i_GroupN = id
set udg_Spell_i_TargetGroup[i] = udg_Spell_i_GroupStack[id]
else
set udg_Spell_i_TargetGroup[i] = CreateGroup()
endif
endif
elseif eid == EVENT_PLAYER_UNIT_SPELL_CAST then
set t = udg_Spell_i_OnCastStack[head]
elseif eid == EVENT_PLAYER_UNIT_SPELL_EFFECT then
set t = udg_Spell_i_OnEffectStack[head]
elseif eid == EVENT_PLAYER_UNIT_SPELL_FINISH then
set udg_Spell_i_Completed[i] = true
return true
else //eid == EVENT_PLAYER_UNIT_SPELL_ENDCAST
set udg_Spell_i_Channeling[i] = false
call RemoveSavedInteger(udg_Spell__Hash, aid, id)
set t = udg_Spell_i_OnFinishStack[head]
endif
if SpellTriggerExecute(i, t) > 0.00 then
//Set the spell time to the user-specified one.
set udg_Spell_i_Time[i] = udg_Spell__Time
if udg_Spell_i_StackRef[i] < 0 then
//Allocate the spell index onto the loop stack.
set aid = udg_Spell_i_StackN
set udg_Spell_i_Stack[aid] = i
set udg_Spell_i_StackRef[i] = aid
set udg_Spell_i_StackN = aid + 1
if aid == 0 then
//If this is the first spell index using the timer, start it up:
call TimerStart(udg_Spell_i_Timer, udg_Spell__Interval, true, function SpellTimerLoop)
endif
endif
elseif (not udg_Spell_i_Channeling[i]) and (t != null or udg_Spell_i_Time[i] <= 0.00) then
call SpellIndexDestroy(i)
endif
set t = null
return true
endfunction
//This function is invoked if an event was launched recursively by another event's callback.
function RunPreSpellEvent takes nothing returns nothing
local integer i = udg_Spell__Index
local real time = udg_Spell__Time
local real d = udg_Spell__Duration
local boolean expired = udg_Spell__Expired
if udg_Spell__Trigger_OnLoop != null then
set udg_Spell_i_OnLoopStack[i] = udg_Spell__Trigger_OnLoop
endif
if RunSpellEvent() then
set udg_Spell__Time = time
set udg_Spell__Duration = d
set udg_Spell__Expired = expired
call SpellIndexGetVars(i)
endif
endfunction
//===========================================================================
// Base function of the system: runs when an ability event does something.
//
function SpellSystemEvent takes nothing returns boolean
if udg_Spell__Running then
call RunPreSpellEvent()
else
set udg_Spell__Running = true
call RunSpellEvent()
set udg_Spell__Running = false
endif
return false
endfunction
//===========================================================================
// Set Spell__Ability to your spell's ability
// Set Spell__Trigger_OnChannel/Cast/Effect/Finish/Loop to any trigger(s) you
// want to automatically run.
//
// GUI-friendly: Run Spell System <gen> (ignoring conditions)
//
function SpellSystemRegister takes nothing returns nothing
local integer aid = udg_Spell__Ability
local integer head = udg_Spell_i_Instances + 1
if HaveSavedInteger(udg_Spell__Hash, 0, aid) or aid == 0 then
//The system rejects duplicate or unassigned abilities.
return
endif
set udg_Spell_i_Instances = head
set udg_Spell_i_Abil[head] = aid
//Preload the ability on dummy unit to help prevent first-instance lag
call UnitAddAbility(udg_Spell_i_PreloadDummy, aid)
//Save head index to the spell ability so it be referenced later.
call SaveInteger(udg_Spell__Hash, 0, aid, head)
//Set any applicable event triggers.
set udg_Spell_i_OnChannelStack[head]= udg_Spell__Trigger_OnChannel
set udg_Spell_i_OnCastStack[head] = udg_Spell__Trigger_OnCast
set udg_Spell_i_OnEffectStack[head] = udg_Spell__Trigger_OnEffect
set udg_Spell_i_OnFinishStack[head] = udg_Spell__Trigger_OnFinish
set udg_Spell_i_OnLoopStack[head] = udg_Spell__Trigger_OnLoop
set udg_Spell_i_InRangeFilter[head] = udg_Spell__Trigger_InRangeFilter
//Set any customized filter variables:
call SpellSetFilters(head)
//Tell the system to automatically create target groups, if needed
set udg_Spell_i_AutoAddTargets[head] = udg_Spell__AutoAddTargets
set udg_Spell_i_UseTG[head] = udg_Spell__UseTargetGroup or udg_Spell__AutoAddTargets
//Handle automatic buff assignment
set udg_Spell_i_BuffAbil[head] = udg_Spell__BuffAbility
set udg_Spell_i_BuffOrder[head] = udg_Spell__BuffOrder
//Set the default time sequences if a duration is used:
set udg_Spell_i_Time[head] = udg_Spell__Time
set udg_Spell_i_Duration[head] = udg_Spell__Duration
set udg_Spell_i_LastTime[head] = udg_Spell__DurationPerLevel
//Set variables back to their defaults:
set udg_Spell__Trigger_OnChannel = null
set udg_Spell__Trigger_OnCast = null
set udg_Spell__Trigger_OnEffect = null
set udg_Spell__Trigger_OnFinish = null
set udg_Spell__Trigger_OnLoop = null
set udg_Spell__Trigger_InRangeFilter= null
set udg_Spell__AutoAddTargets = false
set udg_Spell__UseTargetGroup = false
set udg_Spell__Time = 0.00
set udg_Spell__Duration = 0.00
set udg_Spell__DurationPerLevel = 0.00
set udg_Spell__BuffAbility = 0
set udg_Spell__BuffOrder = 0
set udg_Spell__Filter_AllowEnemy = udg_Spell_i_AllowEnemy[0]
set udg_Spell__Filter_AllowAlly = udg_Spell_i_AllowAlly[0]
set udg_Spell__Filter_AllowDead = udg_Spell_i_AllowDead[0]
set udg_Spell__Filter_AllowMagicImmune = udg_Spell_i_AllowMagicImmune[0]
set udg_Spell__Filter_AllowMechanical = udg_Spell_i_AllowMechanical[0]
set udg_Spell__Filter_AllowStructure = udg_Spell_i_AllowStructure[0]
set udg_Spell__Filter_AllowFlying = udg_Spell_i_AllowFlying[0]
set udg_Spell__Filter_AllowHero = udg_Spell_i_AllowHero[0]
set udg_Spell__Filter_AllowNonHero = udg_Spell_i_AllowNonHero[0]
set udg_Spell__Filter_AllowLiving = udg_Spell_i_AllowLiving[0]
endfunction
function SpellFilterCompare takes boolean is, boolean yes, boolean no returns boolean
return (is and yes) or ((not is) and no)
endfunction
//===========================================================================
// Before calling this function, set Spell__InRangePoint to whatever point
// you need, THEN set Spell__InRange to the radius you need. The system will
// enumerate the units matching the configured filter and fill them into
// Spell_InRangeGroup.
//
function SpellGroupUnitsInRange takes nothing returns boolean
local integer i = udg_Spell_i_Head[udg_Spell__Index]
local integer j = 0
local unit u
local real padding = 64.00
if udg_Spell_i_AllowStructure[i] then
//A normal unit can only have up to size 64.00 collision, but if the
//user needs to check for structures we need a padding big enough for
//the "fattest" ones: Tier 3 town halls.
set padding = 197.00
endif
call GroupEnumUnitsInRangeOfLoc(udg_Spell__InRangeGroup, udg_Spell__InRangePoint, udg_Spell__InRange + padding, null)
loop
set u = FirstOfGroup(udg_Spell__InRangeGroup)
exitwhen u == null
call GroupRemoveUnit(udg_Spell__InRangeGroup, u)
loop
exitwhen udg_Spell_i_AutoAddTargets[i] and IsUnitInGroup(u, udg_Spell__TargetGroup)
exitwhen not IsUnitInRangeLoc(u, udg_Spell__InRangePoint, udg_Spell__InRange)
exitwhen not SpellFilterCompare(IsUnitType(u, UNIT_TYPE_DEAD), udg_Spell_i_AllowDead[i], udg_Spell_i_AllowLiving[i])
exitwhen not SpellFilterCompare(IsUnitAlly(u, udg_Spell__CasterOwner), udg_Spell_i_AllowAlly[i], udg_Spell_i_AllowEnemy[i])
exitwhen not SpellFilterCompare(IsUnitType(u, UNIT_TYPE_HERO) or IsUnitType(u, UNIT_TYPE_RESISTANT), udg_Spell_i_AllowHero[i], udg_Spell_i_AllowNonHero[i])
exitwhen IsUnitType(u, UNIT_TYPE_STRUCTURE) and not udg_Spell_i_AllowStructure[i]
exitwhen IsUnitType(u, UNIT_TYPE_FLYING) and not udg_Spell_i_AllowFlying[i]
exitwhen IsUnitType(u, UNIT_TYPE_MECHANICAL) and not udg_Spell_i_AllowMechanical[i]
exitwhen IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and not udg_Spell_i_AllowMagicImmune[i]
set udg_Spell__InRangeUnit = u
//Run the user's designated filter, if one exists.
exitwhen udg_Spell_i_InRangeFilter[i] != null and not TriggerEvaluate(udg_Spell_i_InRangeFilter[i])
set j = j + 1
set udg_Spell__InRangeUnits[j] = u
exitwhen true
endloop
endloop
if j > udg_Spell__InRangeMax and udg_Spell__InRangeMax > 0 then
//The user has defined a maximum number of units allowed in the group.
//Remove a random unit until the total does not exceed capacity.
loop
set i = GetRandomInt(1, j)
set udg_Spell__InRangeUnits[i] = udg_Spell__InRangeUnits[j]
set j = j - 1
exitwhen j == udg_Spell__InRangeMax
endloop
endif
set udg_Spell__InRangeCount = j
set udg_Spell__InRangeMax = 0
set udg_Spell__InRange = 0.00
set i = udg_Spell_i_Head[udg_Spell__Index]
loop
exitwhen j == 0
set u = udg_Spell__InRangeUnits[j]
call GroupAddUnit(udg_Spell__InRangeGroup, u)
if udg_Spell_i_AutoAddTargets[i] then
call GroupAddUnit(udg_Spell__TargetGroup, u)
endif
if udg_Spell__WakeTargets and UnitIsSleeping(u) then
call UnitWakeUp(u)
endif
if udg_Spell_i_BuffAbil[i] != 0 and udg_Spell_i_BuffOrder[i] != 0 then
//Auto-buff units added to group:
call UnitAddAbility(udg_Spell_i_PreloadDummy, udg_Spell_i_BuffAbil[i])
call IssueTargetOrderById(udg_Spell_i_PreloadDummy, udg_Spell_i_BuffOrder[i], u)
call UnitRemoveAbility(udg_Spell_i_PreloadDummy, udg_Spell_i_BuffAbil[i])
endif
set j = j - 1
endloop
set u = null
return false
endfunction
function SpellPreloadEnd takes nothing returns nothing
local integer i = udg_Spell_i_Instances
loop
exitwhen i == 0
//Remove preloaded abilities so they don't interfere with orders
call UnitRemoveAbility(udg_Spell_i_PreloadDummy, udg_Spell_i_Abil[udg_Spell_i_Head[i]])
set i = i - 1
endloop
endfunction
//===========================================================================
function InitTrig_Spell_System_2 takes nothing returns nothing
local integer i = bj_MAX_PLAYER_SLOTS
local player p
local trigger t
if gg_trg_Spell_System_2 != null then
//A JASS function call already initialized the system.
return
endif
//This runs before map init events so the hashtable is ready before then.
set udg_Spell__Hash = InitHashtable()
//Initialize these two locations which will never get removed
set udg_Spell__CastPoint = Location(0, 0)
set udg_Spell__TargetPoint = Location(0, 0)
//Recycle existing unit groups into the recycle stack to avoid needing to destroy any extras.
set udg_Spell_i_GroupStack[2] = udg_Spell__TargetGroup
set udg_Spell_i_GroupStack[3] = udg_Spell_i_TargetGroup[0]
set udg_Spell_i_GroupStack[4] = udg_Spell_i_TargetGroup[1]
set udg_Spell_i_GroupN = 5 //There are already five valid unit groups thanks to Variable Editor.
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_Spell__InRange", GREATER_THAN, 0.00)
call TriggerAddCondition(t, Filter(function SpellGroupUnitsInRange))
set t = CreateTrigger()
call TriggerAddCondition(t, Filter(function SpellSystemEvent))
loop
set i = i - 1
set p = Player(i)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_CHANNEL, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_CAST, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_FINISH, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_ENDCAST, null)
exitwhen i == 0
endloop
set p = null
set t = null
//Run the configuration trigger so its variables are ready before the
//map initialization events run.
call TriggerExecute(gg_trg_Spell_System_Config)
call SpellSetFilters(0)
//Create this trigger so it's GUI-friendly.
set gg_trg_Spell_System_2 = CreateTrigger()
call TriggerAddAction(gg_trg_Spell_System_2, function SpellSystemRegister)
set gg_trg_Spell_System_Config = gg_trg_Spell_System_2 //In case the user accidentally picks this one
//Create a dummy unit for preloading abilities and casting buffs.
set udg_Spell_i_PreloadDummy = CreateUnit(udg_Spell__DummyOwner, udg_Spell__DummyType, 0, 0, 0)
//Start the timer to remove its abilities:
call TimerStart(udg_Spell_i_Timer, 0.00, false, function SpellPreloadEnd)
call UnitRemoveAbility(udg_Spell_i_PreloadDummy, 'Amov') //Force it to never move to cast spells
endfunction
//TESH.scrollpos=146
//TESH.alwaysfold=0
//***************************************************************************
//***************************************************************************
//***************************************************************************
// L O T U S I C E
// By: Elphis (Nyuu)
// Version: 1.0
//
// Sepll Description:
// ` - Using the power of frost, ice beam summons on the ground at the same time creating freezing weather,
// after the ice beam achieve maximum strength, it immediately ice scrapers on the ground, any enemies in range
// 300, it will pierce, and push enemies out of range, and every 0.2 seconds, it will emit a stream of ejected ice,
// freezing enemies, and those who freezes in 500 range, it will pull enemy into the deep of the ice place.
//
// Damage level 1: 1.5
// Damage level 2: 3
// Damage level 3: 4.5
// Damage level 4: 6
// - Installation:
// - Import/copy Lotus Ice code to your map
// - Import/copy the custom ability and unit to your map and change the SPELL_ID, DUMMY_CASTER, DUMMY_DEG_1, DUMMY_DEG_2, DUMMY_DEG_3 and DUMMY_MISSLE if needed
// - You may view the raw ID of the objects by pressing CTRL+D in the object editor
// - You may play with the configurables below
//
//
//***************************************************************************
//***************************************************************************
//***************************************************************************
library LotusIce
globals
private constant real PERIODIC = .031250000
//Spell rawcode, change if needed
private constant integer SPELL_ID = 'A00A'
//Dummy 1 rawcode, change if needed
private constant integer DUMMY_DEG_1 = 'e003'
//Dummy 2 rawcode, change if needed
private constant integer DUMMY_DEG_2 = 'e004'
//Dummy 3 rawcode, change if needed
private constant integer DUMMY_DEG_3 = 'e005'
//Dummy missle rawcode, change if needed
private constant integer DUMMY_MISSLE = 'e007'
//Dummy caster rawcode, change if needed
private constant integer CASTER_DUMMY = 'e006'
//Buff rawcode, change if needed
private constant integer BUFF_ID = 'B000'
//Weather type when spell is active
private constant integer WEATHER_TYPE = 'SNhs'
//Total ice count
private constant integer DUMMY_COUNT = 10
//Frost effect count random number, incease => laggy, decrease => ice fairy
private constant integer EFFECT_NUMBER = 2
//Total wave of frost
private constant integer FROST_COUNT = 4
//Damage base of spell, increase => instantly dead, decrease => you dead
private constant real DAMAGE_BASE = 1.5
//Push unit radius
private constant real KNOCK_RADIUS = 300.
//Damage radius, increase => incredible spell, decrease => useless spell
private constant real DMG_RADIUS = 100.
//Pull unit when the enemies has freezed
private constant real PULL_RANGE = 500.
//Push speed, increase => fast push, decrease => slow push
private constant real ENEMIES_KNOCK = 5.
//Pull unit speed
private constant real ENEMIES_PULL = 0.5
//Frost missle speed
private constant real MISSLE_SPEED = 20.
//Main ice scale
private constant real ICE_SCALE_1 = 2.
//Second ice scale
private constant real ICE_SCALE_2 = 1.
//Third ice scale
private constant real ICE_SCALE_3 = 1.
//Scale increase per periodic
private constant real SCALE_PER_PERIOD= .07
private constant real ICE_AREA_1 = 150.
private constant real ICE_AREA_2 = 200.
private constant real RANGE_MISSLE_1 = 600.
private constant real RANGE_MISSLE_2 = 700.
//Range increase per wave of frost
private constant real RANGE_PER_PERIOD= 150.
//Freeze radius when the wave of frost is active
private constant real FREEZE_RADIUS = 150.
//Frost wave intevar
private constant real FROST_INTEVAR = 0.1
//Damage intevar
private constant real DAMAGE_INTEVAR = 0.5
//Lotus ice spell duration
private constant real LOTUS_DURATION = 3.
//Frost of wave repeat time
private constant real FROST_REPEAT = 0.8
//Frost effect
private constant string ICE_EFFECT = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
//Order id of dummy spell
private constant string ORDER_ID = "thunderbolt"
//Create a dummy on init function, so this spell never create dummy again
private constant boolean DO_DUMMY_INIT = true
//******************************DAMAGE DATA SETTINGS******************************
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_DEATH
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_CLAW_HEAVY_SLICE
//********************************************************************************
//***************************Non - Configurable*****************************
/* */
/**/private integer MUI = -1 /**/
/* */
/**/private constant timer TIMER = CreateTimer() /**/
/* */
/**/private constant timer TIMER_2 = CreateTimer() /**/
/* */
/**/private integer array StructData /**/
/* */
/**/private integer PMUI = -1 /**/
/* */
/**/private integer array PStructData /**/
/* */
/**/private integer TMUI = -1 /**/
/* */
/**/private integer array TStructData /**/
/* */
/**/private group G = CreateGroup() /**/
/* */
/**/private unit Dummy /**/
/* */
/**/private real Main_Time = 0. /**/
/* */
/**/private rect RECT = Rect(0.,0.,0.,0.) /**/
/* */
//***************************************************************************
/**/private constant real FACING = ICE_AREA_1+ICE_AREA_2/**/
/**/private constant real MAX_COUNT = DUMMY_COUNT*2 /**/
//***************************************************************************
endglobals
//Damage settings********************************************
constant function damageSetting takes integer lvl returns real
return DAMAGE_BASE*lvl
endfunction
//************************************************************
//Duration settings*******************************************
constant function durationSetting takes integer lvl returns real
return LOTUS_DURATION+lvl
endfunction
//************************************************************
//Conditions function*****************************************
constant function conditionFunc takes player caster_owner,unit other returns boolean
/**/ //Assure a better death check//
/**/return IsUnitEnemy(other,caster_owner) and /**/GetUnitTypeId(other) != 0/**/and not IsUnitType(other,UNIT_TYPE_DEAD)
endfunction
//************************************************************
private struct LotusIce
unit dummy
weathereffect weather
real vinc
real value_inc
real frost_rep
real frost_int
real frost_inc
real ag
real gx
real gy
real lotus_dur
boolean frost_active = false
boolean spell_active = true
integer frost_count = FROST_COUNT
integer fade
integer value_fade = 0
player playe
static method onPeriodic takes nothing returns nothing
local integer i = 0
local integer l = 0
local real a
local real x
local real y
local unit f = null
local thistype this
loop
exitwhen i > MUI
set this = StructData[i]
if spell_active then
if value_inc < ICE_SCALE_1 then
set value_inc = value_inc + vinc
set value_fade = value_fade + fade
call SetUnitScale(dummy,value_inc,0.,0.)
call SetUnitVertexColor(dummy,255,255,255,value_fade)
else
if lotus_dur > 0. then
set lotus_dur = lotus_dur - PERIODIC
set Main_Time = lotus_dur
if frost_rep < FROST_REPEAT and frost_count == FROST_COUNT then
set frost_rep = frost_rep + PERIODIC
else
set frost_rep = 0.
set frost_active = true
endif
if frost_active then
if frost_int < FROST_INTEVAR then
set frost_int = frost_int + PERIODIC
else
set frost_int = 0.
if frost_count > 0 then
set frost_inc = frost_inc + RANGE_PER_PERIOD
set frost_count = frost_count - 1
static if not DO_DUMMY_INIT then
set Dummy = CreateUnit(Player(15),CASTER_DUMMY,0.,0.,0.)
endif
loop
exitwhen i > DUMMY_COUNT
set a = .0174533*i*ag
set x = gx + frost_inc * Cos(a)
set y = gy + frost_inc * Sin(a)
call DestroyEffect(AddSpecialEffect(ICE_EFFECT,x,y))
call GroupEnumUnitsInRange(G,x,y,FREEZE_RADIUS,null)
loop
set f = FirstOfGroup(G)
exitwhen f == null
if conditionFunc(playe,f) then
call SetUnitX(Dummy,GetUnitX(f))
call SetUnitY(Dummy,GetUnitY(f))
call IssueTargetOrder(Dummy,ORDER_ID,f)
endif
call GroupRemoveUnit(G,f)
endloop
set i = i + 1
endloop
static if not DO_DUMMY_INIT then
call RemoveUnit(Dummy)
endif
else
set frost_inc = 0.
set frost_count = FROST_COUNT
set frost_active = false
endif
endif
endif
else
set spell_active = false
endif
endif
elseif value_inc > 0. then
set value_inc = value_inc - vinc
set value_fade = value_fade - fade
call SetUnitScale(dummy,value_inc,0.,0.)
call SetUnitVertexColor(dummy,255,255,255,value_fade)
else
set StructData[i] = StructData[MUI]
set StructData[MUI] = -2
set MUI = MUI - 1
if MUI == -1 then
call PauseTimer(TIMER)
endif
call RemoveUnit(dummy)
call RemoveWeatherEffect(weather)
set weather = null
set dummy = null
set playe = null
call destroy()
endif
set i = i + 1
endloop
endmethod
static method onCast takes nothing returns boolean
local thistype this
local integer i
local integer l
local integer alvl
local integer unitid
local real dx
local real dy
local real angle
local real cs
local real sc
local real rg
local real icea
local real cos
local real sin
local unit caster
if GetSpellAbilityId() != SPELL_ID then
set caster = null
return false
endif
set this = allocate()
set MUI = MUI + 1
set StructData[MUI] = this
set playe = GetTriggerPlayer()
set caster = GetTriggerUnit()
set gx = GetSpellTargetX()
set gy = GetSpellTargetY()
call SetRect(RECT,gx-FACING,gy-FACING,gx+FACING,gy+FACING)
set weather = AddWeatherEffect(RECT,WEATHER_TYPE)
call EnableWeatherEffect( weather, true )
set alvl = GetUnitAbilityLevel(caster,SPELL_ID)
set lotus_dur = durationSetting(alvl)
set ag = 360./DUMMY_COUNT
set i = 0
set fade = R2I(255./RANGE_MISSLE_2*MISSLE_SPEED)
set dummy = CreateUnit(Player(15),DUMMY_DEG_1,gx,gy,0.)
call SetUnitScale(dummy,0.,0.,0.)
call SetUnitVertexColor(dummy,255,255,255,0)
loop
exitwhen i > MAX_COUNT
if i < DUMMY_COUNT then
set cs = .0174533*i*ag
set cos = Cos(cs)
set sin = Sin(cs)
set rg = RANGE_MISSLE_1
set frost_int = gx + FACING * cos
set frost_inc = gy + FACING * sin
set value_inc = gx + rg * cos
set frost_rep = gy + rg * sin
set unitid = DUMMY_DEG_2
set icea = ICE_AREA_1
set dx = gx + icea * cos
set dy = gy + icea * sin
set sc = ICE_SCALE_2
else
set rg = RANGE_MISSLE_2
set l = i - DUMMY_COUNT
set cs = .0174533*l*ag
set cos = Cos(cs)
set sin = Sin(cs)
set frost_int = gx + FACING * cos
set frost_inc = gy + FACING * sin
set value_inc = gx + rg * cos
set frost_rep = gy + rg * sin
set unitid = DUMMY_DEG_3
set rg = RANGE_MISSLE_2
set icea = ICE_AREA_2
set dx = gx + icea * cos
set dy = gy + icea * sin
set sc = ICE_SCALE_3
endif
set angle = 57.29583 * Atan2(frost_inc - dy, frost_int - dx)
set vinc = 57.29583 * Atan2(gy - frost_rep, gx - value_inc)
call LotusIce_LotusIcePlugin.add(CreateUnit(Player(15),DUMMY_MISSLE,value_inc,frost_rep,vinc),unitid,dx,dy,angle,vinc,rg,icea,sc,gx,gy,i,damageSetting(alvl),playe,caster,dummy)
set i = i + 1
endloop
set value_inc = 0.
set frost_rep = 0.
set frost_int = 0.
set frost_inc = 0.
set vinc = ICE_SCALE_1/RANGE_MISSLE_2*MISSLE_SPEED
if MUI == 0 then
call TimerStart(TIMER,PERIODIC,true,function thistype.onPeriodic)
endif
set caster = null
return false
endmethod
static method onInit takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i = i + 1
endloop
call TriggerAddCondition(t,function thistype.onCast)
static if DO_DUMMY_INIT then
set Dummy = CreateUnit(Player(15),CASTER_DUMMY,0.,0.,0.)
endif
endmethod
endstruct
public struct LotusIcePlugin
unit dummy
unit caster
unit mdummy
integer dummyid
integer count
boolean spell_active = true
player playe
real scale = 0.
real dmg
real tx
real ty
real dx
real dy
real df
real cos
real sin
real maxsc
real icearea
real distance
real dmg_int = 0.
static method onPeriodic takes nothing returns nothing
local integer i = 0
local real a
local real x
local real y
local boolean pull
local boolean dmg_active = false
local unit f = null
local thistype this
loop
exitwhen i > PMUI
set this = PStructData[i]
if spell_active then
if distance > icearea then
set distance = distance - MISSLE_SPEED
set x = GetUnitX(dummy) + MISSLE_SPEED * cos
set y = GetUnitY(dummy) + MISSLE_SPEED * sin
call SetUnitX(dummy,x)
call SetUnitY(dummy,y)
elseif scale < maxsc then
if GetUnitTypeId(dummy) > 0 then
if GetRandomInt(0,100) <= EFFECT_NUMBER then
call DestroyEffect(AddSpecialEffect(ICE_EFFECT,dx,dy))
endif
call RemoveUnit(dummy)
set dummy = CreateUnit(Player(15),dummyid,dx,dy,df)
call SetUnitScale(dummy,0.,0.,0.)
endif
set scale = scale + SCALE_PER_PERIOD
call SetUnitScale(dummy,scale,0.,0.)
else
if dmg_int < DAMAGE_INTEVAR then
set dmg_int = dmg_int + PERIODIC
else
set dmg_int = 0.
set dmg_active = true
endif
if GetUnitAbilityLevel(f,BUFF_ID) == 0 then
call GroupEnumUnitsInRange(G,dx,dy,KNOCK_RADIUS,null)
set pull = false
else
call GroupEnumUnitsInRange(G,dx,dy,PULL_RANGE,null)
set pull = true
endif
loop
set f = FirstOfGroup(G)
exitwhen f == null
if conditionFunc(playe,f) then
set x = GetUnitX(f)
set y = GetUnitY(f)
if GetUnitAbilityLevel(f,BUFF_ID) == 0 then
set df = 57.29583 * Atan2(y - dy,x - dx)
set a = .0174533*df
set x = x + ENEMIES_KNOCK * Cos(a)
set y = y + ENEMIES_KNOCK * Sin(a)
else
set df = 57.29583 * Atan2(dy - y,dx - x)
set a = .0174533*df
set x = x + ENEMIES_PULL * Cos(a)
set y = y + ENEMIES_PULL * Sin(a)
endif
call SetUnitX(f,x)
call SetUnitY(f,y)
endif
call GroupRemoveUnit(G,f)
endloop
if dmg_active then
call GroupEnumUnitsInRange(G,dx,dy,DMG_RADIUS,null)
loop
set f = FirstOfGroup(G)
exitwhen f == null
if conditionFunc(playe,f) then
call UnitDamageTarget(caster,f,dmg,true,false,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
endif
call GroupRemoveUnit(G,f)
endloop
endif
if GetUnitTypeId(mdummy) == 0 then
set spell_active = false
endif
endif
elseif scale > 0. then
set scale = scale - SCALE_PER_PERIOD
call SetUnitScale(dummy,scale,0.,0.)
else
set PStructData[i] = PStructData[PMUI]
set PStructData[PMUI] = -2
set PMUI = PMUI - 1
if PMUI == -1 then
call PauseTimer(TIMER_2)
endif
call RemoveUnit(dummy)
set dummy = null
set caster = null
set playe = null
call destroy()
endif
set i = i + 1
endloop
endmethod
static method add takes unit u,integer unitid,real x,real y,real f,real f1,real rg,real icea,real sc,real t,real tt,integer c,real damage,player p,unit ct,unit maind returns nothing
local thistype this = allocate()
set PMUI = PMUI + 1
set PStructData[PMUI] = this
set maxsc = sc
set dummy = u
set dummyid = unitid
set dx = x
set dy = y
set df = f
set cos = Cos(.0174533*f1)
set sin = Sin(.0174533*f1)
set icearea = icea
set distance = rg
set count = c
set tx = t
set ty = tt
set dmg = damage
set playe = p
set caster = ct
set mdummy = maind
if PMUI == 0 then
call TimerStart(TIMER_2,PERIODIC,true,function thistype.onPeriodic)
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=223
//TESH.alwaysfold=0
native UnitAlive takes unit id returns boolean//Remove this if you already had one
//! zinc
library FrostBite
/*-----------------------------------------------------------------------------------/
/- v1.0.2
/- JC Helas
/-
/- Description:
/- Release an ice trap that moves back and forth, after move
/- a nova ice will expload that cause them vacuumed to caster's
/- position.
/-
/- 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 the custom locust object
/- 4. Then copy the folder and paste on your map.
/-
/- The spell does not require any libraries.
/-
/-----------------------------------------------------------------------------------*/
{
private
{
/*- Determine the ability ID of Frost Bite -*/
constant integer SPELL_ID = 'A00C' ;
/*- Determine the dummy id of that stands as frost trap -*/
constant integer DUM_ID = 'u000' ;
/*- Determine the base amount of frost trap -*/
constant integer LINES = 14 ;
/*- Determine the additional line per level -*/
constant integer LINES_LVL= 2 ;
/*- Determine the damage amount of back and forth -*/
constant real DAMAGE = 60.0 ;
/*- Determine the additional amount of damage -*/
constant real DAMAGE_LVL = 5.0 ;
/*- Determine the affect of area per line -*/
constant real DAMAGE_AOE = 75.0 ;
/*- Determine the distance travel of each line -*/
constant real DISTANCE = 600.0 ;
/*- Determine the speed of forth -*/
constant real SPEED_FORTH = 20.0 ;
/*- Determine the speed of back -*/
constant real SPEED_BACK = 35.0 ;
/*- Determine the summoning distance to target caster position -*/
constant real SUMMON_DIST = 50.0 ;
/*- Determine the speed of vacuum -*/
constant real VACUUM_SPEED= 25.0 ;
/*- Determine the flying height of vacuumed unit -*/
constant real VACUUM_Z = 300.0 ;
/*- Determine the attack type of Frost Bite -*/
constant attacktype A_TYPE= ATTACK_TYPE_MAGIC ;
/*- Determine the damage type of Frost Bite -*/
constant damagetype D_TYPE= DAMAGE_TYPE_NORMAL ;
/*- Determine the owner of dummies -*/
constant player DUM_OWNER = Player(PLAYER_NEUTRAL_PASSIVE) ;
/*- Determine the model attachment to dummy -*/
constant string ATTACH = "origin" ;
/*- Determine the model of dummy -*/
constant string MODEL = "Doodads\\Cinematic\\FrostTrapUp\\FrostTrapUp.mdl";
/*- Determine the nova fx -*/
constant string TARGETFX = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl";
struct data
{
player owner;
unit caster,dummy;
real angle,rate,speed,dmg,dx,dy;
effect fx;
boolean b;
group g;
}
struct vacuumdata
{
unit u;
real d,r,z,bz,a;
}
constant real periodic=0.031250;
constant group grp=CreateGroup();
constant timer tmr=CreateTimer();
integer ix=0;
integer ic[];
data link=0;
constant timer vtmr=CreateTimer();
integer vix=0;
integer vic[];
function onVacuumLoop()
{
integer i=1;
real x,y;
vacuumdata this;
while(i<=vix)
{
this=vic[i];
this.r=this.r+VACUUM_SPEED;
x=GetUnitX(this.u)+VACUUM_SPEED*Cos(this.a*bj_DEGTORAD);
y=GetUnitY(this.u)+VACUUM_SPEED*Sin(this.a*bj_DEGTORAD);
SetUnitX(this.u,x);
SetUnitY(this.u,y);
SetUnitFlyHeight(this.u,this.bz+(Sin(((180.0/this.d)*this.r)*bj_DEGTORAD)*this.z),0.0);
if(this.r>=this.d)
{
SetUnitPathing(this.u,true);
SetUnitFlyHeight(this.u,GetUnitDefaultFlyHeight(this.u),0);
this.u=null;
vacuumdata.destroy(this);
vic[i]=vic[vix];
vix-=1;
i-=1;
if(vix==0)PauseTimer(vtmr);
}
i+=1;
}
}
function onVacuum(unit t,real x,real y)
{
real dx,dy,xt=GetUnitX(t),yt=GetUnitY(t);
vacuumdata this=vacuumdata.create();
vix+=1;vic[vix]=this;
dx=x-xt;dy=y-yt;
this.u=t;
this.r=0.0;
this.bz=GetUnitFlyHeight(t);
this.d=SquareRoot(dx*dx+dy*dy)*0.75;
this.z=(VACUUM_Z/(DISTANCE*0.75))*this.d;
this.a=bj_RADTODEG*Atan2(y-yt,x-xt);
UnitAddAbility(t,'Amrf');UnitRemoveAbility(t,'Amrf');
SetUnitPathing(t,false);
DestroyEffect(AddSpecialEffect(TARGETFX,xt,yt));
if(vix==1)TimerStart(vtmr,periodic,true,function onVacuumLoop);
}
function onFilter(unit t,player p) -> boolean
{
return UnitAlive(t) &&
!IsUnitType(t,UNIT_TYPE_MAGIC_IMMUNE) &&
!IsUnitType(t,UNIT_TYPE_STRUCTURE) &&
!IsUnitAlly(t,p);
}
function onLoop()
{
data this;
integer i=1;
real x,y;
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;
x=x+(Sin(((180.0/100)*this.rate)*bj_DEGTORAD)*DISTANCE)*Cos(this.angle*bj_DEGTORAD);
y=y+(Sin(((180.0/100)*this.rate)*bj_DEGTORAD)*DISTANCE)*Sin(this.angle*bj_DEGTORAD);
SetUnitX(this.dummy,x);
SetUnitY(this.dummy,y);
link=this;
GroupEnumUnitsInRange(grp,x,y,DAMAGE_AOE,Filter(function()
{
unit t=GetFilterUnit();
if(onFilter(t,link.owner) && !IsUnitInGroup(t,link.g))
{
UnitDamageTarget(link.caster,t,link.dmg,true,true,A_TYPE,D_TYPE,null);GroupAddUnit(link.g,t);
if(!link.b)
{
onVacuum(t,link.dx,link.dy);
}
}
else
{
}
}));
GroupClear(grp);
if(this.rate>=50.0 && this.b)
{
this.b=false;
this.speed=(100.0/DISTANCE)*SPEED_BACK;
GroupClear(this.g);
}
}
else
{
GroupClear(this.g);
DestroyEffect(this.fx);
KillUnit(this.dummy);
this.caster=null;
this.dummy=null;
this.owner=null;
data.destroy(this);
ic[i]=ic[ix];
ix-=1;
i-=1;
if(ix==0)PauseTimer(tmr);
}
i+=1;
}
}
function onCast() -> boolean
{
unit u;
player p;
real x1,y1,x2,y2,a,d;
integer i,lvl;
data this;
if(GetSpellAbilityId()==SPELL_ID)
{
u=GetTriggerUnit();
p=GetOwningPlayer(u);
lvl=GetUnitAbilityLevel(u,SPELL_ID);
i=LINES+(LINES_LVL*lvl);
d=DAMAGE+(DAMAGE_LVL*lvl);
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=data.create();
ix+=1;ic[ix]=this;
this.b=true;
this.dx=x2;
this.dy=y2;
this.dmg=d;
this.rate=0.0;
this.speed=(100.0/DISTANCE)*SPEED_FORTH;
this.angle=a*i;
this.caster=u;
this.owner=p;
this.dummy=CreateUnit(DUM_OWNER,DUM_ID,x2,y2,a*i);
this.fx=AddSpecialEffectTarget(MODEL,this.dummy,ATTACH);
if(this.g==null)this.g=CreateGroup();
if(ix==1)TimerStart(tmr,periodic,true,function onLoop);
i-=1;
}
u=null;
}
return false;
}
function onInit()
{
trigger t=CreateTrigger();
integer i=0;
while(i<=11)
{
TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null);
i+=1;
}
TriggerAddCondition(t,Filter(function onCast));
t=null;
}
}
}
//! endzinc
//TESH.scrollpos=0
//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