• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] NovaSys

Level 5
Joined
Dec 20, 2008
Messages
67
Well ...its a System to create Novas (you all know them).
Since xe has no module to achieve this easily i made this (for guys who dont have/dont want to have xe in their map, i added 2 other versions. however i would recommend the xe version).

It uses one timer for all instances and it is pretty flexible, see attached map for more info.

v1.0: initial release
v1.1: dropped development of the no-xe versions, remade the create method (sorry not backwards compatible), added a bunch of additional operators for more flexibility, updated testmap.


JASS:
////////////////////////////////////////////////////////
//* * * * * * * * * * * * * * * * * * * * * * * * * * * 
//* NoVa System v1.1
//*     by Akolyt0r
//*
//*  requires xebasic and xefx by Vexorian
//*
//* its HIGHLY recommended to read the Documentation
//* AND to check out the Examples included in this Map
//* (especially when you dont have a clue what that
//* extending stuff is all about).
//* 
//* Credits:
//*     Vexorian for dummy.mdx and xe
//*     Anitarf, (Zerzax), ... for feedback/ help
//* 
//* * * * * * * * * * * * * * * * * * * * * * * * * * * 
////////////////////////////////////////////////////////

library NovaSys requires xebasic, xefx
globals // for more info to these, check out the documentation
    public constant integer    MAX_WAVES = 50
    public constant real       DEFAULT_HEIGHT  = 65
    public constant real       DEFAULT_CSIZE   = 50
    
//=================================================
//////// END CONFIGURATION ///////////////
////// Do Not Edit Below ////////////
//// Unless you know //////////
// what ur doing ////////

    private constant real PI2 = bj_PI*2
endglobals

private interface eventHandler
    method onUnitHit takes unit hitTarget returns nothing defaults nothing
    method onTimerLoop takes nothing returns nothing defaults nothing        
endinterface

