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

[JASS] Fire Bomber

Status
Not open for further replies.
Level 29
Joined
Jul 29, 2007
Messages
5,174
I would have done it this way, it seems more effective to me, of course you don't have to use it or like it ^^

JASS:
function Trig_NewTrigger_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

function Trig_NewTrigger_Actions takes nothing returns nothing
    local unit whichUnit = GetTriggerUnit()
    local real a = GetUnitFacing(whichUnit) * bj_DEGTORAD
    local location l = GetSpellTargetLoc()
    local real x = GetLocationX(l) - 1550 * Cos(a)
    local real y = GetLocationY(l) - 1550 * Sin(a)
    local unit bomber = CreateUnit(GetOwningPlayer(whichUnit), 'h002', x , y, GetUnitFacing())
    local real orderx = GetLocationX(l) + 10000 * Cos(a)
    local real ordery = GetLocationY(l) + 10000 * Sin(a)
    local real unitspeed = GetUnitMoveSpeed(bomber)
    local integer i = 0          
    local unit bomb
    local real bombx
    local real bomby
    call UnitApplyTimedLife(bomber, 'BTLF', 15) 
    call IssuePointOrder( bomber, "move", orderx, ordery)
    call TriggerSleepAction(unitspeed/1300)
    loop
       exitwhen i > 6
       set bombx = GetUnitX(bomber)
       set bomby = GetUnitY(bomber)
       set bomb = CreateUnit(GetOwningPlayer(whichUnit), 'h003', bombx, bomby, 0) // angle doesn't matter since the bomb is pointing down
       call goingdown(bomb,10) // check my script below, 10 is actualy 50 per second because its number/0.02.
       set bomb = null
       set i = i+1
       call TriggerSleepAction(0.3)
    endloop
    set whichUnit = null
    call RemoveLocation(l)
    set l = null
    set bomber = null
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_NewTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(gg_trg_NewTrigger, Condition(function Trig_NewTrigger_Conditions))
    call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
endfunction

JASS:
//****************************************************************************************
//               Move unit's height with timers
// Usage: call goingdown(whichUnit,speed)
//
// PUT ME IN YOUR HEADER
// 
// This "system" just moves a unit height with timers (similiar to normal movement with timers  but with height instead of x,y)
//

function goingdowntimer takes nothing returns nothing
       local timer t = GetExpiredTimer()
       local unit whichUnit = GetHandleUnit(t, "whichUnit")
       local real speed = GetHandleReal(t, "speed")
       local real z = GetHandleReal(t, "z")
       local real whichUnitHeight = GetUnitFlyHeight(whichUnit)
       if whichUnitHeight > z+speed then
              call SetUnitFlyHeight(whichUnit, whichUnitHeight-speed, 20000)
       else
              call FlushHandleLocals(t)
              call DestroyTimer(t)
              call KillUnit(whichUnit)
       endif
       set t = null
       set whichUnit = null
endfunction
function goingdown takes unit whichUnit, real speed returns nothing
       local timer t = CreateTimer()
       local real x = GetUnitX(whichUnit)
       local real y = GetUnitY(whichUnit)
       local location whichUnitLocation = Location(x,y)
       local real z = GetLocationZ(whichUnitLocation) 
       call SetHandleHandle(t, "whichUnit", whichUnit)
       call SetHandleReal(t, "speed", speed)
       call SetHandleReal(t, "z", z)
       call TimerStart(t, 0.02, true, function goingdowntimer)
       set t = null
       set whichUnitLocation = null
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
(sorry I must double post, every time I edit a message, if it had any JASS tags they get ruined and deleted :S)

Oh didn't notice I leak that location, if you use it, before you remove "whichUnitLocation" (in the height code), remove it with

call RemoveLocation(whichUnitLocation)

And just an advice, make youself all kind of small codes (like movement with timers, distance between coordinates, and all kind of stuff like that), they really make it faster and more comfortable to make spells later on :)
 
Level 4
Joined
Dec 14, 2004
Messages
85
You don't use any extra locations with my code, you just use the same one that gets created anyways, coordinates are not more precise because a location is a coordinates. So if you use the move polar projection that I gave you then you don't have to use PolarProjectionBJ

BTW the caster system would probably be a huge help here too. You could probably even do it with a projectile. I like using CSCache a lot more than using HandleVars even though AttachableVars are basically the same thing, there are more options that go higher than just that in caster.

