Cohadar
master of fugue
- Reaction score
- 209
Basically a version of Pudge Hook.
With a small exception that this one works with blinking.
With a small exception that this one works with blinking.
JASS:
//===========================================================================
// Demo spell for use of ABC timer attaching and PUI unit attaching
// Author: Cohadar.
// Date: 02.December.2007
//
// How to implement:
// Copy triggers ABC, PUI, CSSafety, and this trigger in your map
// Copy all units and abilities into your map, then change raw codes in triggers
// Make sure your trigger names are the same as scope names
// or spells will not work. (I use local triggers)
//===========================================================================
scope MagicNet
globals
private constant integer AID_MAGIC_NET = 'A001'
private constant real PERIOD = 0.035
private constant string NET_MODEL = "Abilities\\Spells\\Human\\AerialShackles\\AerialShacklesTarget.mdl"
private constant string LIGHTNING = "LEAS"
private constant real AOE = 96.
private constant real PROXIMITY_BORDER = 10000. // 100*100
endglobals
private function distance takes integer level returns real
return 400. + (level * 200.)
endfunction
private function speed takes integer level returns real
return 300. + (level * 150.)
endfunction
private function damage takes integer level returns real
return 100. + (level * 50.)
endfunction
//===========================================================================
private struct Data
unit hero
timer tim
private static Data array PUI
boolean inProgress = false
boolean extending
real x
real y
real tx
real ty
lightning net
integer ticks
real delta
unit snatched
group g
effect fx
//-------------------------------------------------------------------------
static method create takes unit hero returns Data
local Data ret = Data.allocate()
set ret.hero = hero
set ret.tim = NewTimer() // CSSafety
call SetTimerStructA(ret.tim, ret) // ABC
set Data.PUI[GetUnitIndex(hero)] = ret // PUI
set ret.g = CreateGroup()
return ret
endmethod
//-------------------------------------------------------------------------
private method HandleGraphics takes nothing returns nothing
local real angle
local real dx
local real dy
if .extending then
set dx = .tx-.x
set dy = .ty-.y
set angle = Atan2(dy, dx)
set .x = .x + .delta*Cos(angle)
set .y = .y + .delta*Sin(angle)
call MoveLightning(.net, false, GetUnitX(.hero), GetUnitY(.hero), .x, .y)
set .ticks = .ticks - 1
if (.ticks <= 0) then
set .extending = false
endif
else
set dx = GetUnitX(.hero) - .x
set dy = GetUnitY(.hero) - .y
set angle = Atan2(dy, dx)
set .x = .x + .delta*Cos(angle)
set .y = .y + .delta*Sin(angle)
call MoveLightning(.net, false, GetUnitX(.hero), GetUnitY(.hero), .x, .y)
if (dx*dx < PROXIMITY_BORDER) and (dy*dy < PROXIMITY_BORDER) then
call DestroyLightning(.net)
call PauseTimer(.tim)
set .inProgress = false
if .snatched != null then
call DestroyEffect(.fx)
endif
endif
endif
endmethod
private static unit gp_hero
//-------------------------------------------------------------------------
private static method filter takes nothing returns boolean
if GetFilterUnit() == Data.gp_hero then
return false
endif
if GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) < .405 then
return false
endif
if IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) then
return false
endif
return true
endmethod
//-------------------------------------------------------------------------
private static method Periodic takes nothing returns nothing
local Data data = GetTimerStructA(GetExpiredTimer()) // ABC
call data.HandleGraphics()
if data.snatched == null then
call GroupClear(data.g)
set Data.gp_hero = data.hero
call GroupEnumUnitsInRange(data.g, data.x, data.y, AOE, Filter(function Data.filter))
set data.snatched = FirstOfGroup(data.g)
if data.snatched != null then
set data.fx = AddSpecialEffectTarget(NET_MODEL, data.snatched, "chest")
set data.extending = false
if IsUnitEnemy(data.hero, GetOwningPlayer(data.snatched)) then
call UnitDamageTarget(data.hero, data.snatched, damage(GetUnitAbilityLevel(data.hero, AID_MAGIC_NET)), true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
endif
else
call SetUnitX(data.snatched, data.x)
call SetUnitY(data.snatched, data.y)
endif
endmethod
//-------------------------------------------------------------------------
method Start takes real tx, real ty returns nothing
local integer level
local real dx
local real dy
if .inProgress then
call SimError(GetOwningPlayer(.hero), "Magic Net is already casted!")
else
set .inProgress = true
set .extending = true
set .snatched = null
set .tx = tx
set .ty = ty
set .x = GetUnitX(.hero)
set .y = GetUnitY(.hero)
set .net = AddLightning(LIGHTNING, false, .x, .y, .x, .y)
set level = GetUnitAbilityLevel(.hero, AID_MAGIC_NET)
set .delta = speed(level)*PERIOD
set dx = .tx-.x
set dy = .ty-.y
set .ticks = R2I(RMinBJ(distance(level), SquareRoot(dx*dx+dy*dy))/.delta)
call TimerStart(.tim, PERIOD, true, function Data.Periodic)
endif
endmethod
//-------------------------------------------------------------------------
static method Get takes unit hero returns Data
local integer index
set index = GetUnitIndex(hero) // PUI
if Data.PUI[index] == 0 then
debug call BJDebugMsg("|c00FFCC00"+"MagicNet_Data struct created on first use for hero: " + GetHeroProperName(hero))
return Data.create(hero)
endif
return Data.PUI[index]
endmethod
//-------------------------------------------------------------------------
method onDestroy takes nothing returns nothing
call ClearTimerStructA(.tim) // ABC
call ReleaseTimer(.tim) // CSSafety
set Data.PUI[GetUnitIndex(.hero)] = 0 // PUI
call RemoveUnit(.hero)
call DestroyGroup(.g)
endmethod
endstruct
//===========================================================================
private function Actions takes nothing returns nothing
local Data data = Data.Get(GetTriggerUnit())
local location temp = GetSpellTargetLoc()
call data.Start(GetLocationX(temp), GetLocationY(temp))
call RemoveLocation(temp)
set temp = null
endfunction
//===========================================================================
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_MAGIC_NET
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( trig, Condition( function Conditions ) )
call TriggerAddAction( trig, function Actions )
set trig = null
endfunction
endscope
Magic leash will extend from caster in the throw direction searching for something to grab.
Once it finds something it will engulf it with magic threads and pull it towards the caster.
Enemies caught inside net will be damaged.
Attachments
-
394.3 KB Views: 689
-
56.3 KB Views: 498