Another Omnislash. vJass

Zeth

Member
Reaction score
3
Ok, i know there are a lot of Omnislash spells encoded, but only found one approved in THW, and it's GUI. Anyway, i'm not going to send this as a resource because people don't like repeated spells :D

Requirements:

GT - Jesus4Lyf

TimerUtils - Vexorian

Here's a test map, wich has the dummy spell (i used Channel)

http://www.epicwar.com/maps/156575/

And the code:

JASS:
scope Omnislash // requires TimerUtils, GT

    globals
        private constant integer SPELL_ID        = 'A000' // The ID of the ability
        private constant real    AREA            = 450.   // Range of the ennumeration
        private constant real    LOOP            = .4     // Period
        private constant string  SFX             = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl" // Principal SFX
        private constant string  SFX2            = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"          // SFX created in each slash
        private constant string  SFXATTACH       = "weapon" 
        private constant string SFX2ATTACH       = "chest"
        private constant string  ATTACKSTG       = "attack" // You can change it to "attack slam" if you want
        private constant boolean INVULNERABLE    = true     // Dooes Yurnero becomes invulnerable while omnislashing?
        private constant attacktype ATTACKTYPE   = ATTACK_TYPE_HERO
        private constant damagetype DAMAGETYPE   = DAMAGE_TYPE_NORMAL
        private          group      Enum_Group   = CreateGroup() // Group for the enum, is always empty
        private constant integer MAX_ENUM_UNITS  = 30 // Max size of the array... 
    endglobals

private struct OmniStruct
 
        private effect sfx // Phoenix effect
        private player p   // Owning player of casting unit
        private unit c     // Casting unit
        private unit t     // Target unit
        private integer lvl
        private integer cnt// Number of slashes
        private timer tm   
        private real ang   // Angle used to define a random position around the target
        private real cX    
        private real cY
        private real tX
        private real tY
        private real dmg   // Damage, it's a random number between 150 and 250 in each slash
        private integer num=2 // Number of actual slashes
    
        private static unit array targets[MAX_ENUM_UNITS] // Used for group the targets and select a random one from there
        private static integer index=0 

    method Slashes takes integer level returns integer
       return R2I(0.50*level*level+0.50*level+2.00)
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i=0
        call DestroyEffect(.sfx)
        call SetUnitVertexColor(.c,255,255,255,255)
        call SetUnitInvulnerable(.c,false)
        call SetUnitPathing(.c,true)
        call ReleaseTimer(.tm)
        loop
            exitwhen i>30
            set .targets<i>=null // Set all the targets to null
            set i=i+1
        endloop
        set .sfx=null
        set .p=null
        set .c=null
        set .t=null
        set .tm=null
    endmethod

    method Slash takes nothing returns nothing
        set .ang=GetRandomReal(1.,360.) 
        set .tX=GetUnitX(.t)+50.*Cos(.ang*bj_DEGTORAD)
        set .tY=GetUnitY(.t)+50.*Sin(.ang*bj_DEGTORAD)
        call SetUnitFacing(.c,Atan2(.tY-.cY,.tX-.cX)*bj_RADTODEG)
        set .dmg=GetRandomReal(150.,250.) 
        call SetUnitX(.c,.tX)
        call SetUnitY(.c,.tY)
        call SetUnitAnimation(.c,ATTACKSTG)
        call DestroyEffect(AddSpecialEffectTarget(SFX2,.c,SFX2ATTACH))
        call UnitDamageTarget(.c,.t,.dmg,true,true,ATTACKTYPE,DAMAGETYPE,null)
        call IssueTargetOrder(.c,ATTACKSTG,.t)   
    endmethod
        
    static method Filter takes nothing returns boolean
        local thistype this=GetTimerData(GetExpiredTimer())
        set .t=GetFilterUnit()
        if IsUnitEnemy(.t,.p) and GetWidgetLife(.t)&gt;.405 and not IsUnitType(.t,UNIT_TYPE_STRUCTURE) and IsUnitVisible(.t,.p) then
            set .targets[.index]=.t // If the conditions are true, then add the filter unit to the array
            set .index=.index+1
        endif
        return false // No unit enters the group
    endmethod
    
    static method onLoop takes nothing returns nothing
        local thistype this=GetTimerData(GetExpiredTimer())
        local integer i=0
        if .num&gt;.cnt then 
            call .destroy() 
        else
            set .num=.num+1
            call GroupEnumUnitsInRange(Enum_Group,.tX,.tY,AREA,Condition(function thistype.Filter))
            set .t=.targets[GetRandomInt(0,.index-1)]
            if .t!=null then
                call .Slash()
                set .index=0
                loop
                   exitwhen i&gt;MAX_ENUM_UNITS
                   set .targets<i>=null // Cleaning the array
                   set i=i+1
                endloop
            else
                call .destroy()
            endif
        endif
    endmethod

    static method create takes nothing returns thistype
        local thistype this=.allocate()
        set .tm=NewTimer()
        set .c=GetTriggerUnit()
        set .cX=GetUnitX(.c)
        set .cY=GetUnitY(.c)
        set .t=GetSpellTargetUnit()
        set .p=GetOwningPlayer(.c)
        set .lvl=GetUnitAbilityLevel(.c,SPELL_ID)
        set .cnt=Slashes(.lvl)
        call SetUnitVertexColor(.c,255,255,255,125)
        call SetUnitPathing(.c,false)
        call SetUnitInvulnerable(.c,INVULNERABLE)
        call .Slash()
        set .sfx=AddSpecialEffectTarget(SFX,.c,SFXATTACH)
        call SetTimerData(.tm,this)
        call TimerStart(.tm,LOOP,true,function thistype.onLoop)
        return this
    endmethod