BTW still learning doesn't usually mean itself in a literal sense.
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
Tip: Use Atan2(spelly-castery,spellx-casterx) instead of GetUnitFacing(caster)
Because unit doesnt get faced to spell target loc instantly
[jass="like this"]local unit caster = GetTriggerUnit()
local location loc = GetSpellTargetLoc()
local real X = GetLocationX(loc)
local real Y = GetLocationY(loc)
local real RADangle = Atan2(Y-GetUnitY(caster),X-GetUnitX(caster))
local real DEGangle = RADangle*bj_RADTODEG
local player p = GetOwningPlayer(caster)
//Sorry was afk for one day
//you dont use Y actually
//Y + 0*Sin(whatever) will return Y, 0*blabla = 0 (learn maths)
local unit bomber = CreateUnit(p, 'h002', X - 600*Cos(RADangle), Y - 600 * Sin(RADangle), DEGangle)
call RemoveLocation(loc)
set loc = null // yes this is necessery
call IssuePointOrder( bomber, "move", X + 10000 * Cos(RADangle), Y + 10000 * Sin(RADangle))[/code]
 
Wolfy is rit, the angle is instant when the spell is cast. It is only a danger if I don't set it in in first place, which I do.

Wolf, getting a code divided into multiple functions, will not make the code slower ?! Because the trigger will have to access and the use the instruction. If the instruction is already in the code, then it will be easier.

This is about the processor, Fetch-decode-execute, the permanent cicle. If i create an extra function, I will require an extra line, and therefore and extra cicle to complete the instruction, which is slower.

Still, even I must admit that your idea is in deed an advantage in long term programming, and I may yet use it.

I will test the codes soon guys, and report you with more news.

Btw, do you guys now why the plane misses the target ?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Wolf, getting a code divided into multiple functions, will not make the code slower ?! Because the trigger will have to access and the use the instruction. If the instruction is already in the code, then it will be easier.

This is about the processor, Fetch-decode-execute, the permanent cicle. If i create an extra function, I will require an extra line, and therefore and extra cicle to complete the instruction, which is slower.

It will, but in terms of in-game playability, will it matter so much ?
It will however make it much easier and simpler to make further codes if you have all kind of basic codes.


Btw, do you guys now why the plane misses the target ?

At the most, it missed for me at about 60-80 range, I don't really see any reason why it should though, it was really wierd.


Oh and I have a mistake in my script (just a comment mistake), 10 is not 50, its 10x50=500 per second :p
 
Mmmm.
So, there is no solution to make the damn bomber hit the target ????

Maybe this approach is not the best =S
Your code does what my code does Wolf(I think, I have not tested it very well yet, but I will soon )

About game play, it will surely not be important if you play vs a computer, but in large multiplayer games, like my map, optimized code has an important role in reducing lag, and therefore it is of most importance.

Any other suggestions ?

PS, sry for late comment, was on busy for a while =P
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Try to use a angle not based on the caster's facing angle.
I just tried, but of course my WE crashed because WE sucks and I wanna go to sleep.

Use this in your header

JASS:
//****************************************************************************************
//               Angle between two points using coordinates
// call AngleBetweenPointsXY(real x1, real y1, real x2, real y2)

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


Then just give it the x,y of the point behind the caster and the x,y of the target location / the move issue location / the hero location, doesn't really matter.

For example:
JASS:
    local real x = GetLocationX(l) - 1550 * Cos(a)
    local real y = GetLocationY(l) - 1550 * Sin(a)
    local real orderx = GetLocationX(l) + 10000 * Cos(a)
    local real ordery = GetLocationY(l) + 10000 * Sin(a)
    local unit bomber = CreateUnit(GetOwningPlayer(whichUnit), 'h002', x , y, AngleBetweenPointsXY(x,y,orderx,ordery))

Good night.
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
Tip: when you order unit to move a large distance it moves in a different direction (fishy like "a" is your direction it moves a-45+random(0,90) it can get more fishier) I'd rather order periodicly

Whatever just wanted to post something :/
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
MMM, if it crashed on your WE, how do I know it will not crash my WE as well ??? lol...

Err... I guess you aren't working a lot with JASS in the WE ? it crashes randomly a lot of times lol.

And yes you could always do what Need_O2 said (moving with timers instead of ordering).
Or, Need_O2, did you mean ordering him every amount of time ? :huh: timers sound better to me.
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
No no I ment Order to move to a close distance wait some order to move the double distance
Ofcourse timers are better but as he mentioned before he doesnt want timers
 
Level 5
Joined
Aug 16, 2007
Messages
149
I don't see why you can't use this code to place the unit:
JASS:
local real angle = Atan2(<y of caster> - <x of spell>, <x of caster> - <y of spell>)
local real x = <x of spell> + 1550 * Cos(angle * bj_DEGTORAD)
local real y = <y of spell> + 1550 * Sin(angle * bj_DEGTORAD)
call CreateUnit(<casting player>,<dummy id>,x,y,angle-180)
all I've done is split up PolarProjectionBJ and AngleBetweenPoints into their component parts.
 
Wolf:
I have worked a lot with WE, and I know 1 thing: When it crashes is due Human error, as all programs in History. If it crashes because of 1 line in some code, it will crash for all WE's in the world, in that line, because there is an error there. Maybe it is not a syntax error, maybe it because the compiler of WE sux, maybe because the people who made JASS made lots of dummy mistakes, but it will crash.