struct Nova extends eventHandler

    real csize=DEFAULT_CSIZE
    readonly real elapsed
    
    //private membervariables
    private real spd = 500 // default speed
    private real dur = 1.0 // default duration
    private xefx array missile[MAX_WAVES]
    private group alreadyHit
    private real angoffset = 0
    private real cx
    private real cy
    private boolean active=false
    private integer waves
    private static Nova instance
    private static code timerCallback
    private static boolexpr enumFilter
    private static timer T
    private static group g
    private static Nova array V
    private static integer N=0
    debug private boolean speedset=false
    static method create takes real x, real y, string fxpath, integer waves returns Nova
        local Nova this=Nova.allocate()
        local integer i=0
        set this.cx = x
        set this.cy = y
        if this.alreadyHit==null then
            set this.alreadyHit = CreateGroup()
        endif
        set this.elapsed = 0
        set this.active = true
        set this.V[this.N] = this
        set this.N = this.N+1
        set this.waves = waves
        loop
            exitwhen i==waves
            set this.missile[i]=xefx.create(this.cx,this.cy,i*PI2/waves)
            set this.missile[i].z=DEFAULT_HEIGHT
            set this.missile[i].fxpath=fxpath
            set i=i+1
        endloop
        if(.N==1) then
            call TimerStart(.T, XE_ANIMATION_PERIOD, true, .timerCallback )
        endif              
        return this
    endmethod
    
    //SET operators

    method operator speed= takes real speed returns nothing
        set this.spd = speed
        debug set this.speedset = true
    endmethod
    method operator radius= takes real rad returns nothing
        debug if not this.speedset then
        debug   call BJDebugMsg(SCOPE_PREFIX+": Setup speed BEFORE you set radius (unless you WANT default speed)")
        debug endif
        set this.dur = rad/this.spd
    endmethod
    method operator duration= takes real dur returns nothing
        set this.dur = dur
    endmethod
    method operator angOffset= takes real angOffset returns nothing
        set this.angoffset = angOffset
    endmethod       
    method operator x= takes real x returns nothing
        set this.cx = x
    endmethod      
    method operator y= takes real y returns nothing
        set this.cy = y
    endmethod
    method operator z= takes real z returns nothing
        local integer j=0
        loop
            exitwhen j==this.waves
            set this.missile[j].z=z
            set j=j+1
        endloop
    endmethod
    method operator zangle= takes real zangle returns nothing
        local integer j=0
        loop
            exitwhen j==this.waves
            set this.missile[j].zangle=zangle
            set j=j+1
        endloop    
    endmethod    
    method operator scale= takes real s returns nothing
        local integer j=0
        loop
            exitwhen j==this.waves
            set this.missile[j].scale=s
            set j=j+1
        endloop
    endmethod


    //GET operators
    method operator speed takes nothing returns real
        return this.spd
    endmethod
    method operator radius takes nothing returns real
        return this.spd*this.dur
    endmethod
    method operator duration takes nothing returns real
        return this.dur
    endmethod
    method operator angOffset takes nothing returns real
        return this.angoffset
    endmethod    
    method operator x takes nothing returns real
        return this.cx
    endmethod
    method operator y takes nothing returns real
        return this.cy
    endmethod
    method operator z takes nothing returns real
        return this.missile[0].z
    endmethod
    method operator zangle takes nothing returns real
        return this.missile[0].zangle
    endmethod    

    
    
    private method onDestroy takes nothing returns nothing
        local integer j=0
        call GroupClear(.alreadyHit)
        loop
            exitwhen j==this.waves
            call this.missile[j].destroy()
            set j=j+1
        endloop
    endmethod

    method terminate takes nothing returns nothing
        set .active = false
    endmethod
    
    private static method NovaTimerCallback takes nothing returns nothing
        local integer i = 0
        local integer c = 0
        local integer j
        local real ang
        local real step
        local real aod
        local Nova this
        loop   
            exitwhen i == .N
            set this=.V[i]  
            set this.elapsed=this.elapsed+XE_ANIMATION_PERIOD
            if (this.active==false) then
                call this.destroy()
            else
                set j=0
                if(this.elapsed>this.dur)then
                    set this.active=false
                else
                    set aod = .angoffset
                    set Nova.instance=this
                    call GroupEnumUnitsInRange(Nova.g,this.cx,this.cy,this.elapsed*this.spd+this.csize+XE_MAX_COLLISION_SIZE,.enumFilter)   
                    if( this.onTimerLoop.exists and this.active ) then
                        call this.onTimerLoop()
                    endif
                    set step=XE_ANIMATION_PERIOD*this.spd
                    set aod = (.angoffset-aod)/(XE_ANIMATION_PERIOD*bj_PI)
                    loop
                        exitwhen j==this.waves
                        set ang=j*PI2/this.waves + this.angoffset
                        set this.missile[j].x= this.cx + this.spd*this.elapsed*Cos(ang)
                        set this.missile[j].y= this.cy + this.spd*this.elapsed*Sin(ang)
                        set this.missile[j].xyangle = ang + aod
                        set j=j+1
                    endloop                    
                endif
                set .V[c]=this
                set c=c+1
            endif
            set i=i+1
        endloop
        set .N=c
        if(c==0) then
            call PauseTimer(.T)
        endif
    endmethod
    
    private static method NovaEffectCallback takes nothing returns boolean
        local Nova this=.instance
        local unit u=GetFilterUnit()
        if GetUnitTypeId(u)!=XE_DUMMY_UNITID and GetWidgetLife(u) > 0. then
            if IsUnitInRangeXY(u,this.cx,this.cy,this.csize+this.elapsed*this.spd) and IsUnitInGroup(u,this.alreadyHit)==false then   
                call GroupAddUnit(this.alreadyHit,u)
                call this.onUnitHit(u)
            endif
        endif
        set u=null
        return false
    endmethod
    
    static method onInit takes nothing returns nothing
        set Nova.g=CreateGroup()
        set Nova.T=CreateTimer()
        set Nova.enumFilter=Condition(function Nova.NovaEffectCallback)
        set Nova.timerCallback=function Nova.NovaTimerCallback
    endmethod
endstruct
endlibrary
 

Attachments

  • NovaSys.v1.1.w3x
    86 KB · Views: 61
Last edited:
Level 5
Joined
Dec 20, 2008
Messages
67
true, but if you know what you are doing its easier to adjust to change the system to fit your needs even more... (e.g. you could make some member variables public if you need to access them for some reasons ...e.g. the xefx's)
 
Top