• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Ice Bomb

Status
Not open for further replies.
Hi guys. I am trying to create an ice bomb. When it lands it will slow down enemy units caught by it. I found a map made by Emil, Which is posted here.
However, my modifications didn't work very well.
My problem is creating the circle of frosts. It just doesn't create...
I will paste my code here:

JASS:
function IceBombs_Conditions takes nothing returns boolean  
    return GetUnitTypeId(GetTriggerUnit()) == 'h00D'  
endfunction
//===========================================================================
function IceBombs_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit() // the caster
    local unit ice // the dummy unit
    local integer i = 1 //GetUnitAbilityLevel(u, 'A005') //the level of the ability   
    local integer l = 4 + i * 1 //Number of nova rings    
    local integer m = 0 //counts how many rings were created
    local integer n = 50 //size of the dummy unit, where the unit will be created, cummulative size
    local integer o = 8 + i * 2  //Number of novas per ring
    local integer q = 0 //counts how many novas were created
    local integer r = 75 + i * 0 //Distance between rings
    local integer s = 360 / o    
    local real T = .07 - i * 0 //Wait between each ring
    local location L = GetUnitLoc(u)
    local player p = GetOwningPlayer(u)    
    local group g  //group that will select units and damage them
    local unit f  //first unit of group g
    local unit dum
    
    //this main loop counts how many rings were created
    loop
        set m = m + 1
        exitwhen m > l
        
        //This secondary loop counts how many ice effects exist per ring
        loop
            set q = q + 1
            exitwhen q > o            
            set ice = CreateUnitAtLoc(p, 'h00B', PolarProjectionBJ(L, n, ( s * I2R(q) )), bj_UNIT_FACING )
            call UnitApplyTimedLife( dum, 'BTLF', 1.00 )
            
            //this loop selects units near the ice effect and damages them
            set g = CreateGroup()
            call GroupEnumUnitsInRange(g, GetUnitX( dum ), GetUnitY( dum ), 50, Filter(null) )
            loop
                set f = FirstOfGroup(g)
                exitwhen (f == null)
                call GroupRemoveUnit(g, f)
                set dum = CreateUnit(p, 'h007', GetUnitX(f), GetUnitY(f), 0.0)
                call UnitAddAbility(dum, 'A00C')
                call IssueTargetOrder(dum, "frostnova", f)
                call UnitApplyTimedLife(dum, 'BTLF', 1.0)
            endloop
            call DestroyGroup(g)
            //end of selections and damaging part
            
        endloop
        call TriggerSleepAction( T )
        set q = 0 
        set n = n + r       
    endloop
   
    call RemoveLocation(L)
    set L = null
    set u = null
    set ice = null
    set g = null
    set p = null
endfunction    
//===========================================================================
function InitTrig_Ice_Bombs takes nothing returns nothing
    set gg_trg_Ice_Bombs = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Ice_Bombs, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Ice_Bombs, Condition( function IceBombs_Conditions ) )
    call TriggerAddAction( gg_trg_Ice_Bombs, function IceBombs_Actions )
endfunction

Down here you will find the Emil map i talked about.
Plz help. You shall be credited and receive +rep.
 

Attachments

  • emjlr3s JASS Spells 2.w3x
    102.1 KB · Views: 68
Gw !!! I don't damage and slow at the same time, I already Only use Frost Nova.
Also That code was changed from Emils map. So I actually need "i", wich I will change as soon as I can find what is wrong.

The problem is that I can't create the Nova Rings around the caster.
I can post My map here so you can see what is wrong.

News: I decided to post my map for you to have a better approach on the problem.
 

Attachments

  • JAss Plane !.w3x
    132.1 KB · Views: 52
Level 19
Joined
Aug 24, 2007
Messages
2,888
CreateUnit(balbalbalbalbalblabalbalbalbal, CenterX + <distance>*Cos((Q/MaxQ)*bj_PI*2),CenterY + <distance>*Sin((Q/MaxQ)*bj_PI*2),Facing to Hell)

MaxQ = o
and Q is loop counter (q)

Oups forgot to say its inside loop (LoL kidding)
 
Mmm, well I have a problem. The ice effects are not neing separated in order to form a "circle".

JASS:
function IceBombs_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'h00D'
endfunction
//===========================================================================
function IceBombs_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit() 
    local unit ice // the dummy unit
    local player p = GetOwningPlayer(u)
    local integer counter = 0
    local integer  counterMax = 5
    
    //This loop should creat unit in circle form
    loop
        exitwhen (counter > counterMax)
        set ice = CreateUnit(p, 'h00B', GetUnitX(u) + 100 * Cos((counter / counterMax) * bj_PI * 2), GetUnitY(u) + 100 * Sin((counter / counterMax) * bj_PI * 2), 0)
        call UnitApplyTimedLife( ice, 'BTLF', 1.00 )
        set counter = counter + 1
    endloop
    
    set u = null
    set ice = null
    set p = null
