Spell Birds

Viikuna

No Marlo no game.
Reaction score
265
Here is a spell i made for wc3creations spell contest.

It is vJass and MUI. Requires Cohadars TT, Vexorians CheckPathability and SafeX/Y -functions. ( You find all these from testmap. )

code:
JASS:
// Bird Strike by Viikuna
// This spell is made for wc3Creations Spell Contest
// Theme: Missile, Light.   ( and Birds ) 


scope Birds initializer init
// this uses SomeNeatFunctions, TT ( Credits go to Cohadar )

globals
//==================================================================================
//==================================================================================
    // Ability is based on Channel
    private constant integer ABILITY_ID = 'A000'
    // AoE for Knockback
    private constant real AOE = 300.0
    // AoE fot missile collinsion
    private constant real MISSILE_AOE = 50.0 
    // Damage is calculated like this: DAMAGE_LEVEL*AbilityLevel+DAMAGE_BASE
    private constant real DAMAGE_BASE = 0.0
    private constant real DAMAGE_LEVEL = 50.0
    // All the Birds
    private constant integer MISSILE_ID0 = 'h000'
    private constant integer MISSILE_ID1 = 'h001'
    private constant integer MISSILE_ID2 = 'h002'
    private constant integer MISSILE_ID3 = 'h003'
    private constant integer MISSILE_ID4 = 'h004'
    // Damage types
    private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
    private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
    private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
    // When unit collides with some object, the damage is calculated like this:
    // Units Sliding Velocity * DAMAGE_FACTOR
    private constant real DAMAGE_FACTOR = 2.5
    // The bigger the number, the bigger the knockback
    private constant real KNOCKBACK_FACTOR = 0.01
    // missiles Maximum travelling range
    private constant real MAX_RANGE = 1500.0
    // Missiles move speed
    private constant real STARTING_VELOCITY = 10.0
    private constant real ACCELERATION = 0.5 / 2
    // How fast sliding units stop
    private constant real FRICTION = 2.5 / 2
    // Maximum targets knocked per Missile
    private constant integer MAX_TARGETS = 10
 //==================================================================================   
 //==================================================================================   
    private integer array MISSILE_ID
    private filterfunc F
    private filterfunc True
    private group TempG = CreateGroup()
    private unit TempU
endglobals