Still thx for your help m8, I shall see your code anyway. Keep helping =)

O2:
Ahhh, I was getting worried with you. Good thing you made a post. Mmm, what you say may be interesting .... are you sure that really happens ?? Anyway, it makes perfect sense in this particular problem. I shall test Wolf's trigger, if it doesn't work, then I shall try your approach.

Bubba:
Well, no that doesn't work... I already tried to make that, and result is always bogus. That's is why I am here asking for help =)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Wolf:
I have worked a lot with WE, and I know 1 thing: When it crashes is due Human error, as all programs in History. If it crashes because of 1 line in some code, it will crash for all WE's in the world, in that line, because there is an error there. Maybe it is not a syntax error, maybe it because the compiler of WE sux, maybe because the people who made JASS made lots of dummy mistakes, but it will crash.

Actually thats not true.
A lot of times my WE crushed for no reason and when I opened it again and pasted my code without changes from JassCraft it saved and didn't do any problems.
WE just sucks, not JASS. lol.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
As I said: Human error. It may not be tour error, but from the people who made WE, but still, Human error. Also, JASS is not such a good language, it has many dummy mistakes and lots of dis vantages when compared to other languages(depending on the language you are comparing to).

You can't really compare JASS to other programming languages since its based on one of them (C++ if im not wrong).
It has a lot of err, how do you call them, inside-functions ? lol, anyway, it has a lot of functions we can't edit or delete, but thats because it was especialy made for warcraft, not for programming games in general.
Thats why you can call it less efficient then other languages, but as I said, you can't really compare it to them at all.

Just as an example ill take the KillUnit(...), from my own guess (don't sue me if im wrong lol) what it does is taking a variable that is the "life variable" of an object (that unit), and making it worth 0.00.
Another function tells the game that when an object has 0.00 life (actualy its like 0.45 but I don't know the real value), the game will make his death animation and remove him from the game.

We could make those functions alone basicly, but why bother since this is for a single game ? its not like we create new games (although if people have good imagination and knowledge, they can kind of create new games, take an example all the action games, they are sooooo not warcraft. The problem is the lag of course as warcraft was not meant for such games) so why bother giving us the full power of editing the game ?
 
I can =) in fact, I can compare to JAVA, per example. Why ?? Because I actually learned JAVA by using JASS =) .
JASS is a language, based in others, and so you can compare them, because they have something in common to be compared.

Now, back to the point:
Anyway, in your code; what do I put in Cos(a) ???
And what do I put in the AngleBetweenPoints ?!?!

JASS:
local unit caster = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    
    local real x = GetLocationX(l) - 1550 * Cos(a)
    local real y = GetLocationY(l) - 1550 * Sin(a)
    local real orderx = GetLocationX(l) + 10000 * Cos(a)
    local real ordery = GetLocationY(l) + 10000 * Sin(a)
    local unit bomber = CreateUnit(GetOwningPlayer(caster), 'h002', x , y, AngleBetweenPointsXY(x,y,orderx,ordery))

Here is what I did ... help plz..
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
"a" would be the angle between the hero and the target area.

You actualy don't really need the AngleBetweenPoints in the unit creation, you need it only in the "a" setting.

