package Shade
import SpellEffectEvents
import PeriodicModule
import FadeUnit
player referencePlayer = null
// Scythe makes her way ellusively through wild hostiles on the fields - slashing all those who come inbetween.
// Deals damage in a 205 aoe 205 distance in front of her and blinks 410 distance forward.
// Requirements
// General: Wurst installed correctly and wurst editor
// WurstCodes: PeriodicModule, FadeUnit, SpellEffectEvents and Wurst packages
// ObjectEditor: Scythe Illu(unit), Shade(ability), Shade Disabled(ability), Shade Learn(ability), Show Shade Charges(ability)
// Show Shade Charges(buff)
// Instructions
// - Give your hero only the Shade Learn(ability)
// - Make sure Show Shade Charges(ability) buff data is set to Show Shade Charges(buff)
// - Set required configurables correctly
// Required configs
// ===========================================================
// abilId = Castable ability
// disAbilId = Ability icon that shows up when disabled
// illuId = Scythe illusion ID
// showId = Show Charges ability
// buffId = Show Charges buff
// learnId = Dummy learn ability
constant int abilId = 'A005'
constant int disAbilId = 'A006'
constant int illuId = 'e001'
constant int showId = 'A00A'
constant int buffId = 'B000'
constant int learnId = 'A00B'
//
// End of required configs
// Start of spell configurables
//========================================================================
// fxPath = Effect displayed when units are damaged
// blinkPath = Effect displayed where the caster used to be
// cStart = Starting fade color of Giant Scythe
// cEnd = Ending fade color of Giant Scythe
// cTime = How long it takes to fade
// textColor = Color of Shade Charges Text
// textSize = Size of Shade Charges Text
// dtype = Damage type
// atype = Attack type
// damage = How much damage does it deal
// blinkDist = How far does the caster blink
// damagePoint = How far from the caster to deal damage
// damageAoe = Area of damage dealt
constant string fxPath = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"
constant string blinkPath = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"
constant colorA cStart = colorA(150, 235, 235, 255)
constant colorA cEnd = colorA(150, 235, 235, 0)
constant real cTime = 1.0
constant colorA textColor = colorA(150, 200, 150, 200)
constant real textSize = 12.
constant damagetype dtype = DAMAGE_TYPE_UNKNOWN
constant attacktype atype = ATTACK_TYPE_NORMAL
function damage(unit u) returns real
return 5. * u.getAbilityLevel(abilId) + ((.1 + .1 * u.getAbilityLevel(abilId)) * GetHeroAgi(u, true))
function blinkDist() returns real
return 410.
function damagePoint() returns real
return 205.
function damageAoe() returns real
return 205.
//
// End of spell configurables
class Charges
use PeriodicModule
unit u
int cc
int mc
int abil
int disAbil
real time
real reTime
texttag tag
protected constant static real ANIMATION_PERIOD = .02
override function onTimedLoop()
string s = ""
if cc < mc
if time <= 0.
cc++
if cc < mc
time = reTime
if cc == 1
u.removeAbility(disAbilId)
u.addAbility(abilId)
u.setAbilityLevel(abilId, u.getAbilityLevel(learnId))
UnitMakeAbilityPermanent(u, true, abilId)
else
time -= ANIMATION_PERIOD
if time <= 0.
time = 0.
if GetLocalPlayer() == u.getOwner() and u.hasAbility(buffId)
s = I2S(cc) + "(" + R2SW(time, 1,1) + ")"
tag.setText(s, textSize)
tag.setPos(vec3(u.getX()+25., u.getY(), 25))
private static function get(unit u) returns thistype
thistype n = first
while n != null
if n.u == u
return n
n = n.getNext()
return n
static function check(unit u)
thistype n = get(u)
n.cc = n.cc - 1
if n.cc == 0
UnitMakeAbilityPermanent(u, false, abilId)
u.removeAbility(abilId)
u.addAbility(disAbilId)
else if n.cc == n.mc - 1
n.time = n.reTime
construct(unit u, int mc, real reTime, int sC, int abil, int disAbil)
this.u = u
this.cc = sC
this.mc = mc
this.reTime = reTime
this.time = 0.
this.abil = abil
this.disAbil = disAbil
this.tag = CreateTextTag()
tag.setColor(textColor)
this.startPeriodic()
function filter() returns boolean
return IsUnitEnemy(GetFilterUnit(), referencePlayer) and GetFilterUnit().isAlive()
function onCast(unit u, int lvl)
angle ang = u.getFacing().asAngleDegrees()
real nx = polarProjectionX(u.getX(), damagePoint(), ang)
real ny = polarProjectionY(u.getY(), damagePoint(), ang)
unit d = CreateUnit(u.getOwner(), illuId, nx, ny, ang.degrees())
new FadeUnit(d, cStart, cEnd, cTime, true)
d.setAnimation("attack")
d.queueAnimation("stand")
d.setTimeScale(.65)
d.setScale(3.5)
AddSpecialEffect(blinkPath, u.getX(), u.getY()).destr()
group g = CreateGroup()
referencePlayer = u.getOwner()
g.enumUnitsInRange(vec2(nx, ny), 205., Filter(function filter))
real dmg = damage(u)
while g.hasNext()
unit fg = g.next()
UnitDamageTarget(u, fg, dmg, false, false, atype, dtype, WEAPON_TYPE_WHOKNOWS)
AddSpecialEffectTarget(fxPath, fg, "origin").destr()
g.destr()
nx = polarProjectionX(u.getX(), blinkDist(), ang)
ny = polarProjectionY(u.getY(), blinkDist(), ang)
u.setX(nx)
u.setY(ny)
Charges.check(u)
function onLearn() returns boolean
unit u = GetTriggerUnit()
if GetLearnedSkill() == learnId
if u.getAbilityLevel(learnId) == 1
u.addAbility(showId)
u.addAbility(abilId)
new Charges(u, 3, 6., 1, abilId, disAbilId)
else
u.setAbilityLevel(abilId, u.getAbilityLevel(learnId))
return false
init
CreateTrigger()
..registerAnyUnitEvent(EVENT_PLAYER_HERO_SKILL)
..addCondition(Condition(function onLearn))
Charges.setPeriod(Charges.ANIMATION_PERIOD)
onSpellEffect(abilId, (unit caster, int lvl) ->
onCast(caster, lvl))