• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Crow Attack v1.00

Crow Attack

Crows start flying out of the caster and the caster dissapears. Then these crows start flying into the target location. When they arrive, the crows should start flying into the center of the targeted point, and the caster reappears.
Originally requested by Barathrum, enjoy, give credit where due :D.

JASS:
library CrowAttack requires TimerUtils, SimError, xefx, xedamage, optional BoundSentinel
//-----------------------------------------------------------------------------------------------
// Crow Attack v1.00 by scorpion182
//  requires: TimerUtils, SimError, xe, BoundSentinel by vexorian
//
//
//
//
//-----------------------------------------------------------------------------------------------
//-----------------------CALIBRATION SECTION-----------------------------------------------------
    globals
        private constant integer SPELL_ID       = 'A000' // spell rawcode
        private constant real    CROW_SCALE     = 1. //crow scaling value
        private constant string  CROW_PATH      = "units\\critters\\Vulture\\Vulture.mdl" //crow path
        private constant string  CASTER_ART     = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
        private constant integer RED            = 0 //coloring in RGB
        private constant integer GREEN          = 0
        private constant integer BLUE           = 0
        private constant integer ALPHA          = 255
        private constant real    CASTING_TIME   = 1. //spell casting time
        private constant integer MAX_CROW       = 25 //maximum crow instance
        private constant real    FINISH_DIST    = 80. //finish point min distance
        private constant real    MIN_DIST       = 300. //minimum casting distance
        private constant real    CROW_H         = 100. //crow movement height
        private constant real    SPEED          = 600. * XE_ANIMATION_PERIOD //crow movement speed
        private constant string  ERROR_MSG      = "Inside Minimum Range." //error message
        private constant string  DAMAGE_FX      = "" //effect on-damage, because it's used xe_animation_period (0.025) it would be lag
        private constant string  DAMAGE_ATTCH   = "origin" //damage effect attachment point
    endglobals

    private constant function GetCrowCount takes integer lvl returns integer 
        return 12 + lvl * 0 //how many crows?
    endfunction
    
    private constant function GetCollision takes integer lvl returns real
        return 125. + lvl * 0 //crow collision size to give damage
    endfunction
    
    private constant function GetAoE takes integer lvl returns real
        return 200. + lvl * 0 //crow aoe summon
    endfunction

    private constant function GetDamage takes integer lvl returns real
        return 10. + lvl * 0 //does 10 damage per second each crow
    endfunction
    
    //damage filter
    private function DamageOptions takes xedamage spellDamage returns nothing
        set spellDamage.dtype = DAMAGE_TYPE_UNIVERSAL
        set spellDamage.atype = ATTACK_TYPE_NORMAL
        set spellDamage.exception = UNIT_TYPE_STRUCTURE //don't damage building
        set spellDamage.visibleOnly = true //only damage visible unit
        set spellDamage.damageAllies = false //damage allies if true
        set spellDamage.damageTrees = true //damage destructables?
    endfunction

    
