• 🏆 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!

Need Help with spells

Status
Not open for further replies.
Level 6
Joined
Dec 13, 2007
Messages
213
I have a great idea for 5 mega ultimate bosses of almighty, unyielding Doom. but i have one problem. i want really cool spells but i have no idea how to make them. im not new to world editor and have made simple custom abilities for a few months now. but i have no clue how to make the following for the following Bosses, and beleive me ive tried everything:confused: well...almost everything. i only describe the abilities so that you can judge if they are not possible to make

Grade F Kill, Goblin tank: hes got more than this but i can handel those spells
Ability 1.) A warstomp that makes 3 or so peopel fly back about 10 feet when hit. kind of like a jump effect. which i have no idea how to make and no ida where to begin. or even how to begin for that matter

Grade D Kill, Big Water Elemental:
Ability 2.) A whirlpool will appear around the caster, catching anyone inside an area to be pulled in towards the boss for some damage.

Ability 3.) A wave of water comes forth and who so ever it hits is blasted back in the air to land far away from the caster. again, kind of like a jump effect.

Ability 4.) The Boss submerges in water, he moves or maybe teleports, either way when he moves i need a wave effect to appear from his origonal position and move to his new one.

Grade C Kill: havent put much thought into him yet...

Grade B Kill, Blood Mage:
Ability 5.) A Blast wave of fiery death is thrown out in all directions. or, abunch of fireballs balsted out in all directions that hurts what ever they hit.

Ability 6.) Infernal stones rain down continuosly in random areas hurting anyone they hit.

Ability 7.) a volcano spell with out the volcano, i can't figure out how to make it go away.

Grade A Kill, Giant Blood elf Swordsman: lots of lightning spells

Ability 8.) Kinda of like ability 6 but instead of rocks, i want lightning.

Ability 9.) this one is perhaps hardest to make and hardest to Describe. i want my boss to fire 2 lightning bolts at the same time, they go off in opposite directions, then BAM it happens again but in a different position 45 degrees off the first one, then again. all in a circular diameter around the caster. im sry but thats the best i can describe it :wscrolleyes:

I hope someone can help. this isn't easy but i can't figure this stuff out. is there a way i can do this with triggers or do i HAVE to use JASS because computer scripting just rots my mind. but if i must i will learn because i realy want this map to come to fruition. Please help in anyway. be it tips, tutorials, directions, or just by saying if its possible to make this, and if so what tools i need to make them. thanks for any help
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
Why don't you start with simpler things instead of going such complicated things you cannot handle? I'm sorry, but I just can't understand you guys. If you don't know how to code well, just start with simple things and you'll learn eventually.

Why do you want to make something if you don't have any idea how to make it? Where does that desire come from?? Why don't you just learn it on your own instead of bugging people to do it for you? You would feel much better, believe me.

I hope someone can help. this isn't easy but i can't figure this stuff out. is there a way i can do this with triggers or do i HAVE to use JASS cuz computer scripting just rots my mind. but if i must i will learn cuz i realy want this map to come to fruition. plz help in anyway. be it: tips, tutorials, directions, or just by saying if its possible to make this, and if so what tools i need to make them. thanks for any help

This would be much nicer if you got rid of cuzs plzs, people will have a much higher opinion of you if you type clean and literate posts.

Btw, there are some nice tuts here, here and here.
 
Level 6
Joined
Dec 13, 2007
Messages
213
like i said in my post Silvenon, ive made simple spells, now i want to go into the more complicated kick ass spells. and the desire comes from the desire to make something amazing. and i bug you guys to help me because...well am i in the world editor help forum or not. and after making simple spells, which i've been doing for quite a few months, the spells i now think of cant be made through object editor. and learn computer coding on my own? im not super man, i cant even do that with flash mx
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
So you want to say that you don't know triggering? Why didn't you just say so??

Check those tuts I linked you to, I'm not learning you what triggers are, that are tutorials for :)

P.S.

Simple spells --> non-triggered spells
Complicated spells --> triggered spells

That is what you meant (probably).
 
Level 11
Joined
Feb 22, 2006
Messages
752
Note, all of the abilities below require Vexorian's Caster System and vJass (CasterSystem 14.0 and newer requires vJass anyways)

Since wc3campaigns.net is down right now, I've attached CS 14.5 and you can get vJass through Jass NewGen here: http://www.hiveworkshop.com/forums/profile.php?do=editattachments

Firstly, copy and paste these functions into the custom script section of your map:

JASS:
function GetAngleBetweenPoints takes real x1, real y1, real x2, real y2 returns real
    return bj_RADTODEG * Atan2(y2 - y1 , x2 - x1)
endfunction

function PolarProjectionX takes real x, real dist, real angle returns real
    return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
 
function PolarProjectionY takes real y, real dist, real angle returns real
    return y + dist * Sin(angle * bj_DEGTORAD)
endfunction

Now, I've made scripts for two of the abilities, I might make scripts for other ones but I do have other things to do so...

