Spell Railgun

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
A spell I rather made for fun: a railgun spiral effect as known from shooters à la Quake 2.

On the pic you can't see that much since I set the bullet velocity pretty high.

As a little annotation, I'm not very proud of my coding, which is based on yesterday's technology (cs cache) and therefore not too efficient in terms of function calls. I'm also using the caster system.
What's more worth being looked at is the maths behind it including the creation of a simple helix:

Code:
d = movment speed * timer interval
x = d
y = Cos(d*bj_DEGTORAD)
z = Sin(d*bj_DEGTORAD)

and the clockwise rotation of our helix in the target direction

Code:
w = angle between target and unit
x_new = x*cos(w) - y*sin(w)
y_new = y*cos(w) + x*sin(w)

So that's basically it. I'm open for all kinds of questions for those who want to make their own spiral spells. With a little effort this might even be made with GUI.



For all those less interested in the maths: Have fun killing some spiders!




JASS:


constant function FrostBolt_SpellId takes nothing returns integer
    return 'A004'
endfunction

constant function Helix_SpellId takes nothing returns integer
    return 'A003'
endfunction

constant function Helix_Radius takes real w returns real
    return 50.0 - 0.01 * w
endfunction

constant function Helix_TimerInterval takes nothing returns real
    return 0.01
endfunction

constant function Helix_Speed takes nothing returns real
    return 1500.0
endfunction

constant function Spiral_Factor takes nothing returns real
    return 3.6
endfunction

constant function Helix_Art takes nothing returns string
    return "Abilities\\Spells\\Other\\FrostBolt\\FrostBoltMissile.mdl"
endfunction

function Helix_Filter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit() , bj_groupEnumOwningPlayer) == true and GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitType(GetFilterUnit() , UNIT_TYPE_GROUND) == true
endfunction

function Helix_child takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local unit u=GetAttachedUnit(t, "helix_caster")
    local real sin=GetAttachedReal(t, "sin_angle")
    local real cos=GetAttachedReal(t, "cos_angle")
    local real v=Helix_Speed()*Helix_TimerInterval()
    local real d=GetAttachedReal(t, "helix_dist")+v
    local real x=d   
    local real y=Helix_Radius(d)*Cos(d*bj_DEGTORAD*Spiral_Factor())
    local real z=40.0+Helix_Radius(d)*Sin(d*bj_DEGTORAD*Spiral_Factor())
    local real xr=GetAttachedReal(t, "x")+x*cos-y*sin
    local real yr=GetAttachedReal(t, "y")+y*cos+x*sin
    local unit pro=GetAttachedUnit(t, "cst")
    local group g=CreateGroup()
    local boolexpr b=Filter(function Helix_Filter)
    if d<GetAttachedReal(t, "total_dist") then
        call AttachReal(t, "helix_dist",d)
        call SetUnitX(pro, xr)
        call SetUnitY(pro, yr)
        call SetUnitFlyHeight(pro,z, 0)
        set bj_groupEnumOwningPlayer=GetOwningPlayer(u)
        call GroupEnumUnitsInRange(g, xr, yr, 40, b)
        call CasterCastAbilityGroup(GetOwningPlayer(pro), FrostBolt_SpellId(), "frostnova", g, true)
    else
        call DestroyEffect(GetAttachedEffect(t, "effect"))
        call CleanAttachedVars(t)
        call ReleaseTimer(t)      
    endif
    call DestroyBoolExpr(b)
    call DestroyGroup(g)
    set g=null
endfunction

function Helix takes nothing returns nothing
    local unit u=GetSpellTargetUnit()
    local unit c=GetTriggerUnit()
    local real x=GetUnitX(c)
    local real y=GetUnitY(c)
    local real dx=GetUnitX(u)-x
    local real dy=GetUnitY(u)-y
    local real d=SquareRoot(dx*dx+dy*dy)
    local real ang=Atan2(dy,dx)
    local timer t=NewTimer()
    local unit cst=CreateCaster(bj_RADTODEG*ang,x+50.0/d*dx,y+50.0/d*dy)   
    call SetUnitScale(cst,0.4,0.4,0.4)
    call AttachObject(t, "helix_caster", c)
    call AttachReal(t, "x",x)
    call AttachReal(t, "y",y)
    call AttachReal(t, "sin_angle", Sin(ang))
    call AttachReal(t, "cos_angle", Cos(ang))
    call AttachReal(t, "helix_dist", 50.0)
    call AttachReal(t, "total_dist", d)
    call AttachObject(t, "cst", cst)
    call AttachObject(t, "effect", AddSpecialEffectTarget(Helix_Art(),cst,"origin"))
    call TimerStart(t, Helix_TimerInterval(), true, function Helix_child)
endfunction


//===========================================================================
function InitTrig_Helix takes nothing returns nothing
    call PreloadAbility(FrostBolt_SpellId())
    call PreloadAbility(Helix_SpellId())
    call OnAbilityEffect(Helix_SpellId(), "Helix")
endfunction
 

Attachments

  • rail.jpg
    rail.jpg
    217.7 KB · Views: 405
  • Railgun.w3x
    158.3 KB · Views: 416

Sim

Forum Administrator
Staff member
Reaction score
534
You might want to add comments throughout your constant functions, explaining what each of them does, separately, and the stuff. ;)

Also, why are there 2 triggers inside the WE?

I see only one up there.
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
the other spell is a little extra.

the constants are to the major extent self-explaining; what I called the "spiral factor" is the factor that determines how dense the loops are placed in comparison to a 'standard' helix: the smaller than 1 the denser the spirals, the larger the more "loose" they become. If more explanation is required, I'll add detailed comments within the next few days. Yet I didn't really plan this as a spell for submission, but rather as a demo for members to see how about any two- or three dimensional shape or trajectory can be rotated around a certain coordinate and adjusted accordingly.
 

Sim

Forum Administrator
Staff member
Reaction score
534
And nobody has that bonus spell? ;)

Well, first of all add testing features. I hate when the testing unit dies and I'm forced to restart. Remove the cooldown also - we're here to test.

Second, why not make it on attack? it's a railgun afterall, how can it be only one shot? Plus, it would look better.

Third and finally, why does it slow? 0.o
 

Doomhammer

Bob Kotick - Gamers' corporate spoilsport No. 1
Reaction score
67
The on attack...I'll see what I can do. I also thought that at short-range targeted units it should shoot way through.

The slowing is due to the frost-bolt missile I'm using as effect; so I decided to make it an "iceshard - railgun", making the units hit get a freeze-shock.



Edit: It'll take me some more time to add & change things.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top