endfunction
//===========================================================================
function InitTrig_Ice_Bombs takes nothing returns nothing
    set gg_trg_Ice_Bombs = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Ice_Bombs, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Ice_Bombs, Condition( function IceBombs_Conditions ) )
    call TriggerAddAction( gg_trg_Ice_Bombs, function IceBombs_Actions )
endfunction

I did what you asked me to and still i have a problem. Can you guys help me out here ?

PS i attach the map so you all can see the problem.
 

Attachments

  • JAss Plane !.w3x
    130.7 KB · Views: 84
Level 12
Joined
Aug 20, 2007
Messages
866
Wait a second

Your trying to make a circle of units equidistant from the center???

That's exactly the same function I was asking about a few days back, here's the coding

JASS:
function Swarm takes player owner, integer unitid, real x, real y, real r, integer n returns nothing
    local real DegreesBetween = 360/n
    local real D=0
    loop
      exitwhen n==0
      set D = D + DegreesBetween
      call CreateUnit(owner, unitid, (x + (Cos(D * bj_DEGTORAD)*r)), (y + (Sin(D * bj_DEGTORAD)*r)), D - 180)
      set n = n - 1
    endloop
endfunction
owner = owner
unitid = unit's Id
x = X coordinate of center
y = Y coordinate of center
r = Distance from th center (radius)
n = Number of units in the swarm/circle

Just use this function, and it should work fine

You'd probably want it this way though

JASS:
function IceBombs_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local unit ice // the dummy unit
    local player p = GetOwningPlayer(u)
    local real D=0
    local integer n = 6 //Number of units in the circle
    local real DegreesBetween = 360/n
    loop
      exitwhen n==0
      set D = D + DegreesBetween
      set ice = CreateUnit(owner, unitid, (x + (Cos(D * bj_DEGTORAD)*r)), (y + (Sin(D * bj_DEGTORAD)*r)), D - 180)
      call UnitApplyTimedLife(ice, 'BTLF', 1.00)
      set n = n - 1
    endloop
    set u = null
    set ice = null
    set p = null
endfunction


I'm a little curious as to why (the counter/countermax * pi * 2) thing would work?
 
Last edited:
Hi, well "counter/countermax * pi * 2" is just the 360/n thing. It is similar I think ... or at least it was what I understood form O2's explication.

About your code, it just doesn't work properly =S
Here is what I did:

JASS:
function IceBombs_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()  //The dying unit
    local real X = GetUnitX(u)  //X from the position
    local real Y = GetUnitY(u) //Yfrom the position

    local unit ice // the dummy unit
    local player owner = GetOwningPlayer(u) //the owner of thedying unit
    local real D = 0     //I make no idea what this is
    local integer n = 6 //Number of units in the circle
    local real DegreesBetween = 360/n   //No idea
    local real r = 75 //distance from the center, Radius
    
    loop
      exitwhen (n == 0)
      set D = D + DegreesBetween
      set ice = CreateUnit(owner, 'h00B', (X + (Cos(D * bj_DEGTORAD)*r)), (Y + (Sin(D * bj_DEGTORAD)*r)), D - 180)
      call UnitApplyTimedLife(ice, 'BTLF', 1.00)
      set n = n - 1
    endloop
    
    set u = null
    set ice = null
    set owner = null
endfunction

However now the effects don't even show up =S
This still doesn't work !!
Any more suggestions plz ?

EDIT

Guys I found a new code for the circle !!!
However it was in GUI and so I am trying to convert it into an efficient version of jass ... but I need help !!
[jass=new code]function IceBombs_Actions takes nothing returns nothing
local unit u = GetTriggerUnit() //the dying unit
local unit ice //the ice effect
local player p = GetOwningPlayer(u)

//circle vars, this is when real action begins
local location tempPoint = GetUnitLoc(u)
local real i = 1 //counter
local real radiusLength = 400 // the radius of the circle
local real nUnits = radiusLength / 10 // the number of Units I the circle will have (continue)
//is automaticaly calculated by the CPU depending on the Radius of the circle (end)
local location tempPoint2 //a temporary loc for the ice

//the not efficient loop that will create the circle
loop
exitwhen (i > nUnits)
//the idea would be to eliminate the need for locations
//but I have trouble doing that ... so help!
set tempPoint2 = PolarProjectionBJ(tempPoint, radiusLength, ( i * ( 360.00 / ( radiusLength / 10.00 ) ) ))