private struct Data2
    unit u
    unit knocker
    real sin
    real cos
    real x
    effect e
    real y
    real velocity
    boolean impact = false
    
    method move takes nothing returns nothing
        set this.velocity = this.velocity - FRICTION
        set this.x = SafeX(this.x + this.velocity * this.cos)
        set this.y = SafeY(this.y + this.velocity * this.sin)
        set this.velocity = this.velocity - FRICTION
        if CheckPathability(this.x,this.y) == true then
            call SetUnitX(this.u,this.x)
            call SetUnitY(this.u,this.y)
        else
            set this.impact = true
        endif
    endmethod
    
    method onDestroy takes nothing returns nothing
        call PauseUnit(this.u,false)
        call DestroyEffect(this.e)
        if this.impact == true then
            call UnitDamageTarget(this.knocker,this.u,this.velocity*DAMAGE_FACTOR,false,false,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
            call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl",this.x,this.y))
        endif
    endmethod
endstruct

private function Loop2 takes nothing returns boolean
    local Data2 D = TT_GetData()
    if D.impact == true or D.velocity <= 0 then
        call D.destroy()
        return true
    endif
    call D.move()
    return false
endfunction

private struct Data
    unit array bird[10]
    unit shooter
    real velocity
    real range = 0.0
    real x
    real y
    real array birdX[10]
    real array birdY[10]
    real sin
    real cos
    real array birdCos[10]
    real array birdSin[10]
    boolean spreaded = false
    boolean end = false
    
    
    method KnockThem takes nothing returns nothing
        local unit u
        local real x
        local real y
        local real dx
        local real dy
        local real a
        local Data2 D
        local integer i = 0
        set TempU = this.shooter
        call GroupEnumUnitsInRange(TempG,this.x,this.y,AOE,F)
        loop
            set u = FirstOfGroup(TempG)
            set i = i + 1
            exitwhen u == null or i == MAX_TARGETS
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            set dx = x - this.x
            set dy = y - this.y
            set D = Data2.create()
            set D.velocity = (AOE - (SquareRoot(dx * dx + dy * dy)/2) ) * ( this.velocity / 2 ) * KNOCKBACK_FACTOR
            set a = Atan2(dy,dx)
            set D.sin = Sin(a)
            set D.cos = Cos(a)
            set D.x = x
            set D.y = y
            set D.u = u
            set D.e = AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\FaerieDragonInvis\\FaerieDragon_Invis.mdl",D.u,"chest")
            set D.knocker = this.shooter
            call PauseUnit(D.u,true)
            call D.move()
            call TT_Start(function Loop2,D)
            call UnitDamageTarget(this.shooter,u,DAMAGE_LEVEL*GetUnitAbilityLevel(this.shooter,ABILITY_ID)+DAMAGE_BASE,false,false,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
            call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\ProcMissile\\ProcMissile.mdl",x,y))
            call GroupRemoveUnit(TempG,u)
        endloop
        call GroupClear(TempG)
    endmethod
    
    method move takes nothing returns nothing
        local unit u
        local real a
        local real dx
        local real dy
        local real d
        local real r
        local integer i = 0
        local real cos = this.velocity * this.cos
        local real sin = this.velocity * this.sin
        set this.x = SafeX( this.x + cos)
        set this.y = SafeY( this.y + sin)
        set TempU = this.shooter
        call GroupEnumUnitsInRange(TempG,this.x,this.y,MISSILE_AOE,F)
        set u = FirstOfGroup(TempG)
        if this.range >= MAX_RANGE or u != null or CheckPathability(this.x,this.y) == false then
            call GroupClear(TempG)
            set this.spreaded = true
            set r = bj_PI / 5
            set a = 0
            set this.range = 0.0
            call this.KnockThem()
            loop
                exitwhen i > 9
                set a = a + r
                call SetUnitFacing(this.bird<i>,a*bj_RADTODEG)
                set this.birdCos<i> = Cos(a)
                set this.birdSin<i> = Sin(a)
                set i = i + 1
            endloop
            return
        endif
        loop
            exitwhen i &gt; 9
            set dx = this.x - this.birdX<i>
            set dy = this.y - this.birdY<i>
            set d = SquareRoot(dx * dx + dy * dy)
            if d &gt; 150.0 then
                set a = Atan2(dy,dx)
                set this.birdSin<i> = Sin(a)
                set this.birdCos<i> = Cos(a)
            else
                if d &lt; 10 then
                    set this.birdSin<i> = GetRandomReal(0.0,1.0)
                    set this.birdCos<i> = GetRandomReal(0.0,1.0)
                endif
            endif
            set this.birdX<i> = SafeX(this.birdX<i> + cos)
            set this.birdY<i> = SafeY(this.birdY<i> + sin)
            set this.birdX<i> = SafeX(this.birdX<i> + 5.0 * this.birdCos<i>)
            set this.birdY<i> = SafeY(this.birdY<i> + 5.0 * this.birdSin<i>)
            call SetUnitX(this.bird<i>,this.birdX<i>)
            call SetUnitY(this.bird<i>,this.birdY<i>)
            set i = i + 1
        endloop
        set this.velocity = this.velocity + ACCELERATION
        set this.range = this.range + this.velocity
        set this.velocity = this.velocity + ACCELERATION
        set u = null
    endmethod
    
    method spread takes nothing returns nothing
        local integer i = 0
        if this.range &gt; AOE then
            set this.end = true
            return
        endif
        loop
            exitwhen i &gt; 9
            set this.birdX<i> = SafeX(this.birdX<i> + this.velocity * this.birdCos<i>)
            set this.birdY<i> = SafeY(this.birdY<i> + this.velocity * this.birdSin<i>)
            call SetUnitX(this.bird<i>,this.birdX<i>)
            call SetUnitY(this.bird<i>,this.birdY<i>)
            set i = i + 1
        endloop
        set this.velocity = this.velocity + ACCELERATION
        set this.range = this.range + this.velocity
        set this.velocity = this.velocity + ACCELERATION
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i &gt; 9
            call KillUnit(this.bird<i>)
            set i = i + 1
        endloop
    endmethod

endstruct

private function ItIsTrue takes nothing returns boolean
   return true
endfunction

private function filter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(TempU)) == true and GetWidgetLife(GetFilterUnit()) &gt; 0.0451 and GetUnitFlyHeight(GetFilterUnit()) == 0 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false
endfunction

private function Loop takes nothing returns boolean
    local Data D = TT_GetData()
    if D.end == true then
        call D.destroy()
        return true
    endif
    if D.spreaded == true then
        call D.spread()
    else
        call D.move()
    endif
    return false
endfunction

private function B takes nothing returns nothing
     local Data D = Data.create()
     local integer i = 0
     local unit u = GetTriggerUnit()
     local location loc = GetSpellTargetLoc()
     local real x = GetUnitX(u)
     local real y = GetUnitY(u)
     local real x2 = GetLocationX(loc)
     local real y2 = GetLocationY(loc)
     local real dx = x2 - x
     local real dy = y2 - y
     local real angle = Atan2(dy, dx)
     set D.sin = Sin(angle)
     set D.cos = Cos(angle)
     set D.x = x
     set D.y = y
     set D.shooter = u
     set D.velocity = STARTING_VELOCITY
     loop
         exitwhen i &gt; 9
         set D.bird<i> = CreateUnit(Player(13),MISSILE_ID[GetRandomInt(0,4)],D.x,D.y,angle*bj_RADTODEG)
         call PauseUnit(D.bird<i>,true)
         set D.birdX<i> = x
         set D.birdY<i> = y
         set D.birdCos<i> = GetRandomReal(0.0,1.0)
         set D.birdSin<i> = GetRandomReal(0.0,1.0)
         set i = i + 1
     endloop
     call TT_Start(function Loop, D)
     call RemoveLocation(loc)
     set loc = null
     set u = null
endfunction


private function A takes nothing returns boolean
    return GetSpellAbilityId() == ABILITY_ID
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    set MISSILE_ID[0] = MISSILE_ID0
    set MISSILE_ID[1] = MISSILE_ID1
    set MISSILE_ID[2] = MISSILE_ID2
    set MISSILE_ID[3] = MISSILE_ID3
    set MISSILE_ID[4] = MISSILE_ID4
    set True = Filter(function ItIsTrue)
    loop
        call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,True)
        set i = i + 1
        exitwhen i == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t,Condition(function A))
    call TriggerAddAction(t,function B)
    set F = Filter(function filter)
