HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[OLY] Flaming Arrow - Having Trouble

08-16-2008, 08:04 AM#1
Fulla
Flaming Arrow

Launches an arrow enchanted with fire, in an arc towards target point. Upon impact detonates damaging units in an AoE.

==

Anitarf helped me alot with this spell, now just trying to finish it. I'm having 2 problems:
  • The Arc is completely screwed, the projectile just trails along the ground. With debug msges the new Z I'm trying to set is constantly in the negative.
  • The speed the projectile travels at is screwed. At a round 0/180 agrees (sideways) it works fine, but shooting up/down, the speed increases immensely, where the eye can barely keep track of it.

Collapse JASS:
globals
    flamingarrowdata array FlamingArrowArray
    integer FlamingArrowTotal  = 0
    integer ABILITY_RAWCODE    = 'A002'
    real TIMER_INTERVAL        = 0.03
    real MISSILE_SPEED         = 900
    real MISSILE_GRAVITY       = 300
    real MISSILE_MINDIST       = 400
    real MISSILE_DAMAGE        = 100
endglobals

struct flamingarrowdata
    unit missile = null
    effect sfx = null
    integer level = 0
    real sx = 0
    real sy = 0
    real sz = 0
    real vx = 0
    real vy = 0
    real vz = 0
    real time = 0
    real duration = 0
endstruct

function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABILITY_RAWCODE
endfunction

function End takes unit u, integer level returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x, y))
endfunction

function Timer takes nothing returns nothing
    local flamingarrowdata dat
    local integer i = 0
    local integer aoa = 0
    local real z = 0
    loop
        exitwhen i >= FlamingArrowTotal
        set dat = FlamingArrowArray[i]
        set dat.time = dat.time + TIMER_INTERVAL
        set z = GetZ(GetUnitX(dat.missile), GetUnitY(dat.missile))
      //Move missile  
        call SetUnitX(dat.missile, dat.sx + dat.vx * dat.time) 
        call SetUnitY(dat.missile, dat.sy + dat.vy * dat.time)
      //Adjust height  
        set z = dat.sz + dat.vz * dat.time - MISSILE_GRAVITY * dat.time * dat.time / 2 - z
        call BJDebugMsg(R2S(z)) //Z is coming out in negative figures??
        call SetUnitFlyHeight(dat.missile, z, 0)
      //Adjust angle/facing
        set aoa = R2I(Atan2BJ(dat.vz -MISSILE_GRAVITY * dat.time, SquareRoot(dat.vx * dat.vx + dat.vy * dat.vy))) + 90 
        call SetUnitAnimationByIndex(dat.missile, aoa)
        
      //Has missile has reached its destination?  
        if dat.time >= dat.duration then
          //Add an explosion
            call End(dat.missile, dat.level)
          //Destroy everything  
            call DestroyEffect(dat.sfx)
            call KillUnit(dat.missile)
            set FlamingArrowTotal = FlamingArrowTotal - 1
            set FlamingArrowArray[i] = FlamingArrowArray[FlamingArrowTotal]
            call dat.destroy()
            set i = i - 1
        endif
        set i = i + 1
    endloop
    if FlamingArrowTotal==0 then
        call ReleaseTimer(GetExpiredTimer())
    endif  
endfunction