These scripts are untested btw.

  1. Ability 2: Make a dummy spell based off the Channel ability. Make the spell instant-cast. Set follow through time to how long you want your whirlpool to last. Make sure under the Options data field, "Visible" is checked. Tweak the other fields to whatever you want.

    Create a trigger in your map called "Whirlpool" (without the quotes), go to Edit -> Convert to Custom Script, delete everything in that trigger, and copy the code below into the trigger:

    JASS:
    function InitTrig_Whirlpool takes nothing returns nothing
        call OnAbilityEffect('A000' , "Whirlpool_Actions") //Change the ability raw code ('A000') to match the raw code of the ability in your map
    endfunction
    
    //===========================================================================
    
    constant function Whirlpool_Timeout takes nothing returns real
        return 0.04 //How often the timer that executes the move functions expires (lower value = better-looking graphics but more lag)
    endfunction
    
    constant function Whirlpool_MainEffect takes nothing returns string
        return "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl" //Model path for the whirlpool effect that appears at the caster's feet
    endfunction
    
    constant function Whirlpool_AttachEffect takes nothing returns string
        return "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayDamage.mdl" //Model path for any attached effects that appear on units damaged by the whirlpool
    endfunction
    
    constant function Whirlpool_AttachPoint takes nothing returns string
        return "overhead" //Attachment point for the attached effects
    endfunction
    
    constant function Whirlpool_Radius takes integer level returns real
        return 200 + 100 * level //Maximum Radius at which units begin to be pulled into the whirlpool
    endfunction
    
    constant function Whirlpool_Damage takes integer level returns real
        return 20 * level //Damage done by whirlpool per duration
    endfunction
    
    constant function Whirlpool_DamageDuration takes integer level returns real
        return 1.00 //How often the whirlpool damages units
    endfunction
    
    constant function Whirlpool_Duration takes integer level returns real
        return 20.00 //How long the whirlpool lasts
    endfunction
    
    constant function Whirlpool_DamageRadius takes integer level returns real
        return 100.00 //AoE radius of the whirlpool's damage effect
    endfunction
    
    //===========================================================================
    
    struct whirlpooldata
        timer t = CreateTimer()
        unit caster
        real x1
        real y1
        group g = CreateGroup()
        integer level
        method onDestroy takes nothing returns nothing
            if ( .t != null ) then
                call CleanAttachedVars( .t )
                call DestroyTimer( .t )
            endif
            if ( .g != null ) then
                call DestroyGroup( .g )
            endif
        endmethod
    endstruct
    
    function Whirlpool_Attract takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local whirlpooldata temp = GetAttachedInt(t , "temp")
        local unit u
        local real x2
        local real y2
        local real angle
        local real distance
        call GroupEnumUnitsInRange( temp.g, temp.x1, temp.y1, WhirlPool_Radius( temp.level ), null )
        loop
            set u = FirstOfGroup( temp.g )
            exitwhen ( u == null )
            if ( IsUnitEnemy( u, GetOwningPlayer( temp.caster ) ) ) then
                 set x2 = GetUnitX( u )
                 set y2 = GetUnitY( u )
                 set angle = GetAngleBetweenPoints( x2, y2, temp.x1, temp.y1 )
                 set distance = SquareRoot( ( x2 - temp.x1 ) * ( x2 - temp.x1 ) + ( y2 - temp.y1 ) * ( y2 - temp.y1 ) )
                 call SetUnitPosition( u, PolarProjectionX( x2, distance / 50, angle ), PolarProjectionY( y2, distance / 50, angle ) )
            endif
            call GroupRemoveUnit( temp.g, u )
        endloop
        set t = null
    endfunction
    
    function Whirlpool_Actions takes nothing returns nothing
        local whirlpooldata temp = whirlpooldata.create()
        local unit u
        local location casterloc
        local integer dopt= DamageTypes( ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
        set temp.caster = GetTriggerUnit()
        set temp.x1 = GetUnitX( temp.caster )
        set temp.y1 = GetUnitY( temp.caster )
        set temp.level = GetUnitAbilityLevel( caster, 'A000' ) //Change the ability raw code ('A000') to match the raw code of the ability in your map
        set casterloc = GetUnitLoc( temp.caster )
        call AddAreaDamagerForUnitLoc( temp.caster, Whirlpool_MainEffect(), Whirlpool_AttachEffect(), Whirlpool_AttachPoint(), casterloc, Whirlpool_Damage( temp.level ), Whirlpool_DamageDuration( temp.level ), Whirlpool_Duration( temp.level ) + 0.1 , Whirlpool_DamageRadius( temp.level ), false, dopt )
        call TimerStart( temp.t, Whirlpool_Timeout(), true, function Whirlpool_Attract )
        call AttachInt( temp.t, "temp", temp)
        call RemoveLocation( casterloc )
        set casterloc = null
        call TriggerSleepAction( Whirlpool_Duration( temp.level ) )
        call temp.destroy()
    endfunction


    Follow the instructions in the comments within the code to tweak the spell to your specifications (you should only need to change the values within the constant functions near the top of the spell and the ability raw data code of your dummy Channel spell in the two lines specified)
  2. Ability 3: Make a spell based off of any other spell that allows you to target units or terrain (Shockwave, Carrion Swarm, Breath of Fire, etc.) - DON'T USE BLINK - and get rid of all special effects created by that ability when it's cast. Everything else you can change to your own liking.

    Create a trigger in your map called "Wave" (without the quotes), go to Edit -> Convert to Custom Script, delete everything in that trigger, and copy the code below into the trigger:

    JASS:
    function InitTrig_Wave takes nothing returns nothing
        call OnAbilityEffect('A000' , "Wave_Actions") //Change the ability raw code ('A000') to match the raw code of the ability in your map
    endfunction
    
    //===========================================================================
    
    constant function Wave_CrowAbilId takes nothing returns integer
        return 'A001' //Set this to the Crow Form ability id, or the ability id of a custom ability based on Crow Form
    endfunction
    
    constant function Wave_Timeout takes nothing returns real
        return 0.04 //How often the timer that executes the move functions expires (lower value = better-looking graphics but more lag)
    endfunction
    
    constant function Wave_MissileModel takes nothing returns string
        return "" //Model path for the wave missile
    endfunction
    
    constant function Wave_MissileSpeed takes integer level returns real
        return 522 //How fast the wave travels (in wc3 speed units)
    endfunction
    
    constant function Wave_MissileCollision takes integer level returns real
        return 200 + 100 * level //Collision size of the wave (how close units have to get before getting hit by wave)
    endfunction
    
    constant function Wave_MissileDistance takes integer level returns real
        return 500 + 100 * level //Maximum distance the wave travels
    endfunction
    
    constant function Wave_MissileHeight takes nothing returns real
        return 50.00 //Height at which wave missile travels
    endfunction
    
    constant function Wave_Damage takes integer level returns real
        return 100 * level //Damage done to enemy units upon collision with wave
    endfunction
    
    constant function Wave_MoveIncrement takes integer level returns real
        return 10.00 * level //How far the affected units fly backward each time the timer expires
    endfunction
    
    constant function Wave_MaxFlyHeight takes integer level returns real
        return 400.00 //How far up the units fly (the height of the tip of the parabola)
    endfunction
    
    constant function Wave_FlyUpDuration takes integer level returns real
        return 0.30 //How long the units take to reach the maximum fly height
    endfunction
    
    constant function Wave_FlyDownDuration takes integer level returns real
        return 0.20 //How long the units take to fall back down to the ground
    endfunction
    
    //===========================================================================
    
    struct wavedata
        unit caster
        unit missile
        real x1
        real y1
        real angle
        integer level
        method onDestroy takes nothing returns nothing
            if ( .missile != null ) then
                call CleanAttachedVars( .missile )
            endif
        endmethod
    endstruct
    
    struct waveknockbackdata
        unit caster
        unit target
        real angle
        integer level
        boolean destroyplease
    endstruct
    
    globals
        timer wavetimer = CreateTimer()
        waveknockbackdata array waveknockbackarray
        integer waveknockbackarraytotal = 0
    endglobals 
    
    function Wave_Knockback takes nothing returns nothing
        local integer counter = 0
        local real x2
        local real y2
        local waveknockbackdata temp
        loop
            exitwhen ( counter > waveknockbackarraytotal )
            set temp = waveknockbackarray[counter]
            if ( temp.destroyplease ) then
                set waveknockbackarray[counter] = waveknockbackarray[waveknockbackarraytotal - 1]
                set waveknockbackarraytotal = waveknockbackarraytotal - 1
                call temp.destroy()
                set counter = counter - 1
            else
                set x2 = GetUnitX( waveknockbackarray[counter].target )
                set y2 = GetUnitY( waveknockbackarray[counter].target )
                call SetUnitPosition( waveknockbackarray[counter].target , PolarProjectionX( x2 , Wave_MoveIncrement( waveknockbackarray[counter].level ), waveknockbackarray[counter].angle ) , PolarProjectionY( y2 , Wave_MoveIncrement( waveknockbackarray[counter].level ), waveknockbackarray[counter].angle ) )
            endif
            set counter = counter + 1
        endloop
        if ( waveknockbackarrayttoal == 0 ) then
            call PauseTimer( wavetimer )
        endif
    endfunction
    
    function Wave_AddUnit takes integer index, unit caster, unit target, real angle, integer level returns nothing
        local waveknockbackdata temp = waveknockbackdata.create()
        temp.caster = caster
        temp.target = u
        temp.angle = angle
        temp.level = level
        set waveknockbackarray[index] = temp
        set waveknockbackarraytotal = waveknockbackarraytotal + 1
        call PauseUnit( target, true )
        call UnitAddAbility( target, Wave_CrowAbilId() )
        call SetUnitFlyHeight( target, Wave_MaxFlyHeight( level ), Wave_MaxFlyHeight( level ) / Wave_FlyUpDuration( level ) )
        call TriggerSleepAction( Wave_FlyUpDuration( level ) )
        call SetUnitFlyHeight( target, 0.00, Wave_MaxFlyHeight( level ) / Wave_FlyDownDuration( level ) )
        call TriggerSleepAction( Wave_FlyDownDuration( level ) )
        set temp.destroyplease = true
        call UnitRemoveAbility( target, Wave_CrowAbilId() )
        call PauseUnit( target, false )
    endfunction 
    
    function Wave_Impact takes nothing returns nothing
        local unit missile = GetTriggerCollisionMissile()
        local unit u = GetTriggerUnit()
        local wavedata temp = GetAttachedInt( missile, "temp" )
        if ( GetTriggerUnit() != null ) then
            if ( IsUnitEnemy( u, GetOwningPlayer( temp.caster ) ) ) then
                if ( waveknockbackarraytotal == 0 ) then
                    call TimerStart( wavetimer, Wave_Timeout(), true, function Wave_Knockback )
                endif
                call UnitDamageTarget( temp.caster, u, Wave_Damage( temp.level ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
                call Wave_AddUnit( waveknockbackarraytotal, temp.caster, u, temp.angle, temp.level )
            endif
        else
            call temp.destroy()
        endif
        set missile = null
        set u = null
    endfunction
    
    function Wave_Actions takes nothing returns nothing
        local wavedata temp = wavedata.create()
        local unit u
        local location casterloc
        local location targetloc = GetSpellTargetLoc()
        set temp.caster = GetTriggerUnit()
        set temp.x1 = GetUnitX( temp.caster )
        set temp.y1 = GetUnitY( temp.caster )
        set temp.angle = GetAngleBetweenPoints( temp.x1 , temp.y1 , GetLocationX( targetloc ) , GetLocationY( targetloc ) )
        set temp.level = GetUnitAbilityLevel( caster, 'A000' ) //Change the ability raw code ('A000') to match the raw code of the ability in your map
        set casterloc = GetUnitLoc( temp.caster )
        set temp.missile = CollisionMissile_CreateLoc( Wave_MissileModel(), casterloc, temp.angle, Wave_MissileSpeed( temp.level ), 0.00, Wave_MissileDistance( temp.level ), Wave_MissileHeight(), true, Wave_MissileCollision( temp.level ), function Wave_Impact )
        call AttachInt( temp.missile, "temp", temp)
        call RemoveLocation( casterloc )
        call RemoveLocation( targetloc )
        set casterloc = null
        set targetloc = null
    endfunction


    Follow the instructions in the comments within the code to tweak the spell to your specifications (you should only need to change the values within the constant functions near the top of the spell and the ability raw data code of your dummy spell in the two lines specified)
 

Attachments

  • CasterSystem14.5.w3x
    294.7 KB · Views: 38
Last edited:
Level 6
Joined
Dec 13, 2007
Messages
213
Thanks for the help aznricepuff you are the best :thumbs_up:

And actually siveron, i do know triggers...just not Jass or scripting, intruth i dont know how people learn it, tutorials or what?

In my map i uploaded to the site, the last boss has a move thats all triggers, simple triggers. I could describe it but i wanna get my map started, thanks for the links too, ive found it helpful as well.

thanks again aznricepuff
 
Last edited:
Level 11
Joined
Feb 22, 2006
Messages
752
Ok, finally made ability number 1...don't know what took me so long since its basically the same as ability 3...


EDIT: Probably should mention you need a dummy instant-cast ability (like warstomp or thunderclap for example). Set damage to 0. Make whatever special effects you want.

JASS:
function InitTrig_War_Stomp takes nothing returns nothing
    call OnAbilityEffect( 'A000' , "War_Stomp_Actions" ) //Change the ability raw code ('A000') to match the raw code of the ability in your map
endfunction

//===========================================================================

constant function Warstomp_CrowAbilId takes nothing returns integer
    return 'A001' //Set this to the Crow Form ability id, or the ability id of a custom ability based on Crow Form
endfunction

constant function WarStomp_Timeout takes nothing returns real
    return 0.04 //How often the timer that executes the move functions expires (lower value = better-looking graphics but more lag)
endfunction

constant function WarStomp_MoveIncrement takes integer level returns real
    return 10.00 * level //How far the affected units fly backward each time the timer expires
endfunction

constant function WarStomp_MaxFlyHeight takes integer level returns real
    return 200.00 //How far up the units fly (the height of the tip of the parabola)
endfunction

constant function WarStomp_FlyUpDuration takes integer level returns real
    return 0.30 //How long the units take to reach the maximum fly height
endfunction

constant function WarStomp_FlyDownDuration takes integer level returns real
    return 0.20 //How long the units take to fall back down to the ground
endfunction

constant function WarStomp_Radius takes integer level returns real
    return 200.00 + 100 * level //AoE radius of the spell
endfunction

//===========================================================================

struct warstompdata
    timer t = CreateTimer()
    group g = CreateGroup()
    unit caster
    real x1
    real y1
    integer level
    method onDestroy takes nothing returns nothing
        if ( .t != null ) then
            call CleanAttachedVars( .t )
            call DestroyTimer( .t )
        endif
    endmethod
endstruct

function War_Stomp_Knockback takes nothing returns nothing
    local timer t= GetExpiredTimer()
    local warstompdata temp = GetAttachedInt( t , "temp" )
    local group g = CreateGroup()
    local unit u = FirstOfGroup( temp.g )
    local real x2= GetUnitX( u )
    local real y2= GetUnitY( u )
    local real angle= GetAngleBetweenPoints( temp.x1 , temp.y1 , x2 , y2 )
    loop
        set u = FirstOfGroup( temp.g )
        set x2= GetUnitX( u )
        set y2= GetUnitY( u )
        set angle= GetAngleBetweenPoints( temp.x1 , temp.y1 , x2 , y2 )
        exitwhen ( u == null )
        call SetUnitPosition( u , PolarProjectionX( x2 , Warstomp_MoveIncrement( temp.level ), angle ) , PolarProjectionY( y2 , Warstomp_MoveIncrement( temp.level ), angle ) )
        call GroupAddUnit( g, u )
        call GroupRemoveUnit( temp.g, u )
    endloop
    call DestroyGroup( temp.g )
    set temp.g = g
    set t = null
    set g = null
endfunction

function War_Stomp_Actions takes nothing returns nothing
    local warstompdata temp = warstompdata.create()
    local group g = CreateGroup()
    local unit u
    local player p
    set temp.caster = GetTriggerUnit()
    set temp.x1 = GetUnitX( temp.caster )
    set temp.y1 = GetUnitY( temp.caster )
    set temp.level = GetUnitAbilityLevel( temp.caster, 'A000' ) //Change the ability raw code ('A000') to match the raw code of the ability in your map
    set p = GetOwningPlayer( temp.caster )
    call GroupEnumUnitsInRange( g, temp.x1, temp.y1, WarStomp_Radius( level ), null )
    loop
        set u = FirstOfGroup( g )
        exitwhen ( u == null )
        if ( IsUnitEnemy( u, temp.p ) ) then
            call GroupAddUnit( temp.g, u )
            call PauseUnit( u, true )
            call UnitAddAbility( u, WarStomp_CrowAbilId() )
            call SetUnitFlyHeight( u, WarStomp_MaxFlyHeight( temp.level ), WarStomp_MaxFlyHeight( temp.level ) / Warstomp_FlyUpDuration( temp.level ) )
        endif
        call GroupRemoveUnit( g, u )
    endloop
    call TimerStart( temp.t , WarStomp_Timeout() , true , function War_Stomp_Knockback )
    call AttachInt( t , "temp" , temp )
    call TriggerSleepAction( WarStomp_FlyUpDuration( temp.level ) )
    call GroupAddGroup( temp.g, g )
    loop
        set u = FirstOfGroup( g )
        exitwhen ( u == null )
        call SetUnitFlyHeight( u, 0.00, WarStomp_MaxFlyHeight( temp.level ) / WarStomp_FlyDownDuration( temp.level ) )
        call GroupRemoveUnit( g, u )
    endloop
    call TriggerSleepAction( WarStomp_FlyDownDuration( temp.level ) )
    call PauseTimer( temp.t )
    loop
        set u = FirstOfGroup( temp.g )
        exitwhen ( u == null )
        call UnitRemoveAbility( u, WarStomp_CrowAbilId() )
        call PauseUnit( u, false )
        call GroupRemoveUnit( temp.g, u )
    endloop
    call temp.destroy()
    call DestroyGroup( g )
    set g = null
    set p = null
endfunction



The code has been tested so if it doesn't work, it's prolly cause i screwed something up while copy-pasting.

P.S. I know I can script abilities 5 and 9. I can probably also do 6, 7, and 8 but not completely sure about those ones. Look for them in the next few days.
 
Level 11
Joined
Feb 22, 2006
Messages
752
More spells, yay!

Ability 5:

For this one you need an instant-cast ability. Channel with casting type set to instant works perfectly, just make sure you set to visible, fix the follow through time, which is how long your unit stays immobilized after casting the spell (for some reason the default is 180 seconds), and make sure the baseorder id and the orderstring do not conflict with any other spells on your hero.

JASS:
constant function Fire_Blast_AbilId takes nothing returns integer
    return 'A000' //Change the ability raw code ('A000') to match the raw code of the ability in your map
endfunction

constant function Fire_Blast_MissileCount takes integer level returns integer
    return 12 //Number of missiles spawned (they will originate from caster and move outwards at equal angle intervals)
endfunction

constant function Fire_Blast_MissileModel takes nothing returns string
    return "" //Model path for the missiles
endfunction

constant function Fire_Blast_MissileSpeed takes integer level returns real
    return 522 //How fast the missiles travel (in wc3 speed units)
endfunction

constant function Fire_Blast_MissileAngleSpeed takes integer level returns real
    return 0.00 //How fast (in degrees per second) you want the missiles to turn (in case you want them to spiral or sumthing like tht)
endfunction

constant function Fire_Blast_MissileCollision takes integer level returns real
    return 200 + 100 * level //Collision size of the missiles (how close units have to get before getting hit by wave)
endfunction

constant function Fire_Blast_MissileDistance takes integer level returns real
    return 500 + 100 * level //Maximum distance the missiles travel
endfunction

constant function Fire_Blast_MissileHeight takes nothing returns real
    return 50.00 //Height at which missiles travel
endfunction

constant function Fire_Blast_Damage takes integer level returns real
    return 100 * level //Damage done to enemy units upon collision with missiles
endfunction

//===========================================================================

function InitTrig_Fire_Blast takes nothing returns nothing
    call OnAbilityEffect( Fire_Blast_AbilId() , "Fire_Blast_Actions")
endfunction

//===========================================================================

struct fireblastdata
    unit caster
    integer level
endstruct 

function Fire_Blast_Impact takes nothing returns nothing
    local unit missile = GetTriggerCollisionMissile()
    local unit u = GetTriggerUnit()
    local fireblastdata temp = GetAttachedInt( missile, "temp" )
    if ( GetTriggerUnit() != null ) then
        if ( IsUnitEnemy( u, GetOwningPlayer( temp.caster ) ) ) then
            call UnitDamageTarget( temp.caster, u, Fire_Blast_Damage( temp.level ), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS )
        endif
    else
        call CleanAttachedVars( missile )
        call temp.destroy()
    endif
    set missile = null
    set u = null
endfunction

function Fire_Blast_Actions takes nothing returns nothing
    local fireblastdata temp = fireblastdata.create()
    local unit missile
    local location casterloc
    local integer counter = 0
    set temp.caster = GetTriggerUnit()
    set temp.level = GetUnitAbilityLevel( caster, Fire_Blast_AbilId() )
    set casterloc = GetUnitLoc( temp.caster )
    loop
        exitwhen ( counter >= Fire_Blast_MissileCount( temp.level ) )
        set missile = CollisionMissile_CreateLoc( Fire_Blast_MissileModel(), casterloc, ( 360.00 / Fire_Blast_MissileCount( temp.level ) ) * counter, Fire_Blast_MissileSpeed( temp.level ), Fire_Blast_MissileAngleSpeed( temp.level ), Fire_Blast_MissileDistance( temp.level ), Fire_Blast_MissileHeight( temp.level ), true, Fire_Blast_MissileCollision( temp.level ), function Fire_Blast_Impact )
        call AttachInt( missile, "temp", temp )
        set counter = counter + 1
    endloop
    call RemoveLocation( casterloc )
    set missile = null
    set casterloc = null
endfunction


Ability 7:

Ok, here it is: Volcano recreated through JASS...

You need an ability that can target points and for user-friendliness probably should have the AoE targeting image (Channel works fine, just change casting type to unit or point location, check the Targeting Image box in the Options field, and change the area of effect to same area of effect you want your volcano to have).

In addition, you also need to make an ability based off stormbolt. Set damage to 0 and get rid of ALL missile models/effects. You should keep the stun buff. Set duration to how long you want units hit by volcano's projectiles to be stunned. Set mana cost to 0 and cooldown to 0.01.

JASS:
constant function Volcano_AbilId takes nothing returns integer
    return 'A000' //Ability raw code for your volcano spell
endfunction

constant function Volcano_StunAbilId takes nothing returns integer
    return 'A001' //Ability raw code for stun storm bolt spell
endfunction

constant function Volcano_StunAbilOrderString takes nothing returns string
    return "thunderbolt" //Ability raw code for stun storm bolt spell (shouldn't have to change)
endfunction

constant function Volcano_Stun takes nothing returns boolean
    return true //Controls whether or not projectiles stun
endfunction

constant function Volcano_AffectAllied takes nothing returns boolean
    return true //Controls whether or not projectiles damage friendlies
endfunction

constant function Volcano_ProjectileCount takes integer level returns integer
    return 12 //How many projectiles are spawned
endfunction

constant function Volcano_LaunchInterval takes integer level returns real
    return 5.00 //How often projectiles are launched
endfunction

constant function Volcano_RandomAngle takes nothing returns boolean
    return false //Controls whether or not projectiles are thrown at completely random angles
                 //If set to false, projectiles are thrown at regular angle intervals
endfunction                     

constant function Volcano_ProjectileModel takes nothing returns string
    return "" //Model file path for the projectiles that get thrown out
endfunction

constant function Volcano_ProjectileSpeed takes integer level returns real
    return 900.00 //Speed at which projectiles travel
endfunction

constant function Volcano_ProjectileArc takes integer level returns real
    return 0.30 //Arc of projectiles
endfunction

constant function Volcano_ProjectileZ1 takes integer level returns real
    return 0.00 //Height at which projectiles launch (should be set to 0 or else it looks like they are coming from midair)
endfunction

constant function Volcano_ProjectileZ2 takes integer level returns real
    return 0.00 //Height at which projectiles are destroyed when they come back down
endfunction

constant function Volcano_MaxRadius takes integer level returns real
    return 500.00 // Maximum distance projectiles can be hurled
endfunction

constant function Volcano_MinRadius takes integer level returns real
    return 50.00 // Minimum distance projectiles can be hurled
endfunction

constant function Volcano_Damage takes integer level returns real
    return 50.00 * level //Damage done by each projectile
endfunction

constant function Volcano_DamageRadius takes integer level returns real
    return 100.00 // AOE radius for projectiles to do damage
endfunction

constant function Volcano_Duration takes integer level returns real
    return 30.10 //Duration of Volcano spell
endfunction

//===========================================================================

struct volcanodata
    timer t = CreateTimer()
    unit caster
    real targetx
    real targety
    integer level
    method onDestroy takes nothing returns nothing
        if ( .t != null ) then
            call AttachInt( .caster, "temp", 0 )
            call CleanAttachedVars( .t )
            call DestroyTimer( .t )
        endif
    endmethod
endstruct

globals
    trigger volcanotrigger = CreateTrigger()
    trigger volcanostuntrigger = CreateTrigger()
    group volcanounits = CreateGroup()
    group volcanoprojectiles = CreateGroup()
endglobals

function VolcanoTrigger_Conditions takes nothing returns boolean
    return ( OrderId2String( GetIssuedOrderId() ) == "stop" and IsUnitInGroup( GetAttachedInt( GetTriggerUnit(), "temp" ), volcanounits ) )    
endfunction

function VolcanoTrigger_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local volcanodata temp = GetAttachedInt( u, "temp" )
    call temp.destroy()
    call GroupRemoveUnit( volcanounits, u )
    set u = null
endfunction

function VolcanoStunTrigger_Conditions takes nothing returns boolean
    return ( IsUnitInGroup( GetTriggerUnit(), volcanoprojectiles ) and Volcano_Stun )
endfunction

function VolcanoStunTrigger_Actions takes nothing returns nothing
    local unit proj = GetTriggerUnit()
    local volcanodata temp = GetAttachedInt( proj, "temp" )
    local real projx = GetUnitX( proj )
    local real projy = GetUnitY( proj )
    call CasterCastAbilityLevelAOE( GetOwningPlayer( proj ), Volcano_StunAbilId(), temp.level, Volcano_StunAbilOrderString(), projx, projy, Volcano_DamageRadius( temp.level ), false, false )
    if ( Volcano_AffectAllied() ) then
        call CasterCastAbilityLevelAOE( GetOwningPlayer( proj ), Volcano_StunAbilId(), temp.level, Volcano_StunAbilOrderString(), projx, projy, Volcano_DamageRadius( temp.level ), true, false )
    endif    
    call GroupRemoveUnit( volcanoprojectiles, proj )
    call CleanAttachedVars( proj )
    set proj = null    
endfunction

function Volcano_Launch takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local volcanodata temp = GetAttachedInt( t, "temp" )
    local unit proj
    local string modelpath = Volcano_ProjectileModel()
    local real speed = Volcano_ProjectileSpeed( temp.level )
    local real arc = Volcano_ProjectileArc( temp.level )
    local real z1 = Volcano_ProjectileZ1( temp.level )
    local real x2
    local real y2
    local real z2 = Volcano_ProjectileZ2( temp.level )
    local real damageradius = Volcano_DamageRadius( temp.level )
    local real damage = Volcano_Damage( temp.level )
    local boolean affectallied = Volcano_AffectAllied()
    local integer projcount = Volcano_ProjectileCount( temp.level )
    local real minradius = Volcano_MinRadius( temp.level )
    local real maxradius = Volcano_MaxRadius( temp.level )
    local boolean randomangle = Volcano_RandomAngle()
    local real distance
    local real angle
    local integer dopt = DamageTypes( ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
    local integer counter = 0
    loop
        exitwhen ( counter >= projcount )
        set distance = GetRandomReal( minradius, maxradius )
        if ( randomangle ) then
            set angle = GetRandomReal( 0.00, 360.00 )
            set x2 = PolarProjectionX( x1 , distance, angle )
            set y2 = PolarProjectionY( y1 , distance, angle )
        else
            set angle = ( 360.00 / projcount ) * counter
            set x2 = PolarProjectionX( x1 , distance, angle )
            set y2 = PolarProjectionY( y1 , distance, angle )
        endif
        set proj = DamagingProjectileLaunchAOE( temp.caster, modelpath, speed, arc, temp.targetx, temp.targety, z1, x2, y2, z2, damageradius, damage, affectallied, dopt )
        call AttachInt( proj, temp, "temp" )
        call GroupAddUnit( volcanoprojectiles, proj ) 
    endloop
    set t = null
    set proj = null
endfunction

function Volcano_Actions takes nothing returns nothing
    local volcanodata temp = volcanodata.create()
    local location targetloc = GetSpellTargetLoc()
    local integer counter = 0
    set temp.caster = GetTriggerUnit()
    set temp.level = GetUnitAbilityLevel( temp.caster, Volcano_AbilId() )
    set temp.targetx = GetLocationX( targetloc )
    set temp.targety = GetLocationY( targetloc )
    call TimerStart( temp.t, Volcano_LaunchInterval( temp.level ), true, function Volcano_Launch )
    call AttachInt( temp.t, "temp", temp )
    call AttachInt( temp.caster, "temp", temp )
    call GroupAddUnit( volcanounits, temp.caster )
    call TriggerSleepAction( Volcano_Duration( temp.level ) )
    call GroupRemoveUnit( volcanounits, temp.caster )
    call temp.destroy()
    call RemoveLocation( targetloc )
    set targetloc = null
endfunction

//===========================================================================

function InitTrig_Volcano takes nothing returns nothing
    call TriggerRegisterAnyUnitEventBJ( volcanotrigger, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( volcanotrigger, Condition( function VolcanoTrigger_Conditions ) )
    call TriggerAddAction( volcanotrigger, function VolcanoTrigger_Actions )
    call TriggerRegisterAnyUnitEventBJ( volcanostuntrigger, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( volcanotrigger, Condition( function VolcanoStunTrigger_Conditions ) )
    call TriggerAddAction( volcanostuntrigger, function VolcanoStunTrigger_Actions )
    call OnAbilityEffect( Volcano_AbilId() , "Volcano_Actions")
endfunction


Remember, don't forget to change all of the necessary values to fit your map (all of the constant function returns at the top of each script)

Enjoy.
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
Jass ---> Constant values = Constant functions
---> Dependant values* = Constant functionis

vJass ---> Constant values = Constant globals
---> Dependant values* = Methods

*damage, for example (depends on the level)

Jass code:

JASS:
constant function FireFury_SpellId takes nothing returns integer
    return 'A000'
endfunction

constant function FireFury_DummyId takes nothing returns integer
    return 'h000'
endfunction

constant function FireFury_FlameDuration takes nothing returns real
    return 4.0
endfunction

constant function FireFury_FlameDmg takes real lev returns real
    return lev * 50.0
endfunction

constant function FireFury_FlameCount takes integer lev returns integer
    return lev * 2
endfunction

//=========================================================================

function FireFury_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == FireFury_SpellId()
endfunction

function FireFury_Actions takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local unit t = GetSpellTargetUnit()
    local unit u
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local real f = GetUnitFacing(c)
    local integer lev = GetUnitAbilityLevel(c, FireFury_SpellId())
    local integer i = 0
    local player p = GetOwningPlayer(c)
    local group g = CreateGroup()
    
    // .....
    // .....
    
    loop
        exitwhen i == FireFury_FlameCount(lev)
        set u = CreateUnit(p, FireFury_DummyId(), x, y, f)
        call UnitApplyTimedLife(u, 'BTLF', FireFury_FlameDuration())
        call GroupAddUnit(g, u)
        set i = i + 1
    endloop
    
    // .....
    // .....
    
    call UnitDamageTarget(c, t, FireFury_FlameDmg(I2R(lev)), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null)
    
    // .....
    // .....
    // .....
    
    call DestroyGroup(g)
    
    set c = null
    set t = null
    set p = null
    set g = null
endfunction

//============================================
function InitTrig_FireFury takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i == bj_MAX_PLAYER_SLOTS
        call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set i = i + 1
    endloop
    call TriggerAddCondition(t, Condition(function FireFury_Conditions))
    call TriggerAddAction(t, function FireFury_Actions)
    set t = null
endfunction


vJass code:

JASS:
scope FireFury

globals
    private constant integer SPELL_ID = 'A000'
    private constant integer DUMMY_ID = 'h000'
    private constant real FLAME_DUR = 4
endglobals

struct Fire_Data
    integer lev
    method FlameDmg takes nothing returns real
        return .lev * 50
    endmethod
    method FlameCount takes nothing returns integer
        return .lev * 2
    endmethod
endstruct

//=========================================================================

function FireFury_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

function FireFury_Actions takes nothing returns nothing
    local Fire_Data fd = Fire_Data.create()
    local unit c = GetTriggerUnit()
    local unit t = GetSpellTargetUnit()
    local unit u
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local real f = GetUnitFacing(c)
    local integer lev = GetUnitAbilityLevel(c, SPELL_ID)
    local integer i = 0
    local player p = GetOwningPlayer(c)
    local group g = CreateGroup()
    
    set fd.lev = lev
    
    // .....
    // .....
    
    loop
        exitwhen i == fd.FlameCount()
        set u = CreateUnit(p, DUMMY_ID, x, y, f)
        call UnitApplyTimedLife(u, 'BTLF', FLAME_DUR)
        call GroupAddUnit(g, u)
        set i = i + 1
    endloop
    
    // .....
    // .....
    
    call UnitDamageTarget(c, t, fd.FlameDmg(), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null)
    
    // .....
    // .....
    // .....
    
    call DestroyGroup(g)
    
    set c = null
    set t = null
    set p = null
    set g = null
endfunction

//============================================
function InitTrig_FireFury takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i == bj_MAX_PLAYER_SLOTS
        call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set i = i + 1
    endloop
    call TriggerAddCondition(t, Condition(function FireFury_Conditions))
    call TriggerAddAction(t, function FireFury_Actions)
    set t = null
endfunction

endscope


I just made them really quick, so there might be some errors.
 
Level 6
Joined
Dec 13, 2007
Messages
213
How does this sound

i may have found a simpler way to do ability 7

What if i were to base it off inferno, but instead of summoning an infernal, it summons a small unit you can't see (because it says it has to summon a unit) that last half a second, so that way it looks like just a big fiery ball of Death hits. and instead of making the boss keep casting it i make some casters off to the side, make em invisible and use triggers to make them cast it? sound good or should i just stick with Jass?

for Ability 4, the water elemental will use the Blink ability, and when he uses it i use a trigger that goes:
Event:
When water elemental boss uses ability
Condition:
ability being cast equal to blink
Action:
make special effect on unit

and this special effect will look like a Naga building explosion, Because it looks like a splash, and attach it to Grade D Kill his name will be. this is the best i can do until i learn Jass, im trying to learn now.
 
Level 6
Joined
Dec 13, 2007
Messages
213
the hard stuff is over, my map is set! or atleast the hard stuff is set, the whirlpool works the wave thing is good, thanks for the help everyone, it took me a while but i figured the scripts out(kinda) and so far Grade F Kill and Grade D Kill are done, Grade C B and A are next. expect to see my map up there soon, once i upload the previeus map(Necropolis)
 
Status
Not open for further replies.
Top