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

[JASS] Exploading Fireball Spell

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
Before I go if someone has made this spell before then he must know that I didn't stole his resource

I want to make a fire spell using GUI or JASS doesn't matter.
The spell is like the following:

You cast a firebolt at a target point on the ground then it expand into circular firey blow dealing damage to all within the AoE.

Things that must be taken in consideration:
- No Leak
- MUI spell
- Doesn't Ignore Spell Immunity or Resistance
- Don't affect the caster or his allies if standing in the AoE

Can anyone help me with this ?

And thanks in advance :as:
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
You don't need any dummy for UnitDamageTarget...


So it is simply picking up units in X AoE around the casting point and damage them but checking if they are immune to spell or not, isn't it?

Another question:
While I was tring to make this spell I based it upon Rain of Fire spell to have the cursor showing the AoE but addind missle art doesn't work what spell should I base upon it to have a missle art of Firebolt and have the AoE cursor ?
 
So it is simply picking up units in X AoE around the casting point and damage them but checking if they are immune to spell or not, isn't it?
Just enumerate units in x range of y point, then loop through them and if they're an enemy of the caster, call UnitDamageTarget(caster, u, AMOUNT, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS).

Another question:
While I was tring to make this spell I based it upon Rain of Fire spell to have the cursor showing the AoE but addind missle art doesn't work what spell should I base upon it to have a missle art of Firebolt and have the AoE cursor ?
Channel spell.
 
Level 7
Joined
Dec 18, 2008
Messages
400
cant you just make a fireball spell that can only target ground and then place a dummy at target of ability being cast that cast some kind of warstomp that looks like an explosion but doesent stun?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
cant you just make a fireball spell that can only target ground and then place a dummy at target of ability being cast that cast some kind of warstomp that looks like an explosion but doesent stun?

Will this work perfectly ?

Notice that it will take some time for units at far radius to take damage from the spell, if you created as you say all units will take the damage at the same time and it will not be logical with the expanding ring of fire.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Now, creating a dummy unit at that casts Warstomp causes all units in ... well, lets say 500 AoE to take D damage all at the same time. The real challenge is timing the damage so that units in the first 100 AoE take damage first when the animation of the expanding ring is near them then units between 100 to 200 AoE will take the damage after the first group and so on, although the timing will be small because the ring expands quickly. It sound like immposible to me but you guyes made immposible real. Any help or idea ?
 
Level 12
Joined
Dec 10, 2008
Messages
850
Easy if you think about it right, use warstomp with a 100 AOE that deals half the damage you want them to take, then have another spell with 200 AOE that deals the rest of the damage, makes the units within 100 AOE recive all the damage they should, and units in 100-200 AOE take the damage they are supposed to.

Its kinda like cheating
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Easy if you think about it right, use warstomp with a 100 AOE that deals half the damage you want them to take, then have another spell with 200 AOE that deals the rest of the damage, makes the units within 100 AOE recive all the damage they should, and units in 100-200 AOE take the damage they are supposed to.

Its kinda like cheating

Units in 100-200 AoE will take half damage only from the second warstomp.

I have thought it in different way. If I created an array unit group and add units to this group. If you add units 100 AoE to the group[1] then add all units within 200 AoE to gruop[2] then a simple condition check that remove unit from group[2] if they exist in group[1].

What do you think of this ?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Now about the animation what special effect to use to create a ring of expanding fire.

I knew a way long ago about creating a dummy unit with a special model then have it move outside the centre of the circle but that is not an effective way because there is a limit to the maximum move speed. Any idea ?

Edit
Note: The ring have to expand quickly, like that of Frost Nova in Diablo II

2nd Edit
After thinking I noticed that to make what I mentioned first I have to add waits which will cause the spell to be non-MUI. I'm begining to feel making this spell is hopless. Can someone raise my morale and convince me otherwise ?
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
How effecient is creating units at the casting point and they Fire Breath in a radial locations ?

Edit
I have tried this: Create a dummy unit a the point of casting and it has the fire breath spell and set this spell AoE to maximum which will be 99999.00. Now target the same location of the casting unit as the dummy unit will have locust ability and will be untargetable. Making this high AoE will cause all units around the dummy unit to take the fire damage needed. Only one thing is remaing for me which is creating the Special Effect... mmmm. I wonder what model I use and how ?

Edit
set this spell AoE to maximum which will be 99999.00
add
Final Area = 99999.00 ... well not that high number or the enemy in the entire map will caught in flames

2nd Edit - Disappointed
Well ... it doesn't go as I had hoped :(
The damage distribution was wrong. When I make a big AoE I didn't see how damage distribution was but when I lower the number I see how the damage distribution is. Now I have to think of in MUI JASS spell again.
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
meh i wrote a über vJass spell and u want some shitty warstomp :/

shitty ==> please guys be patient with rookies.

