Hatebreeder
So many apples
- Reaction score
- 381
Description:
Requirements:
- Jass New Gen Editor
- Warcraft 1.24 Patch
-Cohadar's Timer Ticker (Also found in Demo Map)
Code:
I don't care about credits as long as you don't claim this your own.Summons a Sphere of leeching mana and unleashes it against enemy units in a 275 AOE of a target location. It aims for units with a mana source, pounding on it's very soul, damaging, stealing mana and growing with every mana point it feast on, though it also attacks units with no mana source (with the penalty of not growing at all) and it moves from unit to unit, if there are any other in a 300 AOE around the unit it is leeching on - else it will vanish.
- Jass New Gen Editor
- Warcraft 1.24 Patch
-Cohadar's Timer Ticker (Also found in Demo Map)
JASS:
scope SoulPounder initializer Init
globals
private constant integer ID = 039;A000039; //Spell Raw Code
private constant integer DUMMY = 039;u001039; //Dummy Raw Code
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
private constant real BAIL = 75. //Distance in front of Caster - required for the creation of the dummy
private constant real ARC = 1.4 // Dummy Arc movement
private constant string ERRORMSG = "There are no targets in this area." //Displays message if no unit is detected
private constant string SFX = "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl" //Impact SFX
private constant string ATTACH = "origin" //SFX attachmentpoint
private group CHECK = CreateGroup()
endglobals
private function Parabola takes real DistCur, real DistMax returns real //parabola function by shadow1500
local real N = (DistCur * 2) / DistMax - 1
return (-N * N + 1) * (DistMax / ARC)
endfunction
private function SetUnitXY takes unit u, real x, real y returns nothing //boarder safty
if x<GetRectMaxX(bj_mapInitialPlayableArea) and x>GetRectMinX(bj_mapInitialPlayableArea) and y<GetRectMaxY(bj_mapInitialPlayableArea) and y>GetRectMinY(bj_mapInitialPlayableArea) then
call SetUnitX(u,x)
call SetUnitY(u,y)
endif
endfunction
private constant function UnitFilter takes nothing returns boolean //basic unit Filter
return IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) == false and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(),bj_groupEnumOwningPlayer) == true
endfunction
private function Radius takes integer Lvl returns real //initial Area of Effect
return 275. + (0. * Lvl)
endfunction
private struct Data
private method Radius_Move takes nothing returns real //Area of effect after each bounce
return 300. + (0. * .Lvl)
endmethod
private method Speed takes nothing returns real //Speed of the projectile
return 17. + (0. * .Lvl)
endmethod
private method DamageAmount takes nothing returns real // Base Damage
return 45. * .Lvl
endmethod
private method Increase takes nothing returns real // stolen mana (in %)
return 0.05 + ( 0.02 * .Lvl )
endmethod
private method Jumps takes nothing returns integer // max jumps
return 3 + ( 2 * .Lvl)
endmethod
unit Caster
unit Dummy
unit Target
real MaxX
real MaxY
real Damage
group Group
integer Max = 0
integer Lvl
static method Timer takes nothing returns boolean
local Data this = TT_GetData()
local real DX = GetUnitX(.Dummy)
local real DY = GetUnitY(.Dummy)
local real TX = GetUnitX(.Target)
local real TY = GetUnitY(.Target)
local real Angle = Atan2(TY - DY,TX - DX)
local real X = DX + .Speed() * Cos(Angle)
local real Y = DY + .Speed() * Sin(Angle)
local real DistX
local real DistY
local real MaxDist
local real CurDist
local real Height
local real Mana
local integer Count = 0
local integer Check = 0
local unit Picked
local unit array Choose
set DistX = TX - DX
set DistY = TY - DY
set CurDist = SquareRoot(DistX * DistX + DistY * DistY)
set DistX = TX - .MaxX
set DistY = TY - .MaxY
set MaxDist = SquareRoot(DistX * DistX + DistY * DistY)
set Height = Parabola(CurDist,MaxDist)
call SetUnitXY(.Dummy,X,Y)
call SetUnitFlyHeight(.Dummy,Height,0)
call SetUnitFacing(.Dummy,Angle * bj_RADTODEG)
if .Target == null then
call .destroy()
return true
endif
if CurDist <= .Speed() then
if IsUnitType(.Target,UNIT_TYPE_DEAD) == false then
if GetUnitState(.Target,UNIT_STATE_MANA) >= 1 then
set Mana = GetUnitState(.Target,UNIT_STATE_MANA) * .Increase()
set .Damage = .Damage + Mana
call SetUnitState(.Target,UNIT_STATE_MANA,GetUnitState(.Target,UNIT_STATE_MANA) - Mana)
call UnitDamageTarget(.Caster,.Target,.Damage,true,true,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
call SetUnitScale(.Dummy,1. + (Mana/.Damage),1. + (Mana/.Damage),1. + (Mana/.Damage))
else
call UnitDamageTarget(.Caster,.Target,.Damage,true,true,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
endif
call DestroyEffect(AddSpecialEffectTarget(SFX,.Target,ATTACH))
endif
set bj_groupEnumOwningPlayer = GetOwningPlayer(.Caster)
call GroupEnumUnitsInRange(.Group,TX,TY,.Radius_Move(),Condition(function UnitFilter))
loop
set Picked = FirstOfGroup(.Group)
exitwhen Picked == null
if IsUnit(Picked,.Target) == false then
set Count = Count + 1
set Choose[Count] = Picked
endif
call GroupRemoveUnit(.Group,Picked)
endloop
set Picked = null
if Count > 0 and .Max < .Jumps() then
set .MaxX = GetUnitX(.Target)
set .MaxY = GetUnitY(.Target)
set .Target = Choose[GetRandomInt(1,Count)]
loop
exitwhen Check >= Count
set Check = Check + 1
set Choose[Check] = null
endloop
set .Max = .Max + 1
else
call .destroy()
return true
endif
endif
return false
endmethod
static method create takes unit c,real x, real y returns Data
local Data this = Data.allocate()
local real X
local real Y
local real TX = x
local real TY = y
local real Angle
local integer Count = 0
local integer Check = 0
local unit array Choose
local unit Picked
set .Caster = c
set .Lvl = GetUnitAbilityLevel(.Caster,ID)
set X = GetUnitX(.Caster)
set Y = GetUnitY(.Caster)
set Angle = Atan2(TY - Y,TX - X)
set .MaxX = X + BAIL * Cos(Angle)
set .MaxY = Y + BAIL * Sin(Angle)
set .Damage = .DamageAmount()
if .Group == null then
set .Group = CreateGroup()
else
call GroupClear(.Group)
endif
set bj_groupEnumOwningPlayer = GetOwningPlayer(.Caster)
call GroupEnumUnitsInRange(.Group,TX,TY,Radius(.Lvl),Condition(function UnitFilter))
loop
set Picked = FirstOfGroup(.Group)
exitwhen Picked == null
set Count = Count + 1
set Choose[Count] = Picked
call GroupRemoveUnit(.Group,Picked)
endloop
set Picked = null
set .Target = Choose[GetRandomInt(1,Count)]
set .Dummy = CreateUnit(GetOwningPlayer(.Caster),DUMMY,.MaxX,.MaxY,Angle * bj_RADTODEG)
loop
exitwhen Check >= Count
set Check = Check + 1
set Choose[Check] = null
endloop
call TT_Start(function Data.Timer,this)
return this
endmethod
private method onDestroy takes nothing returns nothing
call KillUnit(.Dummy)
endmethod
endstruct
private function CheckCast takes nothing returns boolean
local unit Caster
if GetSpellAbilityId() == ID then
set Caster = GetTriggerUnit()
set bj_groupEnumOwningPlayer = GetOwningPlayer(Caster)
call GroupEnumUnitsInRange(CHECK,GetSpellTargetX(),GetSpellTargetY(),Radius(GetUnitAbilityLevel(Caster,ID)),Condition(function UnitFilter))
if FirstOfGroup(CHECK) == null then
call SimError(GetOwningPlayer(Caster),ERRORMSG)
call IssueImmediateOrder(Caster,"stop")
return false
endif
call GroupClear(CHECK)
endif
set Caster = null
return true
endfunction
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == ID then
call Data.create(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
endif
return false
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger Trig = CreateTrigger( )
local trigger Trg = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( Trg , EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerRegisterAnyUnitEventBJ( Trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( Trg , Condition( function CheckCast ) )
call TriggerAddCondition( Trig, Condition( function Conditions ) )
set Trg = null
set Trig = null
endfunction
endscope
Comments? =P