The AngleBetweenPointsXY, takes the coordinates of the first location (your hero's position), and the target coordinates, and sets the angle between them to your angle.

So, it actualy needs to be something like this:
JASS:
local unit u = GetTriggerUnit()
local unit bomber
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local location l = GetSpellTargetLoc()
local real targetx = GetLocationX(l)
local real targety = GetLocationY(l)
local real angle = AngleBetweenPointsXY(x,y,targetx,targety)
set real x = GetLocationX(l) - 1550 * Cos(angle)
set real y = GetLocationY(l) - 1550 * Sin(angle)
set bomber = CreateUnit(GetOwningPlayer(u), 'h002', x , y, angle)
// Order him to move with one order, or with a few like Need_O2 suggested
call RemoveLocation(l)
set l = null
set u = null
set bomber = null


Of course you need to add all the bombs part.
 
I am sorry to say that your code doesn't even compile ... and I don't know why .... It says "expected a variable name":

JASS:
function Trig_Bomber_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local unit bomber
    local real x = GetUnitX(caster)
    local real y = GetUnitY(caster)
    local location l = GetSpellTargetLoc()
    local real targetx = GetLocationX(l)
    local real targety = GetLocationY(l)
    local real angle = AngleBetweenPointsXY(x,y,targetx,targety)
    set real x = GetLocationX(l) - 1550 * Cos(angle)
    set real y = GetLocationY(l) - 1550 * Sin(angle)
    set bomber = CreateUnit(GetOwningPlayer(caster), 'h002', x , y, angle)
    // Order him to move with one order, or with a few like Need_O2 suggested
    call IssuePointOrder( bomber, "move", x + 1550 * Cos(angle * (3.14159 / 180.0)), y + 1550 * Sin(angle * (3.14159 / 180.0)))
    call RemoveLocation(l)
    set l = null
    set caster = null
    set bomber = null
endfunction

And in the header:
JASS:
function AngleBetweenPointsXY takes real x1, real y1, real x2, real y2 returns real  
        return bj_RADTODEG * Atan2(y2 - y1, x2 - x1) 
endfunction

So I really don't understand what is going on =S

I will try to make O2's way to see if it works

EDIT

Oh, I am getting angry with this ... it seems that O2's way doesn't work as well.

I used the following piece of code:
JASS:
local real d = 0
loop
    exitwhen(d == 1500)
    call IssuePointOrder( bomber, "move", X + 100 * Cos(angle * (3.14159 / 180.0)), Y + 100 * Sin(angle * (3.14159 / 180.0)))
    set d = d + 100
endloop

And it doesn't seem to be working as well. Again, when testing my spell, I jumped to a conclusion: I don't think that O2's post is the solution for the problem (not for now), because the error is when the plane is created (I think). When it is created in the correct position, it does his job well, when it is not, it just makes stupid stuff ...

PS: I am not sure if O2's solution will help, this doesn't mean that the solution itself doesn't work.

HELP !!! I am getting desperate !

EDIT

I sent a PM with the problem to O2. Do you want me to send a PM to you (wolf) as well ?

Excused is to say, if you guys help me solve this problem, you will certainly be credited in the spell, when I post it in the spells section.
If you guys can't find a easy way of doing it, I think I will be forced to ask PurplePoot =S
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I was going to go to sleep, but then I said "oh what the hell" and made it.

First thing - this WORKS ! I tested it and it works, if it doesn't work for you - its a problem with your implanting it to your map.

Now im sure the values won't fit your map (with mine he dropped the bombs behind the caster, the last one was exacly on the caster ^^) so change them as you will.

I didn't add a thing that will kill the bomber because I don't know what you want, you can check if you want when he gets out of the map bounds (it looks kinda stupid if a plain suddenly explodes in the sky) and then kill it.

The bombs currently die when they touch the ground so you can just make easly another trigger that triggers when a bomb-unit-type dies.

And without any more text, here's the code.

JASS:
function Trig_NewTrigger_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction
function killbomb takes nothing returns nothing
    local timer time = GetExpiredTimer()
    local unit bomb = GetHandleUnit(time, "bomb")
     call KillUnit(bomb)
    call FlushHandleLocals(time)
    call DestroyTimer(time)
    set time = null
    set bomb = null
endfunction
function bombertimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local timer time = CreateTimer()
    local unit bomber = GetHandleUnit(t, "bomber")
    local unit bomb
    local integer i = GetHandleInt(t, "i")
    local real angle = GetUnitFacing(bomber) * bj_DEGTORAD
    local real x = GetUnitX(bomber) + 250 * Cos(angle)
    local real y = GetUnitY(bomber) + 250 * Sin(angle)
    call IssuePointOrder(bomber, "move", x, y)
    if i >= 4 and i <= 8 then
        set x = GetUnitX(bomber)
        set y = GetUnitY(bomber)
        set bomb = CreateUnit(GetOwningPlayer(bomber), 'h001', x, y, 0)
        call SetUnitFlyHeight(bomb, 1, 500)
        call SetHandleHandle(time, "bomb", bomb)
        call TimerStart(time, 1, false, function killbomb)
    endif
    if i >= 12 then
         call FlushHandleLocals(t)
         call DestroyTimer(t)
    else
         call SetHandleInt(t, "i", i+1)
    endif
    set t = null
    set time = null
    set bomber = null
    set bomb = null
endfunction
function Trig_NewTrigger_Actions takes nothing returns nothing
   local timer t = CreateTimer()
   local unit whichUnit = GetTriggerUnit()
   local unit bomber
   local real x = GetUnitX(whichUnit)
   local real y = GetUnitY(whichUnit)
   local location l = GetSpellTargetLoc()
   local real targetx = GetLocationX(l)
   local real targety = GetLocationY(l)
   local integer i = 0
   local real angle = AngleBetweenPointsXY(x,y,targetx,targety)
   set x = x - 1500 * Cos(angle * bj_DEGTORAD)
   set y = y - 1500 * Sin(angle * bj_DEGTORAD)
   set bomber = CreateUnit(GetOwningPlayer(whichUnit), 'h000', x, y, angle)
   call SetHandleHandle(t, "bomber", bomber)
   call SetHandleInt(t, "i", i)
   call TimerStart(t, 1, true, function bombertimer)
   set t = null
   set whichUnit = null
   set bomber = null
   call RemoveLocation(l)
   set l = null
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_NewTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(gg_trg_NewTrigger, Condition(function Trig_NewTrigger_Conditions))
    call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
endfunction


As usuall this requires Kattana's local handle vars and my AngleBetweenPointsXY (angle between coordinates, I really think everyone should have one) code.
 
Meh ... Although that bomb thing may be just what I was needing, I must confess that this was not what I was expecting ....
Mainly for two reasons:
1 - To solve a damn direction problem, you remade the full spell, and used some system to complicated life.
2 - Well, now I don't understand a little thing of the code ... It's like I never saw it before ...

Although I must say thanks (Thx btw) by your effort, I must ask you, if there is a way out of this spell, without using Katana's system (btw, Where can I find it, and import it ?) and if there is a way outof this mess, without using timers .... (although timers are not such a big problem, Katana's Var system is =S)