What is/are über vJass ?

This is what I made but not an MUI since it contains wait and I can't remove them. here are the codes:
  • Events
    • Unit - A unit Starts the effect of an ability
  • Conditions
    • (Ability being cast) Equal to Cluster Rockets (Test)
  • Actions
    • -------- This wait is for the missile of the dummy spell to reach the point target --------
    • Wait 0.70 seconds
    • Set Temp_Point = (Target point of ability being cast)
    • Unit Group - Pick every unit in (Units within 200.00 of Temp_Point) and do (Actions)
      • Loop - Actions
        • Unit Group - Add (Picked unit) to UnitsInRange[2]
    • Unit Group - Pick every unit in (Units within 100.00 of Temp_Point) and do (Actions)
      • Loop - Actions
        • Unit Group - Add (Picked unit) to UnitsInRange[1]
    • Unit Group - Remove all units of UnitsInRange[1] from UnitsInRange[2]
    • Unit Group - Pick every unit in UnitsInRange[1] and do (Unit - Cause TestUnit to damage (Picked unit), dealing 500.00 damage of attack type Spells and damage type Fire)
    • Wait 0.25 seconds
    • Unit Group - Pick every unit in UnitsInRange[2] and do (Unit - Cause TestUnit to damage (Picked unit), dealing 500.00 damage of attack type Spells and damage type Fire)
Ignore leak for now.
Adding the 0.25 sec causes this spell to be non-MUI, isn't it?

If this 0.25 sec removed then there is no need to add units in unit groups.
 
Level 11
Joined
Apr 6, 2008
Messages
760
Vjass stands for very jass which opens up OOP programming to WE

Here's the manual for Vjass (dunno if this is a updated 1)
JassHelper 0.9.F.0

here's a alpha of the code got some things to change and make more efficent

JASS:
scope FireBall initializer init
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//= Exploding Fireball Spell By Ciebron                                                *=
//=                                                                                    *=
//= A request by Starquizer                                                            *=
//=                                                                                    *=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*Setup Starts=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
globals
    private constant integer Abil_id = 'A000'
    //Rawcode of the Ability
    private constant integer Dummy_id = 'h000'
    //Rawcode of the Dummy projectile
    private constant integer Nova_id = 'h001'
    //Rawcode of the Dummy's that will make the nova
    private constant real Curve = 6
    //A value used by the JumpParabola (lower number makes it go higher and the other way around)
    private constant real Move_Dist = 30.
    //How much the Projectile will move Every interval
    private constant real Nova_MDist = 20.
    //How much the Nova will Expand every interval
    private constant real Aoe = 300.
    //How big the Aoe will be
    private constant integer Nova_Size = 16
    //Number of the dummys that will make the nova
    private constant attacktype AtkType = ATTACK_TYPE_MAGIC
    //Attack Type of the spell
    private constant damagetype DmgType = DAMAGE_TYPE_MAGIC
    //Damage Type of the spell
    private constant real Interval = 0.03
    //Freqency of the spell
    private constant real NInterval = 0.03
    //Freqency of the Nova to expand
endglobals
//This function is based on the level of the spell
private function Damage takes integer level returns real
    return 125.+(50.*level)
endfunction

//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*Setup Ends=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

//A JumpParabola that make so the projectile arc nicely
//Credits to Shadow1500
function JumpParabola takes real dist, real maxdist, real curve returns real
    local real t = (dist * 2) / maxdist - 1
    return (- t * t + 1) * (maxdist / curve)
endfunction

globals
    //Used by the spell don't touch these :)
    private integer Struct
    private boolexpr Bool
endglobals

private struct NovaData
unit u
unit array dummy [Nova_Size]

player P

real dist
real x
real y
real array cos [Nova_Size]
real array sin [Nova_Size]
real damage

group g