endfunction

endscope</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>



Here is the testmap:
View attachment All the Birds.w3x
Download it and give me some comments.

Spell description would be something like this:

It sends few angry Birds flying towards the target location. When Birds collide with something or meet the maximum range, they spread out and deal damage to enemies and knock them them away.

EDIT. some shots: Bird1.jpg Birds2.jpg
 

NaPzt3R

You can change this now in User CP.
Reaction score
38
What about telling us what it does.. And add some screenshots? :D
 

quraji

zap
Reaction score
144
Looks neat. Wonder why it's a target spell? Doesn't seem to affect the spell at all casting at different locations.

I see you're doing quite a bit of moving calculations, which doesn't make sense to me as the birds only exist for a flash and the movement distance is so small (for both birds and knockback units). Seems a waste to me when no one will notice the difference between this and a basic static speed slide.

I really like the look of the birds though, going to have to see what models they are :)
 

Viikuna

No Marlo no game.
Reaction score
265
Actyally those Birds knockback a bit more if they get some time to accelerate.

BTW Check those pics too :)

EDIT, They are those famous bird projectiles. I have allways wondered how many differend color birds there is in wc3, I hope I found them all. ( I think I did )
 

NaPzt3R

You can change this now in User CP.
Reaction score
38
Looks pretty neat from the look of the screenshots.
Going to download the map now.