I will still wait for O2's answer, and I will test your script as soon as I can can, and maybe change it (if I understand the code).
 
Level 11
Joined
Aug 25, 2006
Messages
971
The way I would do it would be using a linked list of structs and a continuous timer. Sorry timers are almost always a given. However the handlevar can be avoided. (As I said at the top of page 5) The handlevar system can be found at www.wc3jass.com
 
I don't refuse to learn. In fact I want to, but i can't !!! I can't find a good website that explains that sort of stuff ... they always give us some stupid example and then say "here is the code, the rest is your problem". And the I can't understand what they want me to do, or how they did it !

The only reason i hate those system is because i can NOT understand a single line of what they do !! besides, why complicate ? they are not needed ...

But please if you know of a DECENT tutorial about those crazy systems, plz let me know it ..
 
....... no comments ... I am testing your suggestions now O2 ...

EDIT

IT WORKS !!!! MUHAHAHAHAHHA HE NO LONGER MISSES THE TARGET !!!

DIRECTLY FROM THE BULLSEYE GNOMISH SCHOOL : BEHOLD, MY PLANE !!! LOL


PS: thx you so much the two of you. I am not using Wolf's version, although I may include it in my spell map, if he allows me to.
Now, I only need to know How to make those stupid bombs die !!!

Yes, I can't kill the bombs before they get to the ground, and I want the bombs to quit the plane in a succession (in an order, like it is happening now). So, this means that although i can drop 6 bombs, one after the other, I can't kill them instantly ...

Maybe I am not explaining myself correctly:
Here, just take my this code, and kill add a Kill Bomb call, to see what will happen (ps add the kill bomb in the bombs loop):

JASS:
globals
    trigger gg_trg_Bomber
endglobals
//=============================================================
function Trig_Bomber_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction
//=============================================================
function Trig_Bomber_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local real angle = GetUnitFacing(caster)
    local location loc = GetSpellTargetLoc()
    local real X = GetLocationX(loc) 
    local real Y = GetLocationY(loc)
    local player p = GetOwningPlayer(caster)
    local unit bomb
    local integer fade = 0
    local real height 
    local integer bombcounter = 0
    local real heightbomb
    
    local unit bomber = CreateUnit(p, 'h002', X - 1450 * Cos(angle * (3.14159 / 180.0)), Y - 1450 * Sin(angle * (3.14159 / 180.0)), angle)
    
    call SetUnitVertexColor(bomber, 255, 255, 255, fade)
    set height = GetUnitFlyHeight(bomber)
    
    call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))
    
    loop
        exitwhen(fade >= 255)
        call TriggerSleepAction(0.1)
        call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))
        set fade = fade + 30
        call SetUnitVertexColor(bomber, 255, 255, 255, fade)
    endloop
    
    loop 
        exitwhen(height <= 450)
        set height = height - 50
        call SetUnitFlyHeight(bomber, height, 80)
        call TriggerSleepAction(0.3)
        call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))
    endloop
    
        call TriggerSleepAction(0.6)
        call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))    
    loop 
        exitwhen(bombcounter == 6)
        call IssuePointOrder( bomber, "move", X + 500 * Cos(angle * (3.14159 / 180.0)), Y + 500 * Sin(angle * (3.14159 / 180.0)))        
        set bomb = CreateUnitAtLoc(p, 'h003', GetUnitLoc(bomber), 270.0)
        call SetUnitFlyHeight(bomb, height, 0)
        set heightbomb = height
        loop
            exitwhen(heightbomb <= 0)
            set heightbomb = heightbomb - 120
            call SetUnitFlyHeight(bomb, heightbomb, 120)
        endloop
        set bombcounter = bombcounter + 1
        call TriggerSleepAction(0.25)
    endloop
    
    call IssuePointOrder( bomber, "move", X + 2000 * Cos(angle * (3.14159 / 180.0)), Y + 2000 * Sin(angle * (3.14159 / 180.0)))
    call TriggerSleepAction(0.2)
        
    loop 
        exitwhen(height >= 600)       
        set height = height + 50
        call SetUnitFlyHeight(bomber, height, 100)     
        call TriggerSleepAction(0.2) 
    endloop
    
    loop
        exitwhen(fade <= 0)
        call TriggerSleepAction(0.1)
        
        set fade = fade - 30
        call SetUnitVertexColor(bomber, 255, 255, 255, fade)
    endloop
   
    call ShowUnit(bomber, false)
    call KillUnit(bomber)
    call RemoveLocation(loc)
    
    set loc = null
    set bomber = null
    set bomb = null
    set caster = null
    set p = null