static group G = CreateGroup()
static integer Total = 0
static integer array Ar
static timer Time = CreateTimer()
static integer index
static unit TempU

    static method create takes unit u,real x,real y,real dmg returns NovaData
        local NovaData Dat = NovaData.allocate()
        local integer i = 0
        local real a = 0
        local real ai = 360/Nova_Size
        
        set Dat.u = u
        set Dat.x = x
        set Dat.y = y
        set Dat.dist = 0.
        set Dat.damage = dmg
        
        loop
            exitwhen i >= Nova_Size
            set Dat.dummy[i] = CreateUnit(GetOwningPlayer(Dat.u),Nova_id,x,y,a)
            set Dat.cos[i] = Cos(a*bj_DEGTORAD)
            set Dat.sin[i] = Sin(a*bj_DEGTORAD)
            set a = a + ai
            set i = i + 1
        endloop
        
        if Dat.Total == 0 then
            call TimerStart(Dat.Time,NInterval,true,function NovaData.Loop)
        endif
        
        set Dat.Ar[Dat.Total] = Dat
        set Dat.Total = Dat.Total + 1
        
        return Dat
    endmethod
    
    static method Loop takes nothing returns nothing
        local NovaData Dat
        local integer i = 0
        
        loop
            exitwhen i >= Dat.Total
            set Dat = Dat.Ar[i]
            
            set Dat.index = 0
            set Dat.dist = Dat.dist + Nova_MDist
            
            loop
                exitwhen Dat.index >= Nova_Size
                call SetUnitX(Dat.dummy[Dat.index],Dat.x+Dat.dist*Dat.cos[Dat.index])
                call SetUnitY(Dat.dummy[Dat.index],Dat.y+Dat.dist*Dat.sin[Dat.index])
                set Dat.index = Dat.index + 1
            endloop
            
            set Struct = Dat
            call GroupEnumUnitsInRange(Dat.G,Dat.x,Dat.y,Dat.dist,Bool)
            
            loop
                set Dat.TempU = FirstOfGroup(Dat.G)
                exitwhen Dat.TempU == null
                call GroupRemoveUnit(Dat.G,Dat.TempU)
                call UnitDamageTarget(Dat.u,Dat.TempU,Dat.damage,false,false,AtkType,DmgType,null)
            endloop
            
            if Dat.dist >= Aoe then
                set Dat.index = 0
                
                loop
                    exitwhen Dat.index >= Nova_Size
                    call KillUnit(Dat.dummy[Dat.index])
                    set Dat.index = Dat.index + 1
                endloop
                
                set Dat.Total = Dat.Total - 1
                set Dat.Ar[i] = Dat.Ar[Dat.Total]
                set i = i - 1
                call Dat.destroy()
            endif
            
            set i = i + 1
        endloop
        
        if Dat.Total == 0 then
            call PauseTimer(Dat.Time)
        endif
    endmethod

    static method UnitFilter takes nothing returns boolean
        local NovaData Dat = Struct
        local unit f = GetFilterUnit()
        local boolean ok = GetWidgetLife(f) <= .305 and IsUnitEnemy(f,Dat.P) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE)
        set f = null
        return ok
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
    
        set .u = null
        
        loop
            exitwhen i >= Nova_Size
            set .dummy[i] = null
            set i = i + 1
        endloop
    endmethod
    
endstruct

private struct Data
unit u
unit Dummy

real cos
real sin
real dist
real maxdist
real damage

static integer Total = 0
static integer array Ar
static timer Time = CreateTimer()
static real z
static real x
static real y


    static method create takes unit u,real x,real y returns Data
        local Data Dat = Data.allocate()
        local real ux = GetUnitX(u)
        local real uy = GetUnitY(u)
        local real DistX = x-ux
        local real DistY = y-uy
        local real a = Atan2(DistY,DistX)
        
        set Dat.u = u
        set Dat.Dummy = CreateUnit(GetOwningPlayer(Dat.u),Dummy_id,ux,uy,a*bj_RADTODEG)
        set Dat.cos = Cos(a)
        set Dat.sin = Sin(a)
        set Dat.maxdist = SquareRoot(DistX*DistX+DistY*DistY)
        set Dat.dist = 0
        set Dat.damage = Damage(GetUnitAbilityLevel(Dat.u,Abil_id))
        
        if Dat.Total == 0 then
            call TimerStart(Dat.Time,Interval,true,function Data.Loop)
        endif
        
        set Dat.Ar[Dat.Total] = Dat
        set Dat.Total = Dat.Total + 1
        
        set u = null
        
        return Dat
    endmethod
    
    static method Loop takes nothing returns nothing
        local Data Dat
        local integer i = 0
        
        loop
            exitwhen i >= Dat.Total
            set Dat = Dat.Ar[i]
            
            set Dat.dist = Dat.dist + Move_Dist
            set Dat.z = JumpParabola(Dat.dist,Dat.maxdist,Curve)
            set Dat.x = GetUnitX(Dat.Dummy)+Move_Dist*Dat.cos
            set Dat.y = GetUnitY(Dat.Dummy)+Move_Dist*Dat.sin
            
            call SetUnitFlyHeight(Dat.Dummy,Dat.z,0.)
            call SetUnitX(Dat.Dummy,Dat.x)
            call SetUnitY(Dat.Dummy,Dat.y)
            
            if Dat.z <= 0. then
                call KillUnit(Dat.Dummy)
                call NovaData.create(Dat.u,Dat.x,Dat.y,Dat.damage)
                set Dat.Total = Dat.Total - 1
                set Dat.Ar[i] = Dat.Ar[Dat.Total]
                set i = i - 1
                call Dat.destroy()
            endif
            
            set i = i + 1
        endloop
        
        if Dat.Total == 0 then
            call PauseTimer(Dat.Time)
        endif
        
    endmethod

    method onDestroy takes nothing returns nothing
        set .u = null
        set .Dummy = null
    endmethod
    