function Actions takes nothing returns nothing
    local flamingarrowdata dat = flamingarrowdata.create()
    local unit u = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real dx = GetLocationX(l) - GetUnitX(u)
    local real dy = GetLocationY(l) - GetUnitY(u)
    local real dz = GetLocationZ(l) - (GetUnitZ(u) + 100)
    local real dist = SquareRoot(dx * dx + dy + dy)
  //Minimum distance  
    if dist < MISSILE_MINDIST then
        set dx = dx * MISSILE_MINDIST / dist
        set dy = dy * MISSILE_MINDIST / dist
        set dist = MISSILE_MINDIST
    endi
  //Setup structs  
    set dat.missile = CreateUnit(GetOwningPlayer(u), 'hmil', GetUnitX(u), GetUnitY(u), Atan2BJ(dy, dx))
    set dat.sfx = AddSpecialEffectTarget(GetAbilityEffectById(ABILITY_RAWCODE, EFFECT_TYPE_MISSILE, 1), dat.missile, "origin")
    set dat.level = GetUnitAbilityLevel(u, ABILITY_RAWCODE)
    set dat.duration = dist / MISSILE_SPEED
    set dat.sx = GetUnitX(u)
    set dat.sy = GetUnitY(u)
    set dat.sz = GetUnitZ(u)
    set dat.vx = dx / dat.duration  
    set dat.vy = dy / dat.duration  
    set dat.vz = dz / dat.duration + MISSILE_GRAVITY * dat.duration / 2 
  //The Missile is shot/launched from 100 above the caster  
    call SetUnitFlyHeight(dat.missile, 100, 0)
    if FlamingArrowTotal == 0 then
        call TimerStart(NewTimer(), TIMER_INTERVAL, true, function Timer)
    endif
    set FlamingArrowArray[FlamingArrowTotal] = dat
    set FlamingArrowTotal = FlamingArrowTotal + 1
    call RemoveLocation(l)
    set u = null
endfunction

//===========================================================================
function InitTrig_Flaming_Arrow takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Actions)
endfunction
Attached Files
File type: w3xSpell 1.w3x (53.8 KB)
08-16-2008, 08:21 AM#2
Tide-Arc Ephemera
Well one thing I'd suggest trying is put

Collapse JASS:
      //Adjust height  
        set z = dat.sz + dat.vz * dat.time - MISSILE_GRAVITY * dat.time * dat.time / 2 - z

in brackets, so:

Collapse JASS:
      //Adjust height  
        set z = (dat.sz + dat.vz * dat.time - MISSILE_GRAVITY * dat.time * dat.time) / (2 - z)

Not sure if it still follows those stupid BODMAS rules though, (Brackets, Of, Division, Mulitplication etc)
08-16-2008, 08:35 AM#3
Fulla
Ok, I tried that but still getting negative Z's.
08-16-2008, 08:52 AM#4
Tide-Arc Ephemera
set z = GetZ(GetUnitX(dat.missile), GetUnitY(dat.missile))
By any chance are you working on the cliff height 2? That's got a Z of 128 as far as I know.
08-16-2008, 09:16 AM#5
Fulla
Oh thats a function I use, perhaps I should have included it:
Collapse JASS:
function GetZ takes real x, real y returns real
    local location l = Location(x, y)
    local real z = GetLocationZ(l)
    call RemoveLocation(l)
    return z
endfunction

function GetUnitZ takes unit u returns real
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real z = GetZ(x, y) + GetUnitFlyHeight(u)
    return z
endfunction

I just did a test incase, when casting an ability:
Collapse JASS:
    call BJDebugMsg(R2S(GetZ(GetUnitX(u),GetUnitY(u))))
    call BJDebugMsg(R2S(GetUnitZ(u)))

Both return 0, so seems to be ok.
08-16-2008, 10:10 AM#6
ToukoAozaki
Quote:
Originally Posted by Fulla
Oh thats a function I use, perhaps I should have included it:
Collapse JASS:
function GetZ takes real x, real y returns real
    local location l = Location(x, y)
    local real z = GetLocationZ(l)
    call RemoveLocation(l)
    return z
endfunction

function GetUnitZ takes unit u returns real
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real z = GetZ(x, y) + GetUnitFlyHeight(u)
    return z
endfunction

That may leak.

Collapse JASS:
function GetZ takes real x, real y returns real
    local location l = Location(x, y)
    local real z = GetLocationZ(l)
    call RemoveLocation(l)
    set l = null
    return z
endfunction

function GetUnitZ takes unit u returns real
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real z = GetZ(x, y) + GetUnitFlyHeight(u)
    return z
endfunction

More optimized version.

Collapse vJass:
library zlib initializer init // not a compression library!
    globals
        private location loc = null
    endglobals

    private function init takes nothing returns nothing
        set loc = Location(0,0)
    endfunction

    function GetZ takes real x, real y returns real
        call MoveLocation(loc, x, y)
        return GetLocationZ(loc)
    endfunction

    function GetUnitZ takes unit u returns real
        return GetZ(GetUnitX(u),GetUnitY(u)) + GetUnitFlyHeight(u)
    endfunction