endfunction
//===========================================================================
function InitTrig_Bomber takes nothing returns nothing
    set gg_trg_Bomber = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Bomber, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Bomber, Condition( function Trig_Bomber_Conditions ) )
    call TriggerAddAction( gg_trg_Bomber, function Trig_Bomber_Actions )
endfunction

EDIT

I've been studying how ghostwolf kills the bombs in his code. I must admit that it is quite interesting. He treats each bomb as a single object, and still there is no need for globals or such, thus making the spell MUI as well.

However, the use of that system complicates my life. That is why I will try to avoid it as much as possible. However, in the end, if I find no other solution, I will use his way of doing things.




EDIT EDIT EDIT EDIT EDIT EDIT EDIT EDIT EDIT EDIT

MEGA EDIT, GODLIKE EDIT, COMBO... EDIT !!!


Hey guys !!!
IT IS DONE !!! I DID IT (lol), although I must thx you for all your help.

I managed to make the bombs explode! now everything works in harmony !=P

I remembered: I need to kill the bombs, but how to do it ??? Well, the answer was simple: addLifeTime !! (lol)

So when the time expires, the bomb dies, and voilá ! BOM BOM BOM BOM BOM BOM (lol)

I know I managed to end the code, but I am still opened to suggestions about how to improve it (as long as it doesn't involve some system).
Here are the two trigger of the code:

[jass=Bomber]
function Trig_Bomber_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A000'
endfunction
//=============================================================
function Trig_Bomber_Actions takes nothing returns nothing
local unit caster = GetTriggerUnit()
local real angle = GetUnitFacing(caster)
local location loc = GetSpellTargetLoc()
local real X = GetLocationX(loc)
local real Y = GetLocationY(loc)
local player p = GetOwningPlayer(caster)
local unit bomb
local integer fade = 0
local real height
local integer bombcounter = 0
local real heightbomb

local unit bomber = CreateUnit(p, 'h002', X - 1450 * Cos(angle * (3.14159 / 180.0)), Y - 1450 * Sin(angle * (3.14159 / 180.0)), angle)

call SetUnitVertexColor(bomber, 255, 255, 255, fade)
set height = GetUnitFlyHeight(bomber)

call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))

loop
exitwhen(fade >= 255)
call TriggerSleepAction(0.1)
call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))
set fade = fade + 30
call SetUnitVertexColor(bomber, 255, 255, 255, fade)
endloop

loop
exitwhen(height <= 450)
set height = height - 50
call SetUnitFlyHeight(bomber, height, 80)
call TriggerSleepAction(0.3)
call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))
endloop

call TriggerSleepAction(0.6)
call IssuePointOrder( bomber, "move", X + 200 * Cos(angle * (3.14159 / 180.0)), Y + 200 * Sin(angle * (3.14159 / 180.0)))
loop
exitwhen(bombcounter == 6)
call IssuePointOrder( bomber, "move", X + 500 * Cos(angle * (3.14159 / 180.0)), Y + 500 * Sin(angle * (3.14159 / 180.0)))
set bomb = CreateUnitAtLoc(p, 'h003', GetUnitLoc(bomber), 270.0)
call SetUnitFlyHeight(bomb, height, 0)
set heightbomb = height
call UnitApplyTimedLife( bomb,'BHwe', 3)
loop
exitwhen(heightbomb <= 0)
set heightbomb = heightbomb - 100
call SetUnitFlyHeight(bomb, heightbomb, 140)
endloop
set bombcounter = bombcounter + 1
call TriggerSleepAction(0.25)
endloop

call IssuePointOrder( bomber, "move", X + 2000 * Cos(angle * (3.14159 / 180.0)), Y + 2000 * Sin(angle * (3.14159 / 180.0)))
call TriggerSleepAction(0.2)

loop
exitwhen(height >= 600)
set height = height + 50
call SetUnitFlyHeight(bomber, height, 100)
call TriggerSleepAction(0.2)
endloop

loop
exitwhen(fade <= 0)
call TriggerSleepAction(0.1)

set fade = fade - 30
call SetUnitVertexColor(bomber, 255, 255, 255, fade)
endloop

call ShowUnit(bomber, false)
call KillUnit(bomber)
call RemoveLocation(loc)

set loc = null
set bomber = null
set bomb = null
set caster = null
set p = null
endfunction
//===========================================================================
function InitTrig_Bomber takes nothing returns nothing
set gg_trg_Bomber = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Bomber, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Bomber, Condition( function Trig_Bomber_Conditions ) )
call TriggerAddAction( gg_trg_Bomber, function Trig_Bomber_Actions )
endfunction[/code]
This is the trigger for the plane. It creates the plane, makes him move and drop the bombs.

