- Reaction score
- 456
Webshot
Spider Queen shoots out web and pulls itself to
the target point using it, damaging all enemy
ground units on it's way.
Level 1: Deals 75 damage.
Level 2: Deals 125 damage.
Level 3: Deals 175 damage.
Requires NewGen
Code:
JASS:
scope Webshot initializer Init
globals
private constant integer SPELL_ID = 039;A000039;
//The caster moves MAX_DISTANCE in MAX_DURATION. So, if the distance
//to the target point is half MAX_DISTANCE, the duration will be half
//too.
private constant real MAX_DISTANCE = 1200.00
private constant real MAX_DURATION = 1.20
//String path for lightning effect, and some colour configuration.
private constant string LIGHTNING_PATH = "LEAS"
private constant real LIGHTNING_A = 0.82
private constant real LIGHTNING_R = 0.15
private constant real LIGHTNING_G = 1.00
private constant real LIGHTNING_B = 0.10
//Distance from the center of the caster to the angle direction.
//The root of the webs are placed on those positions. If you don't
//get it, test it.
private constant real LIGHTNING_DISTANCE = 75.00
private constant real LIGHTNING_ANGLE = bj_PI / 4
private constant real DAMAGE_RADIUS = 112.00
private constant attacktype DAMAGE_ATTACK_TYPE = ATTACK_TYPE_NORMAL
private constant damagetype DAMAGE_DAMAGE_TYPE = DAMAGE_TYPE_UNIVERSAL
private constant weapontype DAMAGE_WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
private constant string DAMAGE_EFFECT = "Abilities\\Weapons\\PoisonArrow\\PoisonArrowMissile.mdl"
private constant string DAMAGE_EFFECT_POINT = "chest"
private constant real INTERVAL = 0.03
endglobals
private constant function DamageFilter takes unit caster, unit target returns boolean
return IsUnitEnemy(target, GetOwningPlayer(caster)) and IsUnitType(target, UNIT_TYPE_GROUND) == true
endfunction
private constant function DamageAmount takes integer level returns real
return 25.00 + level * 50.00
endfunction
private struct Data
private static timer Timer = CreateTimer()
private static Data array Array
private static integer Counter = 0
private unit caster
private real angle
private real xInc
private real yInc
private real damage
private lightning web1
private lightning web2
private real targetX
private real targetY
private integer ticks
private group currentGroup = CreateGroup()
private group damagedGroup = CreateGroup()
private static method ReturnTrue takes nothing returns boolean
return true
endmethod
private method actions takes nothing returns nothing
local real casterX = GetUnitX(.caster)
local real casterY = GetUnitY(.caster)
local unit f
call SetUnitPathing(.caster, false)
call SetUnitPosition(.caster, casterX + .xInc, casterY + .yInc)
call SetUnitFacing(.caster, .angle * bj_RADTODEG)
call MoveLightning(.web1, true, casterX + LIGHTNING_DISTANCE * Cos(.angle + LIGHTNING_ANGLE), casterY + LIGHTNING_DISTANCE * Sin(.angle + LIGHTNING_ANGLE), .targetX, .targetY)
call MoveLightning(.web2, true, casterX + LIGHTNING_DISTANCE * Cos(.angle - LIGHTNING_ANGLE), casterY + LIGHTNING_DISTANCE * Sin(.angle - LIGHTNING_ANGLE), .targetX, .targetY)
call GroupEnumUnitsInRange(.currentGroup, GetUnitX(.caster), GetUnitY(.caster), DAMAGE_RADIUS, Condition(function Data.ReturnTrue))
loop
set f = FirstOfGroup(.currentGroup)
exitwhen f == null
call GroupRemoveUnit(.currentGroup, f)
if not IsUnitInGroup(f, .damagedGroup) and DamageFilter(.caster, f) then
call GroupAddUnit(.damagedGroup, f)
call UnitDamageTarget(.caster, f, .damage, true, false, DAMAGE_ATTACK_TYPE, DAMAGE_DAMAGE_TYPE, DAMAGE_WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(DAMAGE_EFFECT, f, DAMAGE_EFFECT_POINT))
endif
endloop
endmethod
private static method Handler takes nothing returns nothing
local integer i = 0
loop
exitwhen i == .Counter
if .Array<i>.ticks == 0 or GetUnitState(.Array<i>.caster, UNIT_STATE_LIFE) < 0.405 then
call .Array<i>.destroy()
set .Array<i> = .Array[.Counter - 1]
set .Counter = .Counter - 1
set i = i - 1
else
call .Array<i>.actions()
set .Array<i>.ticks = .Array<i>.ticks - 1
endif
set i = i + 1
endloop
if .Counter == 0 then
call PauseTimer(.Timer)
endif
endmethod
static method create takes unit caster, real targetX, real targetY returns Data
local Data dat = .allocate()
local real casterX = GetUnitX(caster)
local real casterY = GetUnitY(caster)
local real dx = targetX - casterX
local real dy = targetY - casterY
local real distance = SquareRoot(dx * dx + dy * dy)
local real angle = Atan2(dy, dx)
local real web1x = casterX + LIGHTNING_DISTANCE * Cos(angle + LIGHTNING_ANGLE)
local real web1y = casterY + LIGHTNING_DISTANCE * Sin(angle + LIGHTNING_ANGLE)
local real web2x = casterX + LIGHTNING_DISTANCE * Cos(angle - LIGHTNING_ANGLE)
local real web2y = casterY + LIGHTNING_DISTANCE * Sin(angle - LIGHTNING_ANGLE)
local real duration = distance / MAX_DISTANCE * MAX_DURATION
set dat.caster = caster
set dat.xInc = (distance / duration * INTERVAL) * Cos(angle)
set dat.yInc = (distance / duration * INTERVAL) * Sin(angle)
set dat.angle = angle
set dat.damage = DamageAmount(GetUnitAbilityLevel(caster, SPELL_ID))
set dat.web1 = AddLightning(LIGHTNING_PATH, true, web1x, web1y, targetX, targetY)
call SetLightningColor(dat.web1, LIGHTNING_R, LIGHTNING_G, LIGHTNING_B, LIGHTNING_A)
set dat.web2 = AddLightning(LIGHTNING_PATH, true, web2x, web2y, targetX, targetY)
call SetLightningColor(dat.web2, LIGHTNING_R, LIGHTNING_G, LIGHTNING_B, LIGHTNING_A)
set dat.targetX = targetX
set dat.targetY = targetY
set dat.ticks = R2I(duration / INTERVAL)
set .Array[.Counter] = dat
set .Counter = .Counter + 1
if .Counter == 1 then
call TimerStart(.Timer, INTERVAL, true, function Data.Handler)
endif
return dat
endmethod
private method onDestroy takes nothing returns nothing
call SetUnitPathing(.caster, true)
call DestroyLightning(.web1)
call DestroyLightning(.web2)
call DestroyGroup(.damagedGroup)
call DestroyGroup(.currentGroup)
endmethod
endstruct
private function Actions takes nothing returns nothing
local location targetLoc = GetSpellTargetLoc()
call Data.create(GetTriggerUnit(), GetLocationX(targetLoc), GetLocationY(targetLoc))
call RemoveLocation(targetLoc)
set targetLoc = null
endfunction
//==========================================================
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Actions)
endfunction
endscope</i></i></i></i></i></i></i>
Screen:
___________________________________________________________
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