endlibrary

Well, I suggest you to avoid locals.
08-16-2008, 11:18 AM#7
dorreen
Why dont you use this?
Collapse JASS:
globals
    private location l = Location(0.0,0.0)
endglobals

function GetZ takes real x, real y returns real
     call MoveLocation(l,x,y)
     return GetLocationZ(l)
endfunction
I would like to know if there is something bad about it, because I am usually using it.

EDiT. ey, sorry for useless post, I just read previous post.
08-16-2008, 11:19 AM#8
Anitarf
Quote:
Originally Posted by Tide-Arc Ephemera
in brackets, so:

Collapse JASS:
      //Adjust height  
        set z = (dat.sz + dat.vz * dat.time - MISSILE_GRAVITY * dat.time * dat.time) / (2 - z)

Not sure if it still follows those stupid BODMAS rules though, (Brackets, Of, Division, Mulitplication etc)
Don't go inserting random brackets into code you don't understand. What you have there makes no sense at all! I never thought an equation could be butchered beyond reckognition like that with just four brackets.


Fulla: first thing I noticed, you should fix this: set dat.sz = GetUnitZ(u)+100
Fix it and report back. Also, you should finally change that 100 into a PROJECTILE_LAUNCH_Z constant, it's not just so the spell is more calibratable, it also makes it easier to understand wtf is going on in the code for someone first reading it.

Also, you really need to put it all in a scope and make the functions properly private.
08-16-2008, 11:25 AM#9
Tide-Arc Ephemera
Quote:
Originally Posted by Anitarf
Don't go inserting random brackets into code you don't understand. What you have there makes no sense at all! I never thought an equation could be butchered beyond reckognition like that with just four brackets.

My apologies to both you and Fulla, but I misread it.

Also, while you're angered at me... does BODMAS still apply in Jass?
08-16-2008, 01:22 PM#10
Fulla
Ok, fixed all the reported bugs. Still same problems but a little better.
The arc works partially, but the projectile never goes up, just immediately descends (I even tried setting gravity to 10 down from 400, little difference).

I've tried making it a scope but then the spell completely stops working, I'll need to readup more in this. Then I can also get rid of the data arrays/totals.

===

Also I've been thinking:
- Since I'm now moving the projectile via velocity, couldn't time / duration be removed completely?
- Instead simply do a projectile Z to ground Z check, stopping projectile when ground is higher. Would make things easier?

New Code:
Collapse JASS:
globals
    flamingarrowdata array FlamingArrowArray
    integer FlamingArrowTotal       = 0
    
    integer ABILITY_RAWCODE         = 'A002'
    real TIMER_INTERVAL             = 0.03
    real MISSILE_LAUNCHZ            = 100
    real MISSILE_SPEED              = 900
    real MISSILE_GRAVITY            = 10
    real MISSILE_MINDIST            = 400
    real MISSILE_DAMAGE             = 100
endglobals

struct flamingarrowdata
    unit missile = null
    effect sfx = null
    integer level = 0
    real sx = 0
    real sy = 0
    real sz = 0
    real vx = 0
    real vy = 0
    real vz = 0
    real time = 0
    real duration = 0
endstruct

function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABILITY_RAWCODE
endfunction

function End takes unit u, integer level returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x, y))
endfunction