[jass=Bombs]
function Trig_Bombs_Actions takes nothing returns nothing
local unit bomb = GetDyingUnit()
local integer bombID = GetUnitTypeId(bomb)
local player p = GetOwningPlayer(bomb)
local unit f
local group targets
local unit dummy
local effect e
if bombID == 'h003' then
set e = AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", GetUnitX(bomb), GetUnitY(bomb))
set targets = CreateGroup()
call GroupEnumUnitsInRange( targets, GetUnitX( bomb ), GetUnitY( bomb ), 500, Filter(null) )
loop
set f = FirstOfGroup(targets)
exitwhen f == null
if IsUnitEnemy(f, p) then
call SetWidgetLife(f, GetWidgetLife(f) - 350)
endif
call GroupRemoveUnit(targets,f)
endloop
call DestroyGroup(targets)
call DestroyEffect(e)
endif
set bomb = null
set p = null
set f = null
set targets = null
set dummy = null
set e = null
endfunction
//===========================================================================
function InitTrig_Bombs takes nothing returns nothing
set gg_trg_Bombs = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Bombs, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction( gg_trg_Bombs, function Trig_Bombs_Actions )
endfunction[/code]

This is the trigger for my fire bomb !! Plz note, it is not done yet, the bomb will be an incendiary bomb, so when it explodes, it will leave the ground burning. I will create a dummy unit and a dummy ability to do so, but for now, I just want your opinion.


Its all for now =)
Thx for your help, now I can create any kind of bomb I want !!!
I am thinking of:
1 - Incendiary bomb: explodes and burns
2 - Ice bomb: The explosion deals ice damage (or freezes, dunno yet)
3 - Gas Bomb: my favorite, the exploding sound will be an Ogre fart (lol), and it will create a poison cloud based on Cloud (from the Elven Raider). Units inside that cloud will suffer of something (dunno yet lol).
4 - Atomic Bomb: this one is a Cliché for any bomber spell
5 - I am opened for more suggestions =)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
And he refuses to learn (as I did before)

I never refused to learn vJass, im just too lazy for it :p

PS: thx you so much the two of you. I am not using Wolf's version, although I may include it in my spell map, if he allows me to.

Allow ? lol I made it for you... (I was more expecting a "WOW THANKS THIS IS AWESOM" but whatever... *cries*... ^^).

I know I managed to end the code, but I am still opened to suggestions about how to improve it (as long as it doesn't involve some system).

Do you mean Kattana's handle local vars by "system" ? you really should learn how to use it (or use tables or structs or whatever...), moving locals from one function to another is defiantly a needed thing.
 
Allow ? lol I made it for you... (I was more expecting a "WOW THANKS THIS IS AWESOM" but whatever... *cries*... ^^).
Wolf, I appreciate greatly your help. Without you (and O2) I would have never succeeded.
However I will not use your code because:
1 - I discovered a way of using mine
2 - I find my code way easier
3 - I understand nothing of Katana's something something, and I make no idea on how to use it.

However, I also know you took great effort to help me and create that trigger. I don't forget that, and that's why i want to make good use of it: it would be a shame to let your work become unknown, after so much effort.

Do you mean Kattana's handle local vars by "system" ? you really should learn how to use it (or use tables or structs or whatever...), moving locals from one function to another is defiantly a needed thing.

Does Katana's something something allow me to move locals between different functions ?
I agree that is a major needing, at least for me. I get stuck most of the time, because i can't do that.
However, people say (including some expert people) that such system are not useful. You can do everything without them.
How is it going to be ? Who is rit ?
You seem to have experience with that system. Where can I read decent tutorials about it ??

Anyway, if you guys find an error in my code, or something that can be improved, please let me know. I will change it =) (maybe lol)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Does Katana's something something allow me to move locals between different functions ?
I agree that is a major needing, at least for me. I get stuck most of the time, because i can't do that.
However, people say (including some expert people) that such system are not useful. You can do everything without them.
How is it going to be ? Who is rit ?
You seem to have experience with that system. Where can I read decent tutorials about it ??

I can't see how you can move locals between functions without such things.
And I don't think there is a good tutorial anyway.

You kinda "stick" your local to a timer and then "summon" it back in the timer actions, something like this

JASS:
function timeractions takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit someUnit = GetHandleUnit(t, "someString") // here you use GET-handle-TYPE(use unit here, not handle),
    // you do not need to put the value since you already set it before
    //
    // do something
    //
    call FlushHandleLocals(t) // every time when you want to dostroy your timers, you'll need to delete the things 
    // you stuck into it with this command.
    call DestroyTimer(t)
    set t = null
    set someUnit = null