//-----------------------END OF CALIBRATION SECTION----------------------------------------------
    globals
        private xedamage xed
    endglobals
    
    private struct data
        unit caster
        timer t
        integer lvl
        integer alpha = 255 //caster alpha
        integer alph = 255 //crow alpha
        real cx
        real cy
        real tx
        real ty
        real dur_f
        real alpha_dec = 100. / (CASTING_TIME/XE_ANIMATION_PERIOD) //100%/time
        xefx array fx [MAX_CROW] 
        real array distdone [MAX_CROW] 
        real array distance [MAX_CROW] 
        integer array status [MAX_CROW] 
        real array ang [MAX_CROW] 
        integer crow_count = 0
        boolean finish = false
        boolean start_create = false
        real angle
    
        static method create takes unit c, real cx, real cy, real tx, real ty returns thistype
            local thistype this = thistype.allocate()
            
            set .caster = c
            set .tx = tx
            set .ty = ty
            set .cx = cx
            set .cy = cy
            set .angle=Atan2(ty - cy, tx - cx)
            set .lvl = GetUnitAbilityLevel(c, SPELL_ID)
            set .t = NewTimer()
            call PauseUnit(c, true)
            call SetUnitInvulnerable(c, true)
            
            return this
        endmethod
        
        private method onDestroy takes nothing returns nothing 
            local integer i = 0
            
            call DestroyEffect(AddSpecialEffect(CASTER_ART, .tx, .ty))
            
            loop
            exitwhen i == GetCrowCount(.lvl)
                
                call .fx[i].hiddenDestroy()
                set i = i + 1
                
            endloop
        
            call ReleaseTimer(.t)
            call PauseUnit(.caster, false)
            call SetUnitInvulnerable(.caster, false)
        endmethod
        
        static method onLoop takes nothing returns nothing
            local thistype this = thistype (GetTimerData(GetExpiredTimer()))
            local integer i = 0
            local real a
            local real dis 
            local real x
            local real y
            local real dx
            local real dy
            
            if not .finish then
            
                if .alpha>0 then
                    set .alpha = .alpha - PercentTo255(.alpha_dec)
                    call SetUnitVertexColor(.caster, 255, 255, 255, .alpha)
                else
                    
                    if not .start_create then
                        set .start_create = true
                        call DestroyEffect(AddSpecialEffect(CASTER_ART, .cx, .cy))
                        
                        loop
                        exitwhen i == GetCrowCount(.lvl)
                            set a = GetRandomReal(0, 2 * bj_PI)
                            set dis = GetRandomReal(1, GetAoE(.lvl))
                            set x = cx + dis * Cos (a)
                            set y = cy + dis * Sin (a)
                            set .fx[i] = xefx.create(x, y, .angle)
                            set .fx[i].fxpath = CROW_PATH
                            set .fx[i].scale = CROW_SCALE
                            set .fx[i].z = CROW_H
                            call .fx[i].recolor(RED, GREEN, BLUE, ALPHA)
                            set dx = tx - .fx[i].x
                            set dy = ty - .fx[i].y
                            set .distance[i] = SquareRoot(dx * dx + dy * dy)
                            set .distdone[i] = 0.
                            set .status[i] = 1
                            set i = i +1
                        endloop
                    
                    endif
                
                    if .crow_count != GetCrowCount(.lvl) then
                        
                        set i = 0
                        
                        loop 
                        exitwhen i == GetCrowCount(.lvl)
                            
                            if .status[i] != 0 then
                            
                                
                                if .distdone[i] < .distance[i] then
                                    
                                    set .distdone[i]=.distdone[i] + SPEED
                                    set .ang[i] = Atan2(ty - .fx[i].y, tx - .fx[i].x)
                                    set .fx[i].x = .fx[i].x + SPEED * Cos(.ang[i])
                                    set .fx[i].y = .fx[i].y + SPEED * Sin(.ang[i]) 
                                    call xed.damageAOE(.caster,.fx[i].x, .fx[i].y, GetCollision(.lvl), GetDamage(.lvl) * XE_ANIMATION_PERIOD)
                
                                
                                else
                                    set .status[i] = 0
                                    set .crow_count = .crow_count + 1
                                endif
                            
                            
                            endif
                            
                            set i = i + 1
                        endloop
                        
                    else
                        set .finish = true
                        call SetUnitX(.caster, .tx)
                        call SetUnitY(.caster, .ty)
                    endif
                endif
                
            else
                
                if .alpha <= 255 then
                    set .alpha = .alpha + PercentTo255(.alpha_dec)
                    set .alph = .alph - PercentTo255(.alpha_dec)
                    call SetUnitVertexColor(.caster, 255, 255, 255, .alpha)
                    
                    set i = 0
                    loop
                    exitwhen i == GetCrowCount(.lvl)
                        call .fx[i].recolor(RED, GREEN, BLUE, .alph)
                        set i = i + 1
                    endloop
                    
                else
                    call .destroy()
                endif
                
            endif
            
        endmethod
        
        static method SpellEffect takes nothing returns boolean
            local thistype this
            
            if GetSpellAbilityId() == SPELL_ID then
                set this = thistype.create(GetTriggerUnit(), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), GetSpellTargetX(), GetSpellTargetY())
                call SetTimerData(.t, this)
                call TimerStart(.t, XE_ANIMATION_PERIOD, true, function thistype.onLoop)
            endif
            return false
        endmethod

        static method CheckMinDistance takes nothing returns boolean
            
                local unit u = GetTriggerUnit()
                local real x = GetUnitX(u)
                local real y = GetUnitY(u)
                local real dx = x - GetSpellTargetX()
                local real dy = y - GetSpellTargetY()
            
                if (GetSpellAbilityId() == SPELL_ID and dx * dx + dy * dy<MIN_DIST * MIN_DIST) then
                
                    call SimError(GetOwningPlayer(u), ERROR_MSG)
                    call PauseUnit(u, true)
                    call IssueImmediateOrder(u, "stop")
                    call PauseUnit(u, false)
                
                endif
            
                set u = null
                return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, Condition(function thistype.SpellEffect))
            
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
            call TriggerAddCondition(t, Condition(function thistype.CheckMinDistance))
            
            //init xedamage
            set xed=xedamage.create()
            call DamageOptions(xed)
            call xed.useSpecialEffect(DAMAGE_FX,DAMAGE_ATTCH)
        endmethod
    endstruct
    