function Timer takes nothing returns nothing
    local flamingarrowdata dat
    local integer i = 0
    local integer aoa = 0
    local real z = 0
    loop
        exitwhen i >= FlamingArrowTotal
        set dat = FlamingArrowArray[i]
        set dat.time = dat.time + TIMER_INTERVAL
        set z = GetZ(GetUnitX(dat.missile), GetUnitY(dat.missile))
      //Move missile  
        call SetUnitX(dat.missile, dat.sx + dat.vx * dat.time) 
        call SetUnitY(dat.missile, dat.sy + dat.vy * dat.time)
      //Adjust height  
        set z = dat.sz + dat.vz * dat.time - MISSILE_GRAVITY * dat.time * dat.time / 2 - z
        call BJDebugMsg(R2S(z)) //Z is coming out in negative figures??
        call SetUnitFlyHeight(dat.missile, z, 0)
      //Adjust angle/facing
        set aoa = R2I(Atan2BJ(dat.vz -MISSILE_GRAVITY * dat.time, SquareRoot(dat.vx * dat.vx + dat.vy * dat.vy))) + 90 
        call SetUnitAnimationByIndex(dat.missile, aoa)
        
      //Has missile has reached its destination?  
        if dat.time >= dat.duration then
          //Add an explosion
            call End(dat.missile, dat.level)
          //Destroy everything  
            call DestroyEffect(dat.sfx)
            call KillUnit(dat.missile)
            set FlamingArrowTotal = FlamingArrowTotal - 1
            set FlamingArrowArray[i] = FlamingArrowArray[FlamingArrowTotal]
            call dat.destroy()
            set i = i - 1
        endif
        set i = i + 1
    endloop
    if FlamingArrowTotal==0 then
        call ReleaseTimer(GetExpiredTimer())
    endif  
endfunction

function Actions takes nothing returns nothing
    local flamingarrowdata dat = flamingarrowdata.create()
    local unit u = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real dx = GetLocationX(l) - GetUnitX(u)
    local real dy = GetLocationY(l) - GetUnitY(u)
    local real dz = GetLocationZ(l) - (GetUnitZ(u) + MISSILE_LAUNCHZ)
    local real dist = SquareRoot(dx * dx + dy + dy)
  //Minimum distance  
    if dist < MISSILE_MINDIST then
        set dx = dx * MISSILE_MINDIST / dist
        set dy = dy * MISSILE_MINDIST / dist
        set dist = MISSILE_MINDIST
    endif
  //Setup structs  
    set dat.missile = CreateUnit(GetOwningPlayer(u), 'hmil', GetUnitX(u), GetUnitY(u), Atan2BJ(dy, dx))
    set dat.sfx = AddSpecialEffectTarget(GetAbilityEffectById(ABILITY_RAWCODE, EFFECT_TYPE_MISSILE, 1), dat.missile, "origin")
    set dat.level = GetUnitAbilityLevel(u, ABILITY_RAWCODE)
    set dat.duration = dist / MISSILE_SPEED
    set dat.sx = GetUnitX(u)
    set dat.sy = GetUnitY(u)
    set dat.sz = GetUnitZ(u) + MISSILE_LAUNCHZ
    set dat.vx = dx / dat.duration  
    set dat.vy = dy / dat.duration  
    set dat.vz = dz / dat.duration + MISSILE_GRAVITY * dat.duration / 2 
  //The Missile is shot/launched from 100 above the caster  
    call SetUnitFlyHeight(dat.missile, 100, 0)
    if FlamingArrowTotal == 0 then
        call TimerStart(NewTimer(), TIMER_INTERVAL, true, function Timer)
    endif
    set FlamingArrowArray[FlamingArrowTotal] = dat
    set FlamingArrowTotal = FlamingArrowTotal + 1
    call RemoveLocation(l)
    set u = null
endfunction