set ice = CreateUnitAtLoc( p, 'h00B', tempPoint2, 0 )

call UnitApplyTimedLife(ice, 'BTLF', 1)
call RemoveLocation(tempPoint2)
set i = i + 1
endloop

//it's null time !
call RemoveLocation(tempPoint)
set tempPoint = null
set tempPoint2 = null
set u = null
set p = null
set ice = null
endfunction[/code]

Guys I would like to remove locations because they are slower and mean.
But I have trouble doing that ... can you guys help me plz ???
 
Last edited:
Level 12
Joined
Aug 20, 2007
Messages
866
Uh

I'm gonna explain the code that I sent you, because it was actually exactly what your looking for (a JASS system to make circles w/out locations)

Ok I'll expalian what each line does, but basically this is the literal way you calculate points of a circle

First, D = Current Degrees of the central angle for your new point
DegreesBetween = The number of degrees between each central angle, in other words, if there are 12 points, equally spaced, 360 degrees / 12 points = 30 degrees between each point

So, for each loop, the D gets set to the central angle for the next point
The next part for creating the unit, is again how you use Sin() and Cos() to get points of a circle, you seemed to have no idea how the math works, so I'll assume you haven't reached that point in mathematics (it's ok)

Basically, the Cos( degrees of the central angle) = distance from the center (in a unit of one), so you must multiply it by the radius (1*r = r), and add the X to move it to the correct X coordinate on the whole grid

Same thing happens with the Sin() and Y coordinate, again you don't need to know this yet, just understand that is how the system works
The last bit, "D-180" so the unit will face the center, just a visual so it looks like that point has just been swarmed

JASS:
function IceBombs_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()  //The dying unit
    local real X = GetUnitX(u)  //X from the position
    local real Y = GetUnitY(u) //Yfrom the position
    local unit ice  //the dummy unit
    local player owner = GetOwningPlayer(u) //the owner of thedying unit
    local real D = 0     //The "Degrees" variable, keeps track of the current central angle
    local integer n = 6 //Number of units in the circle
    local real DegreesBetween = 360/n   //# of degrees between each angle, is split depending on the # of units
    local real r = 75 //distance from the center, Radius
    loop
      exitwhen (n == 0) //This loop counts down rather than up, saves a variable
      set D = D + DegreesBetween //Set the central angle to the next point's central angle
      set ice = CreateUnit(owner, 'h00B', (X + (Cos(D * bj_DEGTORAD)*r)), (Y + (Sin(D * bj_DEGTORAD)*r)), D - 180) //Sets the unit variable, calculates the X,Y coords, and faces the unit inwards
      call UnitApplyTimedLife(ice, 'BTLF', 1.00) //Adds an expiration timer
      set n = n - 1 //The actual count downwards
    endloop
    set u = null //Nullifies the original unit variable
    set ice = null //Nullifies the dummy unit variable, not sure if this needs to be inside the loop
endfunction

The only reasons I can think of for this not working is either the trigger setup is messed up, 'h00B' might be incorrect, or I scrwed up either my math or Jass, hopefully the Jass, because that completely shake my entire foundation of mathematics


If your using this to make effects, not usable units, I would highly suggest using the special effects variables and functions, much easier and lags less (I believe)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I was too lazy to look at all the text, but your codes are wrong.

Polar movments work like this:
JASS:
x + number * Cos(angle * bj_DEGTORAD)
y + number * Sin(angle * bj_DEGTORAD)

Therefor, your circle should be something like this
JASS:
globals
     integer globangle = 60
endglobals
function blabla takes nothing returns nothing
     local unit u = GetTriggerUnit()
     local unit dummy
     local real ux = GetUnitX(u)
     local real uy = GetUnitY(u)
     local integer ablevel = GetUnitAbilityLevel(u, 'h000')
     local integer angle = globangle * ablevel
     local integer maxcounter = 360/angle
     local integer counter = 1
     local integer maxrings = ablevel * 2
     local integer rings = 0
     local real x
     local real y
     loop
        exitwhen rings == maxrings 
        loop
            exitwhen counter == maxcounter
            set dummy = CreateUnit(GetOwningPlayer(u), 'h000', ux, uy, 0)
            call IssuePointOrder(dummy, "dunno  string", x + counter * 100 * Cos(angle * counter * bj_DEGTORAD), y + counter * 100 * Sin( angle * counter * bj_DEGTORAD))
            call UnitApplyTimedLife(dummy, 'whatever', 1)
            set dummy = null
            set counter = counter + 1
        endloop
        set rings = rings + 1
     endloop
     set u = null
endfunction
And I just made it now in 2 seconds without looking at it so there are problably problems in it lol. Its just and example of how to use polar movement.
 
Herman, your code doesn't work =S it doesn't even create stuff ... and no, my rawcodes are all fine.
Also, my the code that uses locs works perfectly fine, however it is highly not efficient. About effects, they are slower and they have less interaction with the environment than units, which is important.

Any way, I make no idea why your code isn't working ... still thx on the help about the Cos and Sin =)

Wolf ... i have no words ... it just makes less sense then Herman's code (lol), you order units to cast stuff in a point and blarg.... you use vJass as well, which i can't (lol), but it isn't a great problem because that can be easily converted.

Now both codes don't work =S any help... any help on optimizing this one plz =s
JASS:
function IceBombs_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit() //the dying unit
    local unit ice //the ice effect
    local player p = GetOwningPlayer(u)
    
    //circle vars, this is when real action begins 
    local location tempPoint = GetUnitLoc(u)
    local real i = 1 //counter
    local real radiusLength = 400  // the radius of the circle
    local real nUnits = radiusLength / 10 // the number of Units I the circle will have (continue)
    //is automaticaly calculated by the CPU depending on the Radius of the circle (end)
    local location tempPoint2 //a temporary loc for the ice
    
    //the not efficient loop that will create the circle
    loop
        exitwhen (i > nUnits)
        //the idea would be to eliminate the need for locations
        //but I have trouble doing that ... so help! 
        set tempPoint2 = PolarProjectionBJ(tempPoint, radiusLength, ( i * ( 360.00 / ( radiusLength / 10.00 ) ) ))
        
        set ice = CreateUnitAtLoc( p, 'h00B', tempPoint2, 0 )
    
        call UnitApplyTimedLife(ice, 'BTLF', 1)
        call RemoveLocation(tempPoint2)
        set i = i + 1
    endloop
    
    //it's null time !
    call RemoveLocation(tempPoint)
    set tempPoint = null
    set tempPoint2 = null 
    set u = null
    set p = null
    set ice = null
endfunction
 
Level 12
Joined
Aug 20, 2007
Messages
866
Math

JASS:
(X + (Cos(D * bj_DEGTORAD)*r)) = x + number * Cos(angle * bj_DEGTORAD)

Just simplified differently

D = angle
JASS:
(X + (Cos(angle * bj_DEGTORAD)*r)) = x + number * Cos(angle * bj_DEGTORAD)

r = number
JASS:
(X + (Cos(angle * bj_DEGTORAD)*number)) = x + number * Cos(angle * bj_DEGTORAD)

Remove Parentheses
JASS:
X + Cos(angle * bj_DEGTORAD) * number = x + number * Cos(angle * bj_DEGTORAD)

PEMDAS, WarCraft does number * cos() first, not the other way around

So yeah, and at the same time the code I had original wrote works, I tested it out



I'm gonna upload a version that works, and you can put in from there the appropriate rawcodes (again, I don't know what the codes ar esuppsoed to be)