endstruct

private function OnCast takes nothing returns boolean
    local unit u
    local location Tloc
    
    if GetSpellAbilityId()==Abil_id then
        set u = GetTriggerUnit()
        set Tloc = GetSpellTargetLoc()
        call Data.create(u,GetLocationX(Tloc),GetLocationY(Tloc))
        call RemoveLocation(Tloc)
        set Tloc = null
        set u = null
    endif
    
    return false
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local integer index = 0
    
    loop
        call TriggerRegisterPlayerUnitEvent(trig, Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    //We use condition instead of action because condition is faster
    call TriggerAddCondition(trig,Condition(function OnCast))
    //Setting the Boolexpr filter
    set Bool = Filter(function NovaData.UnitFilter)
    
    set trig = null
endfunction

endscope
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
Vjass stands for very jass which opens up OOP programming to WE

Here's the manual for Vjass (dunno if this is a updated 1)
JassHelper 0.9.F.0

here's a alpha of the code got some things to change and make more efficent

JASS:
scope FireBall initializer init
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//= Exploding Fireball Spell By Ciebron                                                *=
//=                                                                                    *=
//= A request by Starquizer                                                            *=
//=                                                                                    *=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*Setup Starts=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
globals
    private constant integer Abil_id = 'A000'
    //Rawcode of the Ability
    private constant integer Dummy_id = 'h000'
    //Rawcode of the Dummy projectile
    private constant integer Nova_id = 'h001'
    //Rawcode of the Dummy's that will make the nova
    private constant real Curve = 6
    //A value used by the JumpParabola (lower number makes it go higher and the other way around)
    private constant real Move_Dist = 30.
    //How much the Projectile will move Every interval
    private constant real Nova_MDist = 20.
    //How much the Nova will Expand every interval
    private constant real Aoe = 300.
    //How big the Aoe will be
    private constant integer Nova_Size = 16
    //Number of the dummys that will make the nova
    private constant attacktype AtkType = ATTACK_TYPE_MAGIC
    //Attack Type of the spell
    private constant damagetype DmgType = DAMAGE_TYPE_MAGIC
    //Damage Type of the spell
    private constant real Interval = 0.03
    //Freqency of the spell
    private constant real NInterval = 0.03
    //Freqency of the Nova to expand
endglobals
//This function is based on the level of the spell
private function Damage takes integer level returns real
    return 125.+(50.*level)
endfunction

//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*Setup Ends=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

//A JumpParabola that make so the projectile arc nicely
//Credits to Shadow1500
function JumpParabola takes real dist, real maxdist, real curve returns real
    local real t = (dist * 2) / maxdist - 1
    return (- t * t + 1) * (maxdist / curve)
endfunction

globals
    //Used by the spell don't touch these :)
    private integer Struct
    private boolexpr Bool
endglobals

private struct NovaData
unit u
unit array dummy [Nova_Size]

player P

real dist
real x
real y
real array cos [Nova_Size]
real array sin [Nova_Size]
real damage

group g

static group G = CreateGroup()
static integer Total = 0
static integer array Ar
static timer Time = CreateTimer()
static integer index
static unit TempU

    static method create takes unit u,real x,real y,real dmg returns NovaData
        local NovaData Dat = NovaData.allocate()
        local integer i = 0
        local real a = 0
        local real ai = 360/Nova_Size
        
        set Dat.u = u
        set Dat.x = x
        set Dat.y = y
        set Dat.dist = 0.
        set Dat.damage = dmg
        
        loop
            exitwhen i >= Nova_Size
            set Dat.dummy[i] = CreateUnit(GetOwningPlayer(Dat.u),Nova_id,x,y,a)
            set Dat.cos[i] = Cos(a*bj_DEGTORAD)
            set Dat.sin[i] = Sin(a*bj_DEGTORAD)
            set a = a + ai
            set i = i + 1
        endloop
        
        if Dat.Total == 0 then
            call TimerStart(Dat.Time,NInterval,true,function NovaData.Loop)
        endif
        
        set Dat.Ar[Dat.Total] = Dat
        set Dat.Total = Dat.Total + 1
        
        return Dat
    endmethod
    
    static method Loop takes nothing returns nothing
        local NovaData Dat
        local integer i = 0
        
        loop
            exitwhen i >= Dat.Total
            set Dat = Dat.Ar[i]
            
            set Dat.index = 0
            set Dat.dist = Dat.dist + Nova_MDist
            
            loop
                exitwhen Dat.index >= Nova_Size
                call SetUnitX(Dat.dummy[Dat.index],Dat.x+Dat.dist*Dat.cos[Dat.index])
                call SetUnitY(Dat.dummy[Dat.index],Dat.y+Dat.dist*Dat.sin[Dat.index])
                set Dat.index = Dat.index + 1
            endloop
            
            set Struct = Dat
            call GroupEnumUnitsInRange(Dat.G,Dat.x,Dat.y,Dat.dist,Bool)
            
            loop
                set Dat.TempU = FirstOfGroup(Dat.G)
                exitwhen Dat.TempU == null
                call GroupRemoveUnit(Dat.G,Dat.TempU)
                call UnitDamageTarget(Dat.u,Dat.TempU,Dat.damage,false,false,AtkType,DmgType,null)
            endloop
            
            if Dat.dist >= Aoe then
                set Dat.index = 0
                
                loop
                    exitwhen Dat.index >= Nova_Size
                    call KillUnit(Dat.dummy[Dat.index])
                    set Dat.index = Dat.index + 1
                endloop
                
                set Dat.Total = Dat.Total - 1
                set Dat.Ar[i] = Dat.Ar[Dat.Total]
                set i = i - 1
                call Dat.destroy()
            endif
            
            set i = i + 1
        endloop
        
        if Dat.Total == 0 then
            call PauseTimer(Dat.Time)
        endif
    endmethod

    static method UnitFilter takes nothing returns boolean
        local NovaData Dat = Struct
        local unit f = GetFilterUnit()
        local boolean ok = GetWidgetLife(f) <= .305 and IsUnitEnemy(f,Dat.P) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE)
        set f = null
        return ok
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i = 0
    
        set .u = null
        
        loop
            exitwhen i >= Nova_Size
            set .dummy[i] = null
            set i = i + 1
        endloop
    endmethod
    