endstruct

private function Execute takes nothing returns nothing
        call OmniStruct.create()
endfunction
    
public function InitTrig takes nothing returns nothing
    local trigger t=CreateTrigger()
    call GT_RegisterStartsEffectEvent(t,SPELL_ID)
    call TriggerAddAction(t,function Execute)
    set t=null
endfunction
endscope</i></i>


Recommendations? :p

Updates:

15/12/10 : Added method to calculate number of slashs, thanks Carnerox.
 

Carnerox

The one and only.
Reaction score
84
You should do Slashes like this, instead of doing the If Level =.

JASS:
method Slashes takes integer level returns real
   return 0.50*level*level+0.50*level+2.00
endmethod
 

Bo-Bo

New Member
Reaction score
8
Hey!

I got a few questions:

JASS:
static method Filter takes nothing returns boolean
    local thistype this=GetTimerData(GetExpiredTimer())
    set .t=GetFilterUnit()
    if IsUnitEnemy(.t,.p) and GetWidgetLife(.t)&gt;.405 and not IsUnitType(.t,UNIT_TYPE_STRUCTURE) and IsUnitVisible(.t,.p) then
        set .targets[.index]=.t // If the conditions are true, then add the filter unit to the array
        set .index=.index+1
    endif
    return false // No unit enters the group
endmethod


1. Why does this work?
The Filter function isn't called by a timer!? So how can you get an expired timer?
Or can you use this, because the Filter function is called by the GroupEnumUnitsInRange function?

2. I still don't get which is better:
JASS:
GetWidgetLife(.t)&gt;.405
or
 

Zeth

Member
Reaction score
3
1. Because the Filter function is called by GroupEnumUnitsInRange, that function is called inside onLoop function, onLoop function IS called by a timer. :p

2. the first is the best, also you can use UnitAlive

Carnerox said:
You should do Slashes like this, instead of doing the If Level =.

Thanks man, that's great!!!
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
2. I still don't get which is better:
JASS:
GetWidgetLife(.t)&gt;.405
or

I don't quite remember. I think the GetWidgetLife and 0.405 life has problems with stuff like reincarnation (or maybe it's the other one). However, Blizzard implemented the [ljass]UnitAlive[/ljass] native (click that for link), which is as simple as declaring the native.
 

Bo-Bo

New Member
Reaction score
8
1. Because the Filter function is called by GroupEnumUnitsInRange, that function is called inside onLoop function, onLoop function IS called by a timer. :p

Haha^^
Ok, that's cool, thanks!
 
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