Btw, it's fun to kill the peasants xD
 

Attachments

  • Ice Bomb Trigger.w3x
    13.2 KB · Views: 107
Last edited:
Mmm, herman thx for your code. Somehow it doesn't work when I make an inversion ... strange ... Although your code forces me to choose how many units I need (which is a dis vantage in this case) it is a great code for other things and I may yet use it ) Thx for it =).

However I would still like to know if some1 could find a solution for my previous problem about the locs =s
 
Level 12
Joined
Aug 20, 2007
Messages
866
sorry bout the code

I apologize, you can edit it how ever you please with the units, just add a couple locals that will calculate the appropriate number of units (and the radius), if you'd like, I could create a formula for the code that will make a distance from the center based on the number of units + their collision sizes (that'd need to be inputed by you for the unit-type of the ice) so that they are never shifting eachothers positions

I hate to break it to you, but that code is the solution for it, granted there are about a trillion variations, but basically thats the fix to use coordinates rather than locations (<--accidentally wrote locals here, sorry)

If it's really too much to use the coordinates, as long as the function isn't being repeated 10x per second, you should be ok with the slowness (as long as you clear the leaks as well)
 
Last edited:
Level 12
Joined
Aug 20, 2007
Messages
866
It's ok

I should change it, about 6x when I looked at it I got confused and said, "wait what the hell?"

And then did the little algebra thing and said ohhhhh

I'm gonna start doin it the way it's shown all over, too many parentheses
(parenthesis or parentheses?)
 