endstruct

private struct Data
unit u
unit Dummy

real cos
real sin
real dist
real maxdist
real damage

static integer Total = 0
static integer array Ar
static timer Time = CreateTimer()
static real z
static real x
static real y


    static method create takes unit u,real x,real y returns Data
        local Data Dat = Data.allocate()
        local real ux = GetUnitX(u)
        local real uy = GetUnitY(u)
        local real DistX = x-ux
        local real DistY = y-uy
        local real a = Atan2(DistY,DistX)
        
        set Dat.u = u
        set Dat.Dummy = CreateUnit(GetOwningPlayer(Dat.u),Dummy_id,ux,uy,a*bj_RADTODEG)
        set Dat.cos = Cos(a)
        set Dat.sin = Sin(a)
        set Dat.maxdist = SquareRoot(DistX*DistX+DistY*DistY)
        set Dat.dist = 0
        set Dat.damage = Damage(GetUnitAbilityLevel(Dat.u,Abil_id))
        
        if Dat.Total == 0 then
            call TimerStart(Dat.Time,Interval,true,function Data.Loop)
        endif
        
        set Dat.Ar[Dat.Total] = Dat
        set Dat.Total = Dat.Total + 1
        
        set u = null
        
        return Dat
    endmethod
    
    static method Loop takes nothing returns nothing
        local Data Dat
        local integer i = 0
        
        loop
            exitwhen i >= Dat.Total
            set Dat = Dat.Ar[i]
            
            set Dat.dist = Dat.dist + Move_Dist
            set Dat.z = JumpParabola(Dat.dist,Dat.maxdist,Curve)
            set Dat.x = GetUnitX(Dat.Dummy)+Move_Dist*Dat.cos
            set Dat.y = GetUnitY(Dat.Dummy)+Move_Dist*Dat.sin
            
            call SetUnitFlyHeight(Dat.Dummy,Dat.z,0.)
            call SetUnitX(Dat.Dummy,Dat.x)
            call SetUnitY(Dat.Dummy,Dat.y)
            
            if Dat.z <= 0. then
                call KillUnit(Dat.Dummy)
                call NovaData.create(Dat.u,Dat.x,Dat.y,Dat.damage)
                set Dat.Total = Dat.Total - 1
                set Dat.Ar[i] = Dat.Ar[Dat.Total]
                set i = i - 1
                call Dat.destroy()
            endif
            
            set i = i + 1
        endloop
        
        if Dat.Total == 0 then
            call PauseTimer(Dat.Time)
        endif
        
    endmethod

    method onDestroy takes nothing returns nothing
        set .u = null
        set .Dummy = null
    endmethod
    
endstruct