endfunction
function bla takes nothing returns nothing
    local timer t = CreateTimer()
    local unit someUnit = someUnit
    call SetHandleHandle(t, "someString", someUnit) // setting a unit is HandleHandle, integer is HandleInt, etc.
    // so, you "stick" it to your timer - t , you then give it a name you will call it with later, and a value so its
    // SetHandleVARIABLETYPE(yourTimer, "yourString", yourValue)
    // the types (as you can see in Kattana's script) are Handle(unit),Int,Real,Boolean,String.
    call TimerStart(t, 1, false, function timeractions)
    set t = null
    set someUnit = null
endfunction


Hope this helps.
 
Meh ... confusing ... I need timers, then I attach units to them, and then I kill Timers plus the units ... somewhat ... confusing ...

Anyway, Here is My incendiary Bomb spell !!!
It only has 1 level, because it is for an Item =P
Hope you like it =)

PS: because the effects take huge memory, it will lag if you mass use it, so be careful.

Description: A plane comes out of nowhere, and drops 6 bombs. Each bomb will deal 50 damage to units, and 75 to buildings. After the explosion, the ground will burn for 20 seconds, burning and killing all units on it.

Hope you like it, give suggestions =p

I use my code here, Wolfs code will be used in the map intent to submit to the spells section.
 

Attachments

  • Plane !.w3x
    93.1 KB · Views: 33
MM, i don't understand what you mean ... it would do the same in your code ... The plane goes where it has to, the problem is that he redirects his trajectory every loop. Instead of telling him where to go in 1 order, I do so in many little orders. It's like dividing his trajectory into small pieces, and then making the plane make those pieces nicely and correctly. I don't see what the problem is here. Besides I followed O2's suggestion =S

EDIT
Corrected that small location leak. Now I use GetUnitX and GetUnitY. thx =)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
This is what im talking about. It happend to me about 5/7 times.
 

Attachments

  • BLABLABLA.JPG
    BLABLABLA.JPG
    7.1 KB · Views: 130
OMG !, did you downloaded the map I posted today !? (lol you did).
That is freaking impossible. That has to be an error from your WE. With the new code, that never happened to me, never.

The closest thing I have to that, is the fact that sometimes (in the first 1 or 2 secs of life of the plane), the plane changes angle to go to where he has to.

That never happened to me while I was testing ... your report is certainly weird to me ....

Anyway, did you like the incendiary effect ?
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
I tested it again, its actualy like this.

It comes to the right spot from the wrong direction (which is way cooler lol ! :p).

About the bombs themselves - they fall toooooo slow.
And they lag tooooo much.
There is no point in a spell if it lags in 1-2 casts in single player in a map without doodads/units/anything.
 

Attachments

  • BLABLABLA.JPG
    BLABLABLA.JPG
    6.1 KB · Views: 119
Mmm, That is nearly impossible ... How can how target a location, if you are in the opposite angle ??! It's like me trying to slap some one behind me, I just can't (or shouldn't be able to).

About the lags, The lag is not caused by the code, It is caused by the effects .... Unfortunately, the effects take huge size of memory, and make the game lag.

If you have suggestions about how to reduce the lag of my spell, I would like very much to hear them please.

Although I could remove some effects ... but it wouldn't be the same thing if you understand me =S
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Mmm, That is nearly impossible ... How can how target a location, if you are in the opposite angle ??! It's like me trying to slap some one behind me, I just can't (or shouldn't be able to).

That is the start frame.
Try to cast behind the caster and see what happens.

About the lags, The lag is not caused by the code, It is caused by the effects .... Unfortunately, the effects take huge size of memory, and make the game lag.

I know, just remove some of the effects, it doesn't need to be super-effecty lol.


Just as a general feedback, it looks a bit stupid that the plain flies so low (500 is low...).
 
Mmmmm
After making some thinking, I decided to do some changes:
1 - The plane will not drop 6 bombs, but 5
2 - The bombs will no longer explode, they will just burn the ground
3 - I like the plane going down, it gives him a nice effect (lol). The plane starts with 600 height, and the it goes down until 450. I may change this value to 500 to see if it looks better
4 - I will replace the fire effect, with a dummy unit. This way I will be able to clear memory faster, because I don't have to wait 20 seconds.

Mm, yes, you are correct GhostWolf. If my caster casts the spell, from the opposite angle, the plane will still hit the target, but it will be created on the wrong angle.
If my code does it, your code will do it as well rit ?

I will now perform some of the changes. I will post the new map when I am done with it.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
You either set 2 locations to the target and the caster and check angle between them, or use a customized coordinates angle checker like this one

JASS:
//****************************************************************************************
//               Angle between two points using coordinates
// call AngleBetweenPointsXY(real x1, real y1, real x2, real y2)

function AngleBetweenPointsXY takes real x1, real y1, real x2, real y2 returns real
    return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
endfunction
 
Status
Not open for further replies.
Top