MMmm, Herman, your code almost worked ... Although it is perfect for a 1st circle ring, it can not support a second 1... Somehow it only handles 6 units per circle and I make no idea why ...

However I need more then 6 units per circle ... Also I was forced to use an If in order to increase the variables which is stupid when you have a formulae and can't use it because it doesn't work somehow ....

I'll post the map and the code you can help a little ...
Here we see the advantage of the other code upon yours Herman, as it handles more then 6 units per circle .. somehow ..

JASS:
function IceBombs_Actions takes nothing returns nothing
    //vars related to the bomb
    local unit u = GetTriggerUnit()
    local real X = GetUnitX(u)
    local real Y = GetUnitY(u)
    local player owner = GetOwningPlayer(u)
    //vars for dummy units
    local unit ice
    local unit dum
    //cars for slecting and damaging units around ice
    local group g
    local unit f
    //vars to create a circle
    local real D = 0 //used to make unit face center of circle
    local integer n = 6 //number of ice units
    local real DegreesBetween = 360/n
    local real r = 0 //radius from the center
    //vars to create a Nth ring
    local integer nRings = 0
    local integer maxRings = 1
    
    loop
        exitwhen (nRings > maxRings )
        
        if nRings == 0 then
            set r = 100
            set n = 6
        elseif nRings == 1 then
            set r = 200
            set n = 12
        endif
        
        loop
            exitwhen n == 0
            set D = D + DegreesBetween
            set ice = CreateUnit(owner, 'h00B', (X + (Cos(D * bj_DEGTORAD) * r)), (Y + (Sin(D * bj_DEGTORAD) * r)), D - 180)
            call UnitApplyTimedLife(ice, 'BTLF', 1.00)
            
            //selects all enemy units in 100 from ice and casts frost nova on them
            set g = CreateGroup()
            call GroupEnumUnitsInRange( g, X, Y, 150, Filter(null) )
            loop
                set f = FirstOfGroup(g)
                exitwhen (f == null)
                call GroupRemoveUnit(g,f)
                if IsUnitEnemy(f, owner) then
                    set dum = CreateUnit(owner, 'h007', GetUnitX(f), GetUnitY(f), 0)
                    call UnitAddAbility(dum, 'A00C')
                    call IssueTargetOrder(dum, "frostnova", f)
                    call UnitApplyTimedLife(dum, 'BTLF', 1.0)
                endif
            endloop
            call DestroyGroup(g)
            set g = null
            //end of damaging part
            
            set n = n - 1
        endloop
        
        call TriggerSleepAction(0.7)
        set nRings = nRings + 1
    endloop
    
    set dum = null
    set ice = null
    set u = null
    set owner = null
endfunction

and now the map ... =S
 

Attachments

  • JAss Plane !.w3x
    132 KB · Views: 58
Level 12
Joined
Aug 20, 2007
Messages
866
Ok

I overviewed your trigger, there are a few things about that need to change
I don't have the time right now, I might be able to get to it later, but it gets a little complicated when you wanna loop rings rather than just the units in the ring

I also put in some notes about the radians and degrees
it is much more efficient (and accurate) to use radians and the bj_DEGTORAD, bj_RADTODEG in wc because pi is a very odd number, and WC has already been programmed with a function for it (the two bj_'s)

At the same time, constantly converting between radians and degrees is really inefficient and could be taken care of by just using radians

Heres what I got so far....
 

Attachments

  • JAss Plane ! Edited.w3x
    132.1 KB · Views: 65
MMm Herman, so far your opt doesn't work at all =S What's happening !?
Plz post as soon as you have time.
Also, The MaxRings var should have not been deleted, you see, it is a good programming practice to avoid "magic numbers". What are magic numbers ?? Magic numbers are numbers that appear in code, but you don't know what they represent.
You may know what they are, but other people will have trouble understanding it.

Also, it will be more difficult for newbies to change if they need.
Therefore i believe keeping that var is a good thing.

Still .... is it a JASS bug ?
 
Level 12
Joined
Aug 20, 2007
Messages
866
Ok

Well, I finished it, btw, it didn't work the first time because I actually did not even touch the Ice Bombs trigger

I think the bombing run is off, but gives it a kind of ww2 "it's not a smart bomb" kind of feel to it

From the modifications I put in it looks ok to me, although you definitely need to read the notes, as there may be some conflict as to how you wanted the damage to be calculated

It looks pretty cool at 2 rings, if you wanna do 3 rings it might be a bit over the edge with the effects, but it will still work
 

Attachments

  • JAss Plane ! Edited2.w3x
    133.5 KB · Views: 47
Status
Not open for further replies.
Top