private function OnCast takes nothing returns boolean
    local unit u
    local location Tloc
    
    if GetSpellAbilityId()==Abil_id then
        set u = GetTriggerUnit()
        set Tloc = GetSpellTargetLoc()
        call Data.create(u,GetLocationX(Tloc),GetLocationY(Tloc))
        call RemoveLocation(Tloc)
        set Tloc = null
        set u = null
    endif
    
    return false
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    local integer index = 0
    
    loop
        call TriggerRegisterPlayerUnitEvent(trig, Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    //We use condition instead of action because condition is faster
    call TriggerAddCondition(trig,Condition(function OnCast))
    //Setting the Boolexpr filter
    set Bool = Filter(function NovaData.UnitFilter)
    
    set trig = null
endfunction

endscope

Thanks for the help but how could I learn vJASS if I don't know JASS well, its completely complex, but I thank you anyway.

-----

Add

Can this codes be pasted in the map custom script, I don't know how to use them.
 
Level 14
Joined
Nov 18, 2007
Messages
816
If you are learning Jass, go directly for vJass, makes your life a lot easier (declaring globals wherever you need them).

And converting something like this to plain Jass is pointless: First, because JassHelper does that for you, and second, because the resulting code is a lot more complex as it involves allocation and deallocation algorithms for structs and 2D arrays.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
If you are learning Jass, go directly for vJass, makes your life a lot easier (declaring globals wherever you need them).

And converting something like this to plain Jass is pointless: First, because JassHelper does that for you, and second, because the resulting code is a lot more complex as it involves allocation and deallocation algorithms for structs and 2D arrays.

Is vJASS some sort of converting the function database of WC3 into those functions of vJASS which involves more functions ?

If so, then how to convert my map from JASS to vJASS ?
 
Level 11
Joined
Apr 6, 2008
Messages
760
u dont need to convert u map to Vjass. vJass also not add additional functions read the manual and u will know what it does :)

also here is the map of the spell i made for u (no fully optimized). i made a nova system and a parabola missile. it shadow themed but u can easy make it fire themed (just didnt find something fire for the "fire nova")
 

Attachments

  • Nova System by Ciebron Alpha v1.1.w3x
    28.1 KB · Views: 65
Level 16
Joined
Mar 3, 2006
Messages
1,564
u dont need to convert u map to Vjass. vJass also not add additional functions read the manual and u will know what it does :)

also here is the map of the spell i made for u (no fully optimized). i made a nova system and a parabola missile. it shadow themed but u can easy make it fire themed (just didnt find something fire for the "fire nova")

Thanks for the map.

But there is mistake I found it by chance: The spell worked on opponents normally but when I casted it on the caster portrait it created the initial effect and left it without dissappearing then the spell didn't work after that.

Also when I tried to to change the model file of Priest unit which create the nova effect the triggers gave me an error in the script.

After more testing:
I can't modify anything in the map even the start position when moved it gave me errors.

Questions:
What are structs and what is the meaning of private ?
You also told me to read a manual what manual are you refering to ?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
it because u dont have jass newgen pack i thing if u try to save it, it will give u a error (i u change anything it need to save)

Your vJASS map was too hard for me to understand, at least for now; as I'm still a begginer in JASS. Let's try it in GUI then move to JASS.

If you were to make this spell in GUI what would you think of ?

There is a Tutorial by wyrmlord about making your spell MUI, the first method is using local variable and the second is by using an index. The first method have faults so I'm gonna ignore it and use the second but will it work well in this spell ?
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
i suggest using indexed (which i use in my map also)

Index will work properly, I think. But there is a problem that annoyes me which waits; as I found wait is related to the game speed.

I added a 0.7sec wait for the missile to reach the target point but when I slow down the game I found the action that must happen after the wait are executed before the missile of the spell reach the target.

P.S. If you don't understand what I mean try the map I attached to see what I mean, it has many faults as I was constructing the principle action of the spell.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
yeah, The "fireball" a dummy unit with u move every X interval (every 0.4 second) towards the target location, and when it is close enough u remove the dummy then u do the nova.

You are very patient Ciebron :thumbs_up:

How could I check that the dummy unit is near the point ?
Also the maximum move speed in Object Editor is 522.00 which will be slow I think ?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Did you miss me, huh ? ......... I guess not.

Well lets summerize whats need to be done if this spell is to be made in GUI (Correct anything that is wrong)

1- Create a dummy things that is needed
2- When dummy spell is casted a dummy unit is created and is ordered to move to the target point to create the effect of missile art.
3- A check condition to indicate that the last created dummy unit has reached the target
4- Now lets start the spell action and since it includes waits we will use Index (Implementing Stacks as mentioned by wyrmlord)

Are there anything I miss ?

I'm sure I got everyone that read this thread tired and bored from my lots of questions.
 
Last edited:

peq

peq

