Doomhammer
Bob Kotick - Gamers' corporate spoilsport No. 1
- Reaction score
- 67
That's a real surprise: a quite tricky spell made with GUI! Especially the curved movement of the axes is very nice.
+rep
May I bow down, King of GUI?
Here's quite* the same thing using vJass and ABC (and CasterSystem, and CSSafety)
(*) Except that the axes here don't return to the caster. Btw I mine is made for the Beastmaster
+rep
May I bow down, King of GUI?
Here's quite* the same thing using vJass and ABC (and CasterSystem, and CSSafety)
JASS:
scope axes requires ABC, CSSafety, HelperFunctions
globals
constant integer axes_spellid = 039;A04B039;
private constant real width = 90.0
private constant integer leftaxe_id = 039;n010039;
private constant integer rightaxe_id =039;n001039;
private constant real speed = 800.0
private constant real interval = 0.04
private constant real spilldamage = 0.2 //spilldamage factor
private constant real flyheight = 65
private rect ax_rect
private boolexpr unitfilter
private boolexpr destfilter
private unit u
endglobals
private constant function Damage takes integer level returns real
return 90.0 + level * 60.0
endfunction
public function AxesInit takes nothing returns nothing
set ax_rect=Rect(-64.0,-64.0,64.0,64.0)
set unitfilter=Filter(function IsEnemy)
set destfilter=Filter(function IsDestructableVulnerable)
endfunction
private function DamageDestructable takes nothing returns nothing
call SetWidgetLife(GetEnumDestructable(),GetWidgetLife(GetEnumDestructable())-bj_enumDestructableRadius)
endfunction //use bj_enumDestructableRadius to transfer damage
struct axes
unit array u[4]
real array r[14] //total axes instances limited to 585
method set_axes takes unit c, unit u, player p returns nothing
set .u[0]=c
set .u[1]=u
set .r[0]=0.0 //t
set .r[1]=GetUnitX(c) //x
set .r[2]=GetUnitY(c) //y
set .r[3]=GetUnitX(u)-.r[1] //dx
set .r[4]=GetUnitY(u)-.r[2] //dy
set .r[5]=SquareRoot(.r[3]*.r[3]+.r[4]*.r[4]+.1) //d
set .r[6]=width/(.r[5]*.r[5]) //a
set .r[7]=-width*.r[4]/.r[5] //xa
set .r[8]=width*.r[3]/.r[5] //ya
set .r[9]=Atan2(.r[4],.r[3]) //w
set .r[10]=Sin(.r[9])
set .r[11]=Cos(.r[9])
if GetUnitFlyHeight(u)!=0 then
set .r[12]=GetUnitFlyHeight(u)-flyheight
else
set .r[12]=0.0
endif
set .r[13]=flyheight
set .u[2]=CreateUnit(p,leftaxe_id,.r[1]+.r[7],.r[2]+.r[8],bj_RADTODEG*.r[9])
set .u[3]=CreateUnit(p,rightaxe_id,.r[1]-.r[7],.r[2]-.r[8],bj_RADTODEG*.r[9])
endmethod
method onDestroy takes nothing returns nothing
local integer i=0
call KillUnit(.u[2])
call KillUnit(.u[3])
loop
exitwhen i>3
set .u<i>=null
set i=i+1
endloop
endmethod
endstruct
function HurtGroup takes nothing returns nothing
call UnitDamageTarget(u, GetEnumUnit(), bj_enumDestructableRadius, false, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, null)
endfunction
function TwinAxes_child takes nothing returns nothing
local timer t=GetExpiredTimer()
local axes ax=GetStructA(t)
local group g=CreateGroup()
local real ds
local real x
local real y
local real xr
local real yr
local real dam=Damage(GetUnitAbilityLevel(ax.u[0],axes_spellid))
set ax.r[0]=ax.r[0]+interval
set ds=ax.r[0]*speed
if ds<ax.r[5] then
if ax.r[12]!=0.0 then
set ax.r[13]=flyheight+ax.r[12]*ds/ax.r[5]
endif
set u=ax.u[0]
set x=ds
set y=-ax.r[6]*ds*ds
set xr=x*ax.r[11]-y*ax.r[10]
set yr=y*ax.r[11]+x*ax.r[10]
call SetUnitPosition(ax.u[2],ax.r[1]+ax.r[7]+xr,ax.r[2]+ax.r[8]+yr)
call SetUnitFlyHeight(ax.u[2],ax.r[13],0)
call MoveRectTo(ax_rect,ax.r[1]+ax.r[7]+xr,ax.r[2]+ax.r[8]+yr)
set bj_enumDestructableRadius=dam*spilldamage
set bj_forceRandomCurrentPick=GetOwningPlayer(ax.u[0])
call EnumDestructablesInRect(ax_rect,destfilter,function DamageDestructable)
call GroupEnumUnitsInRect(g,ax_rect,unitfilter)
if FirstOfGroup(g)!=null then
call ForGroup(g, function HurtGroup)
call GroupClear(g)
endif
set xr=x*ax.r[11]+y*ax.r[10]
set yr=x*ax.r[10]-y*ax.r[11]
call SetUnitPosition(ax.u[3],ax.r[1]-ax.r[7]+xr,ax.r[2]-ax.r[8]+yr)
call SetUnitFlyHeight(ax.u[3],ax.r[13],0)
call MoveRectTo(ax_rect,ax.r[1]-ax.r[7]+xr,ax.r[2]-ax.r[8]+yr)
call EnumDestructablesInRect(ax_rect,destfilter,function DamageDestructable)
call GroupEnumUnitsInRect(g,ax_rect,unitfilter)
if FirstOfGroup(g)!=null then
call ForGroup(g, function HurtGroup)
call GroupClear(g)
endif
else
call GroupEnumUnitsInRange(g, ax.r[1]+ax.r[3],ax.r[2]+ax.r[4],150.0,null)
if IsUnitInGroup(ax.u[1],g) then
call UnitDamageTarget(ax.u[0],ax.u[1], dam, false, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, null)
endif
call ax.destroy()
call ClearStructA(t)
call ReleaseTimer(t)
endif
endfunction
function TwinAxes takes nothing returns nothing
local axes ax=axes.create()
local unit u=GetTriggerUnit()
local timer t=NewTimer()
call ax.set_axes(u,GetSpellTargetUnit(),GetOwningPlayer(u))
call SetUnitAnimationByIndex(u, 9)
call SetStructA(t, ax)
call TimerStart(t, interval, true, function TwinAxes_child)
endfunction
endscope
//===========================================================================
function InitTrig_Axes takes nothing returns nothing
call axes_AxesInit()
call OnAbilityEffect(axes_spellid, "TwinAxes")
endfunction</i>
(*) Except that the axes here don't return to the caster. Btw I mine is made for the Beastmaster