endlibrary

Requires:
- TimerUtils by Vexorian
- xe by Vexorian
- BoundSentinel by Vexorian
- SimError by Vexorian


Keywords:
crow, black, dark, sorceress, wizard, mage, undead, death, wing, group, attack, teleport
Contents

Crow Attack v1.00 (Map)

Reviews
07:51, 14th Apr 2010 TriggerHappy: Coding was fine, so was the spell.

Moderator

M

Moderator

07:51, 14th Apr 2010
TriggerHappy:

Coding was fine, so was the spell.
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Well, scorpion182 did mention that this spell was done for a request and never stated that it was an original idea.

I quickly skimmed over the code and couldn't really see anything bad with it, just a few very minor issues popped out. I have yet to test this in-game.


  • You should inline PercentTo255 which should be pretty easy to do.
  • You could have done
    JASS:
    call SetTimerData(.t, this)
    call TimerStart(.t, XE_ANIMATION_PERIOD, true, function thistype.onLoop)
    in the create method.
  • You could try to find an alternative to pausing the caster since pausing has some other unwanted effects.
  • You could make DAMAGE_SFX be played at a different interval than XE_ANIMATION_PERIOD to avoid have sfx spam. (You'll need a constant for the interval and a real in the struct to achieve that.) Oops, I didn't see that the SFX would be played whenever xedamage manages to damage a target. You should probably put call xed.useSpecialEffect(DAMAGE_FX,DAMAGE_ATTCH) in the DamageOptions function though.
I'll edit this post if I test this in-game.
 
Level 22
Joined
Feb 3, 2009
Messages
3,292
Hmm... I requested this spell not HeX.16... I clearly remember that I requested it in your thread on forums "Taking vJASS/Zinc requests" Maybe he requested it too, but I don't think 2 users requested for the exact same spell.

EDIT: Yep, I found it:

Hello, I need this one:

Name: Crow Attack
Levels: 1
Description: Leave blank, I'll put it.
Spell is ground target spell
What spell does?:
(model will be: units\critters\Vulture\Vulture.mdl set red, green, blue colors to 0.
-Crows start flying out of the caster and the caster dissapears. Then these crows start flying into the target location. When they arrive, the crows should start flying into the center of the targeted point, and the caster reappears.

Must be MUI and leakless

+rep and credit if you can make it

@ HeX.16
you should update your jasshelper (replace jasshelper.exe and clijasshelper.exe in the folder called "jasshelper" inside jass newgen pack's folder)

EDIT:

Crow Attack done.

Crow Attack


icon.jpg


Crows start flying out of the caster and the caster dissapears. Then these crows start flying into the target location. When they arrive, the crows should start flying into the center of the targeted point, and the caster reappears.

 
Level 12
Joined
Apr 4, 2010
Messages
862
Barathrum is a cow? isnt it? or a hive member? LOL ( a starting joke ) errr i tried the spell and it turns out the other way .. LOL the crows didnt appear, the caster appeared then later the caster became a bird... is it the thingy problem or my problem??
 
Top