Level 6
Joined
May 13, 2007
Messages
171
I wanted to make something in gui aggain so:

  • ExFic create
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ExFi_FreeIndexesCount Greater than 0
        • Then - Actions
          • -------- Pop a free index from the free-indexes Stack --------
          • Set ExFi_FreeIndexesCount = (ExFi_FreeIndexesCount - 1)
          • Set CurrentIndex = ExFi_FreeIndexes[ExFi_FreeIndexesCount]
        • Else - Actions
          • -------- Now free index on the stack -> create a new one --------
          • Set CurrentIndex = ExFi_MaxIndex
          • Set ExFi_MaxIndex = (ExFi_MaxIndex + 1)
      • -------- Add current index to the list of active instances --------
      • Set ExFi_Instances[ExFi_InstancesCount] = CurrentIndex
      • Set ExFi_s_Instance[CurrentIndex] = ExFi_InstancesCount
      • Set ExFi_InstancesCount = (ExFi_InstancesCount + 1)
      • -------- Start Periodic Trigger if its the first instance --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ExFi_InstancesCount Equal to 1
        • Then - Actions
          • Trigger - Turn on ExFi Periodic <gen>
        • Else - Actions
  • ExFi destroy
    • Events
    • Conditions
    • Actions
      • -------- push the current index onto the stack --------
      • Set ExFi_FreeIndexes[ExFi_FreeIndexesCount] = CurrentIndex
      • Set ExFi_FreeIndexesCount = (ExFi_FreeIndexesCount + 1)
      • -------- Remove the instance from the list of active instances --------
      • -------- (move the last instance to the position of the curret instance) --------
      • Set ExFi_InstancesCount = (ExFi_InstancesCount - 1)
      • Set ExFi_s_Instance[ExFi_Instances[ExFi_InstancesCount]] = ExFi_s_Instance[CurrentIndex]
      • Set ExFi_Instances[ExFi_s_Instance[CurrentIndex]] = ExFi_Instances[ExFi_InstancesCount]
      • -------- Turn off periodic Trigger if no instances are left --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ExFi_InstancesCount Equal to 0
        • Then - Actions
          • Trigger - Turn off ExFi Periodic <gen>
        • Else - Actions
  • ExFi onSpellEffect
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Fireball
    • Actions
      • -------- ceate an instance of the spell --------
      • Trigger - Run ExFic create <gen> (checking conditions)
      • -------- Set all the starting values --------
      • Set ExFI_s_Caster[CurrentIndex] = (Triggering unit)
      • Set ExFI_s_Direction[CurrentIndex] = (Angle from (Position of (Triggering unit)) to (Target point of ability being cast))
      • Unit - Create 1 Missile for (Owner of (Triggering unit)) at ((Position of (Triggering unit)) offset by 100.00 towards ExFI_s_Direction[CurrentIndex] degrees) facing ExFI_s_Direction[CurrentIndex] degrees
      • Set ExFI_s_Missile[CurrentIndex] = (Last created unit)
      • Set ExFI_s_DistToTravell[CurrentIndex] = (Distance between (Position of ExFI_s_Missile[CurrentIndex]) and (Target point of ability being cast))
      • Set ExFI_s_NovaPhase[CurrentIndex] = False
      • Unit Group - Remove all units from ExFi_s_AlreadyHit[CurrentIndex]
  • ExFi Periodic
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • -------- Loop over all the instances --------
      • For each (Integer B) from 0 to (ExFi_InstancesCount - 1), do (Actions)
        • Loop - Actions
          • Set CurrentIndex = ExFi_Instances[(Integer B)]
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ExFI_s_NovaPhase[CurrentIndex] Equal to True
            • Then - Actions
              • -------- This instance is currently in the nova-phase --------
              • Set ExFI_s_DistToTravell[CurrentIndex] = (ExFI_s_DistToTravell[CurrentIndex] + 15.00)
              • For each (Integer A) from 0 to 9, do (Actions)
                • Loop - Actions
                  • Unit - Move ExFI_s_NovaMissiles[((10 x CurrentIndex) + (Integer A))] instantly to ((Position of ExFI_s_Missile[CurrentIndex]) offset by ExFI_s_DistToTravell[CurrentIndex] towards (((Real((Integer A))) / 10.00) x 360.00) degrees)
              • -------- Pick units and damage them --------
              • Unit Group - Pick every unit in (Units within ExFI_s_DistToTravell[CurrentIndex] of (Position of ExFI_s_Missile[CurrentIndex])) and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ((Picked unit) belongs to an enemy of (Owner of ExFI_s_Caster[CurrentIndex])) Equal to True
                      • ((Picked unit) is Magic Immune) Equal to False
                      • ((Picked unit) is in ExFi_s_AlreadyHit[CurrentIndex]) Equal to False
                    • Then - Actions
                      • -------- unit is hit -> damage it --------
                      • Unit - Cause ExFI_s_Caster[CurrentIndex] to damage (Picked unit), dealing 150.00 damage of attack type Spells and damage type Normal
                      • Unit Group - Add (Picked unit) to ExFi_s_AlreadyHit[CurrentIndex]
                      • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Weapons\RedDragonBreath\RedDragonMissile.mdl
                      • Special Effect - Destroy (Last created special effect)
                    • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ExFI_s_DistToTravell[CurrentIndex] Greater than or equal to 250.00
                • Then - Actions
                  • For each (Integer A) from 0 to 9, do (Actions)
                    • Loop - Actions
                      • Unit - Kill ExFI_s_NovaMissiles[((10 x CurrentIndex) + (Integer A))]
                  • Unit - Kill ExFI_s_Missile[CurrentIndex]
                  • -------- Spell finished --------
                  • Trigger - Run ExFi destroy <gen> (ignoring conditions)
                • Else - Actions
            • Else - Actions
              • -------- This instance is currently in the missile-phase --------
              • Unit - Move ExFI_s_Missile[CurrentIndex] instantly to ((Position of ExFI_s_Missile[CurrentIndex]) offset by 30.00 towards ExFI_s_Direction[CurrentIndex] degrees)
              • Set ExFI_s_DistToTravell[CurrentIndex] = (ExFI_s_DistToTravell[CurrentIndex] - 30.00)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ExFI_s_DistToTravell[CurrentIndex] Less than or equal to 0.00
                • Then - Actions
                  • -------- Target reached -> switch to nova-mode :D --------
                  • Set ExFI_s_NovaPhase[CurrentIndex] = True
                  • Set ExFI_s_DistToTravell[CurrentIndex] = 0.00
                  • Unit - Hide ExFI_s_Missile[CurrentIndex]
                  • For each (Integer A) from 0 to 9, do (Actions)
                    • Loop - Actions
                      • Unit - Create 1 Missile for (Owner of ExFI_s_Caster[CurrentIndex]) at (Position of ExFI_s_Missile[CurrentIndex]) facing (((Real((Integer A))) / 10.00) x 360.00) degrees
                      • Set ExFI_s_NovaMissiles[((10 x CurrentIndex) + (Integer A))] = (Last created unit)
                • Else - Actions