//===========================================================================
function InitTrig_FlamingArrow takes nothing returns nothing
    set Trig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(Trig, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddCondition(Trig, Condition(function Conditions))
    call TriggerAddAction(Trig, function Actions)
endfunction

EDIT: Uploaded map just incase.
Attached Files
File type: w3xSpell 1.w3x (54.1 KB)
08-16-2008, 01:34 PM#11
darkwulfv
Just a suggestion, but maybe you could use a create method in your struct to clean up the code in actions? A large chunk of it seems to be just setting struct members. It won't solve your problem, but at least your code will look a little neater :D

Quote:
I've tried making it a scope but then the spell completely stops working, I'll need to readup more in this.
I used to have this problem. Make sure you either have a private init function and declare your scope like this:

scope Blah initializer Init Where Init is a function that creates your trigger (basically just make the "InitTrig_TriggerName" function into a private and rename it). OR, make the InitTrig_TriggerName function (the one Wc3 makes by default) a public function and name it "InitTrig". Finally, make sure your scope name and the name of the trigger match exactly and that there's no spaces.

And don't forget to make all your globals/functions in that scope private.

EXAMPLE:

Collapse JASS:
scope Hax initializer Init
globals
  private real blah = 2.4
  private constant integer TEST_INTEGER = 3
  private constant integer ABILITY_ID = 'A001'
endglobals

private function Conditions takes nothing returns boolean
  return GetSpellAbilityId() == 'A001'
endfunction

private function Actions takes nothing returns nothing
  local unit u = GetTriggerUnit()
  
  call KillUnit(u)
  set u = null
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
endfunction
endscope

Tada!
08-16-2008, 02:10 PM#12
Anitarf
Quote:
Originally Posted by Fulla
Ok, fixed all the reported bugs. Still same problems but a little better.
The arc works partially, but the projectile never goes up, just immediately descends (I even tried setting gravity to 10 down from 400, little difference).
You need to increase G to get a higher arc, not decrease it.

Quote:
Also I've been thinking:
- Since I'm now moving the projectile via velocity, couldn't time / duration be removed completely?
You're not, so no. In case you still don't understand fully how this works, it determines the starting conditions for the projectile (start position, starting speed) and then in the loop function calculates the current position based on starting conditions and time elapsed; so, you still need time to calculate the position, and you still need duration to know when the projectile hits. In my experience this is the simplest and the most accurate and efficient way to do a projectile like this.

Quote:
- Instead simply do a projectile Z to ground Z check, stopping projectile when ground is higher. Would make things easier?
No.
08-16-2008, 02:28 PM#13
Fulla
Ok converted to a Scope then, thx Wulf. Although the vjass/Scope spells I examined in the resource section didn't use/require "Intializer Init" after Scope like that.

===

With increasing the gravity, the arc is alot smoother, but it doesn't go up at all. This is what its meant to do:
Zoom
Instead it goes from 100 above caster Z > straight down. Sorry perhaps I didn't explain that properly at start.

Quote:
You're not, so no. In case you still don't understand fully how this works, it determines the starting conditions for the projectile (start position, starting speed) and then in the loop function calculates the current position based on starting conditions and time elapsed; so, you still need time to calculate the position, and you still need duration to know when the projectile hits. In my experience this is the simplest and the most accurate and efficient way to do a projectile like this.

Sorry let me try again.
If we have current projectile x/y/z AND Velocity x/y/z AND Gravity, would that not be sufficient to move a projectile & halt upon wall/ground collision?

===

The 2nd problem is still there, shooting spell in certain direction (down/up) is just horrific. I recommend testing map out to see.

Collapse JASS:
scope FlamingArrow initializer Init

globals
    flamingarrowdata array FlamingArrowArray
    integer FlamingArrowTotal       = 0
    
    private constant integer ABILITY_RAWCODE         = 'A002'
    private constant real TIMER_INTERVAL             = 0.03
    private constant real MISSILE_LAUNCHZ            = 100
    private constant real MISSILE_SPEED              = 900
    private constant real MISSILE_GRAVITY            = 500
    private constant real MISSILE_MINDIST            = 400
    private constant real MISSILE_DAMAGE             = 100
endglobals

struct flamingarrowdata
    unit missile = null
    effect sfx = null
    integer level = 0
    real sx = 0
    real sy = 0
    real sz = 0
    real vx = 0
    real vy = 0
    real vz = 0
    real time = 0
    real duration = 0
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABILITY_RAWCODE
endfunction

private function End takes unit u, integer level returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x, y))
endfunction