EDIT:
This is awesome.
Is it okay if I use it in my map? I might edit it a bit.
 

Viikuna

No Marlo no game.
Reaction score
265
No problem, you are free to use it. ( That is actually the reason why I posted it in first place. )
 

Faust

You can change this now in User CP.
Reaction score
123
An excellent idea, I will use some "mutated" form it some time in my map ^^
 

Jedimindtrixxx

┻━┻ ︵ ¯\(ツ)/¯ ︵ ┻━┻
Reaction score
168
wow i tried it out and its amazing. they go faster over time and they push out more the more they travel!
one thing though, at times they fly through the enemy and dont hit them.

also, how would i make them speed up faster?
i see this:
JASS:
    // Missiles move speed
    private constant real STARTING_VELOCITY = 10.0
    private constant real ACCELERATION = 0.5 / 2

but to make it faster do i increase the .5 or decrease, or do i increase/decrease the /2 ?
 

Viikuna

No Marlo no game.
Reaction score
265
Actyally, I dont really remember why it is 0.5 / 2, and not 0.25, since they are the same thing. ( weird )

Anyways, it incereases missiles speed by 0.25 per every timer tick. So after first tick , missile speed is 10 + 0.25 ( = 10.25). After second tick it will be 10.25 + 0.25 ( = 10.5 ) and etc.

To make accelerate faster just replace that 0.5 / 2 ( = 0.25 ) with 0.26 or 0.27 or some other number, which is greater than 0.25.

at times they fly through the enemy and dont hit them.
This is because birds doest trigger collinsion, but the center of that bird swarm does. You can incerease MISSILE_AOE, it tells from how big are it will pick enemy units and trigger collinsion.
 

_whelp

New Member
Reaction score
54
The description sounds kinda funny cause angry birds give me the thought of mad birds pooping.
JASS:
//lolololololol
 

Viikuna

No Marlo no game.
Reaction score
265
Do I need to do something else than wait to get spells aproved?
Waiting is no problem, but if there is something else, I would like to know.
 

gameman

It's been a long, long time.
Reaction score
95
Wow! This is awesome. I'll be wondering when you will be doing requests.
 

Viikuna

No Marlo no game.
Reaction score
265
Well, If you have something to request PM me and I see what I can do. I can make spells, but dont request any big systems or things that take too much coding :D .
 

Viikuna

No Marlo no game.
Reaction score
265
Omg, since this is now aproved, I think I need to recode it, so it is at the date of best quality vJass coding.
 

Romek

Super Moderator
Reaction score
963
> Omg, since this is now aproved, I think I need to recode it, so it is at the date of best quality vJass coding.
Go ahead. Though it's approval-worthy as it is.

That somewhat reminds me of my Panda Roll spell.
It's approved, though I'm planning on recoding it so it meets my standards.
 
Reaction score
91
Awesome idea, pretty original and quite interesting! I guess I can find some use of this in my map if you recode it.
Just a suggestion - wouldn't it be better if the birds landed/exploded/whatever it's called at the position where you casted the spell? Right now it has a fixed distance and it could be hard to target someone in a fast paced game where every unit is moving and trying to dodge some damage.
 

Viikuna

No Marlo no game.
Reaction score
265
Good idea, fixxed distance really kinda sucks. I will get back to this later, gotta make some pizza now..
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      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