Its nearly the same method which wyrmlord explains in his tutorial, just a little bit more complicated because I do not like the 1 to 50 loop.
My method is closer to the jass code you would get if you used vJass.

PS: those triggers will leake like hell. I did not remove the leaks because removing leaks in GUI is so ugly.
 

Attachments

  • fireballspell_gui.w3x
    18.4 KB · Views: 44
Level 16
Joined
Mar 3, 2006
Messages
1,564
I have made it that way but ignore leaking for now.

My main problem is that I can't convert it to JASS as I lack the xp using it plus some variables I want to make them local but since I it involved in more than function I must make them udg; which means that the spell will be non-MUI.

  • Exploading Fireball
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Channel
    • Actions
      • Set TempPoint = (Position of (Casting unit))
      • Set target = (Target point of ability being cast)
      • Set facing = (Angle from TempPoint to target)
      • Unit - Create 1 missile effect for Player 1 (Red) at TempPoint facing facing degrees
      • Set temp_unit = (Last created unit)
      • Countdown Timer - Start tmissile as a Repeating timer that will expire in 0.02 seconds
  • Missile Effect
    • Events
      • Time - tmissile expires
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between (Position of temp_unit) and target) Less than or equal to 30.00
        • Then - Actions
          • Countdown Timer - Pause tmissile
          • Unit - Add a 0.10 second Generic expiration timer to temp_unit
          • For each (Integer A) from 1 to 180, do (Actions)
            • Loop - Actions
              • Unit - Create 1 Wispx for Player 1 (Red) at (target offset by ((Real(index)) x step) towards (2.00 x (Real((Integer A)))) degrees) facing (2.00 x (Real((Integer A)))) degrees
              • Set effect[(Integer A)] = (Last created unit)
          • Countdown Timer - Start tnova as a Repeating timer that will expire in 0.05 seconds
        • Else - Actions
          • Unit - Move temp_unit instantly to ((Position of temp_unit) offset by step towards facing degrees)
  • Nova Effect
    • Events
      • Time - tnova expires
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 180, do (Actions)
        • Loop - Actions
          • Unit - Move effect[(Integer A)] instantly to (target offset by ((Real(index)) x step) towards (2.00 x (Real((Integer A)))) degrees)
      • Unit Group - Pick every unit in (Units within ((Real(index)) x step) of target) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to G[index]
      • Unit Group - Remove all units of (Units within ((Real((index - 1))) x step) of target) from G[index]
      • Unit Group - Pick every unit in G[index] and do (Unit - Cause TestUnit to damage (Picked unit), dealing 75.00 damage of attack type Spells and damage type Fire)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Real(index)) x step) Greater than or equal to 200.00
        • Then - Actions
          • For each (Integer A) from 1 to 180, do (Actions)
            • Loop - Actions
              • Unit - Remove effect[(Integer A)] from the game
          • Countdown Timer - Pause tnova
          • Set index = 1
        • Else - Actions
          • Set index = (index + 1)
NOTE I am making this spell to be applied in a map so any help I would like to be in JASS and try avoiding vJASS as I don't understand it please
 
Status
Not open for further replies.
Top