private function Timer takes nothing returns nothing
    local flamingarrowdata dat
    local integer i = 0
    local integer aoa = 0
    local real z = 0
    loop
        exitwhen i >= FlamingArrowTotal
        set dat = FlamingArrowArray[i]
        set dat.time = dat.time + TIMER_INTERVAL
        set z = GetZ(GetUnitX(dat.missile), GetUnitY(dat.missile))
      //Move missile  
        call SetUnitX(dat.missile, dat.sx + dat.vx * dat.time) 
        call SetUnitY(dat.missile, dat.sy + dat.vy * dat.time)
      //Adjust height  
        set z = dat.sz + dat.vz * dat.time - MISSILE_GRAVITY * dat.time * dat.time / 2 - z
        call BJDebugMsg(R2S(z)) //Z is coming out in negative figures??
        call SetUnitFlyHeight(dat.missile, z, 0)
      //Adjust angle/facing
        set aoa = R2I(Atan2BJ(dat.vz -MISSILE_GRAVITY * dat.time, SquareRoot(dat.vx * dat.vx + dat.vy * dat.vy))) + 90 
        call SetUnitAnimationByIndex(dat.missile, aoa)
        
      //Has missile has reached its destination?  
        if dat.time >= dat.duration then
          //Add an explosion
            call End(dat.missile, dat.level)
          //Destroy everything  
            call DestroyEffect(dat.sfx)
            call KillUnit(dat.missile)
            set FlamingArrowTotal = FlamingArrowTotal - 1
            set FlamingArrowArray[i] = FlamingArrowArray[FlamingArrowTotal]
            call dat.destroy()
            set i = i - 1
        endif
        set i = i + 1
    endloop
    if FlamingArrowTotal==0 then
        call ReleaseTimer(GetExpiredTimer())
    endif  
endfunction

private function Actions takes nothing returns nothing
    local flamingarrowdata dat = flamingarrowdata.create()
    local unit u = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real dx = GetLocationX(l) - GetUnitX(u)
    local real dy = GetLocationY(l) - GetUnitY(u)
    local real dz = GetLocationZ(l) - (GetUnitZ(u) + MISSILE_LAUNCHZ)
    local real dist = SquareRoot(dx * dx + dy + dy)
  //Minimum distance  
    if dist < MISSILE_MINDIST then
        set dx = dx * MISSILE_MINDIST / dist
        set dy = dy * MISSILE_MINDIST / dist
        set dist = MISSILE_MINDIST
    endif
  //Setup structs  
    set dat.missile = CreateUnit(GetOwningPlayer(u), 'hmil', GetUnitX(u), GetUnitY(u), Atan2BJ(dy, dx))
    set dat.sfx = AddSpecialEffectTarget(GetAbilityEffectById(ABILITY_RAWCODE, EFFECT_TYPE_MISSILE, 1), dat.missile, "origin")
    set dat.level = GetUnitAbilityLevel(u, ABILITY_RAWCODE)
    set dat.duration = dist / MISSILE_SPEED
    set dat.sx = GetUnitX(u)
    set dat.sy = GetUnitY(u)
    set dat.sz = GetUnitZ(u) + MISSILE_LAUNCHZ
    set dat.vx = dx / dat.duration  
    set dat.vy = dy / dat.duration  
    set dat.vz = dz / dat.duration + MISSILE_GRAVITY * dat.duration / 2 
  //The Missile is shot/launched from 100 above the caster  
    call SetUnitFlyHeight(dat.missile, 100, 0)
    if FlamingArrowTotal == 0 then
        call TimerStart(NewTimer(), TIMER_INTERVAL, true, function Timer)
    endif
    set FlamingArrowArray[FlamingArrowTotal] = dat
    set FlamingArrowTotal = FlamingArrowTotal + 1
    call RemoveLocation(l)
    set u = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    set Trig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(Trig, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddCondition(Trig, Condition(function Conditions))
    call TriggerAddAction(Trig, function Actions)
endfunction

endscope
Attached Files
File type: w3xSpell 1.w3x (54.2 KB)
08-16-2008, 03:02 PM#14
Anitarf
Change your gravity to something between 1000 and 2000 and fix this line: local real dist = SquareRoot(dx*dx + dy*dy)
08-16-2008, 03:18 PM#15
Fulla
Works perfectly now :) Haha, what a silly mistake. Thx alot for your help.
Now I'll attempt to fully vjass/scope it.

I edited the post above, probably as you replied but just wanted to ask:
If we periodically get the current projectile x/y/z AND the stored Velocity x/y/z AND the constant Gravity, would that not be sufficient to move a projectile & halt upon wall/ground collision?