HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

My missile function

02-18-2007, 01:21 PM#1
CommanderZ
I tried Daelins tut about deducting formulas. I applied the code well and it worked, but one thing irritated me a bit - the time of missile's flight is static and the speed is derived from distance to target. Nice for static targets, but terrible for moving ones as missile's speed increased when target was running away of caster or decreased when it was running towards him. I didn't find any other missile tuts, so I decided to write my own function. I utilized analythical geometry knowled we are just learning in school and produced this code:

Collapse JASS:
function H2I takes handle h returns integer
    return h
    return 0
endfunction

function I2H takes integer i returns handle
    return i
    return null
endfunction

function I2U takes integer i returns unit
    return i
    return null
endfunction

function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    return true
endfunction
function Missile_Move takes nothing returns nothing
    local gamecache gc=udg_gc
    local timer t = GetExpiredTimer()
    local unit m= I2U(GetStoredInteger(gc,I2S(H2I(t)), "missile"))
    local unit u= I2U(GetStoredInteger(gc,I2S(H2I(t)), "target"))

    local real rx        = GetUnitX(u)-GetUnitX(m) // relative x coord
    local real ry        = GetUnitY(u)-GetUnitY(m) // relative y coord
    
    local real d   = SquareRoot(rx*rx+ry*ry) // distance 
    
    local real left = d/(300*0.035) // get ratio = how big part of d will m travel this time
    
    call SetUnitX(m, GetUnitX(m)+rx/left) // adjust missile X pos
    call SetUnitY(m, GetUnitY(m)+ry/left) // adjust missile X pos      

    if d< 30 then  // m is nearer than 30 -> trigger explosion, damage or whatever I want
          //call SetUnitX(m, GetUnitX(u))
          //call SetUnitY(m, GetUnitY(u))
          call PauseTimer(t)
          call FlushStoredInteger(gc,I2S(H2I(t)), "missile")
          call FlushStoredInteger(gc,I2S(H2I(t)), "target")          
          call DestroyTimer(t)
          call RemoveUnit (m)
     endif
     set m = null
     set t = null
     set u = null
     set gc = null
endfunction          


function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local gamecache gc=udg_gc
    
    local unit c = GetSpellAbilityUnit() // c = caster
    local unit u = GetSpellTargetUnit()  // u = victim
    local unit m = CreateUnit(GetOwningPlayer(c), 'hrif', GetUnitX(c), GetUnitY(c), 0.00) // create dummy unit    m=missile

    local timer t = CreateTimer()
    call PingMinimapLocForPlayer(Player(0),GetUnitLoc(u),1)    
    call StoreInteger(gc,I2S(H2I(t)), "missile", H2I(m)) 
    call StoreInteger(gc,I2S(H2I(t)), "target", H2I(u))     

    call TimerStart(t, 0.035, true, function Missile_Move)

    set t = null
    set u = null 
    set m = null
    set c = null     
    set gc = null  
endfunction


//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition( gg_trg_Untitled_Trigger_001, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction

I find it simplier than daelin's one and the missile has fixed speed. Please check it and tell me if it is okay, if it doesn't leak etc. And don't bug me for JESP compliance

Thanks in advance
02-18-2007, 01:29 PM#2
Vexorian
hmmm, It can crash if it goes out of the map's bounds.

Optimizing the map makes 0 sense if you are still going to use the slowest and least secure storage method possible.

At least spell JESP correctly. Making there's no point in making something that is not a spell JESP compliant is sillyness incarnated.
02-18-2007, 02:19 PM#3
CommanderZ
The missile which chases its target can imo never get outside map bounds

Why is gamecache so slow and insecure? I was looking at KaTTaNa's Local Handle Variables, but I found it exactly the same as my solution. And other possibilities? There is CScache, structs and...anything else? I don't want (and to be honest, I cannot) use such complicated third party solutions

JESP...ok, I will JESP it. I just thought it is necessary for spells which are put for public use, but not for internal (and especially for such simple) testing spell.
02-18-2007, 04:30 PM#4
The)TideHunter(
structs and dynamic arrays are the way to go, but if you want to try out stuff and see if you know what your talking about, use gc to test, but to optimize, you should convert it into struct friendly code.
Its not to hard tbh, make a new struct called projectile or somethin, store or your variables there, the x, the y, the distance to target, the target, targets x, y etc and continue to use a timer to update, and you only need 1 gc call which will be to store the struct integer.
02-18-2007, 04:51 PM#5
CommanderZ
Okay, I will have a look at it. I tried to convert it to CSCache and better JESP compliance in the meantime.

Collapse JASS:
// spell config section
function missile_frequency takes nothing returns real
    return 0.035
endfunction

function missile_speed takes nothing returns real
    return 600
endfunction


// end of config section




function H2I takes handle h returns integer
    return h
    return 0
endfunction

function I2H takes integer i returns handle
    return i
    return null
endfunction

function I2U takes integer i returns unit
    return i
    return null
endfunction

function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    return true
endfunction
function Missile_Move takes nothing returns nothing
    //local gamecache gc=udg_gc
    local timer t = GetExpiredTimer()
    local unit m= GetAttachedUnit(t , "missile")
    local unit u= GetAttachedUnit(t , "target")

    local real rx        = GetUnitX(u)-GetUnitX(m) // relative x coord
    local real ry        = GetUnitY(u)-GetUnitY(m) // relative y coord
    
    local real d   = SquareRoot(rx*rx+ry*ry) // distance 
    
    local real left = d/(missile_speed()*missile_frequency()) // get ratio = how big part of d will m travel this time
    
    call SetUnitX(m, GetUnitX(m)+rx/left) // adjust missile X pos
    call SetUnitY(m, GetUnitY(m)+ry/left) // adjust missile X pos      

    if d< 30 then  // m is nearer than 30 -> trigger explosion, damage or whatever I want
          //call SetUnitX(m, GetUnitX(u))
          //call SetUnitY(m, GetUnitY(u))
          call PauseTimer(t)
          //call FlushStoredInteger(gc,I2S(H2I(t)), "missile")
          //call FlushStoredInteger(gc,I2S(H2I(t)), "target")          
          call DestroyTimer(t)
          call RemoveUnit (m)
     endif
     set m = null
     set t = null
     set u = null
endfunction          


function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    //local gamecache gc=udg_gc
    
    local unit c = GetSpellAbilityUnit() // c = caster
    local unit u = GetSpellTargetUnit()  // u = victim
    local unit m = CreateUnit(GetOwningPlayer(c), 'hrif', GetUnitX(c), GetUnitY(c), 0.00) // create dummy unit    m=missile

    local timer t = CreateTimer()
    call PingMinimapLocForPlayer(Player(0),GetUnitLoc(u),1)    
    call AttachObject(t, "missile", m) 
    call AttachObject(t, "target", u)     

    call TimerStart(t, missile_frequency(), true, function Missile_Move)

    set t = null
    set u = null 
    set m = null
    set c = null     
  
endfunction


//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition( gg_trg_Untitled_Trigger_001, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction


02-19-2007, 08:24 PM#6
CommanderZ
So, do you think I can use this in my spells wthout fearing of future problems?
02-19-2007, 08:47 PM#7
Pyrogasm
Quote:
Originally Posted by CommanderZ
JSEP
Quote:
Originally Posted by CommanderZ Again
JSEP
It's JESP.
02-19-2007, 10:40 PM#8
Vexorian
you don't really need structs and dynamic arrays, even static global array may work, although it all depends on how clean you want your code to look.

But, definitively, you shouldn't use H2I nor any system that calls it for this, typecasting is seriously unnecessary and if used incorrectly it brings issues so it is better to avoid it unless it is necessary to use it.
02-20-2007, 01:31 PM#9
CommanderZ
But all tuts use something I2H based :(

Are there ano tutorials on those struts or dynamic arrays? I haven't found any.

To Pyrogasm: thanks, corrected
02-20-2007, 07:55 PM#10
Joker
Whats so bad about H2I?
02-20-2007, 08:17 PM#11
Daelin
Of course the time is static, I designed the formula that way to make it super efficient (but lose the dynamic aspect). If you plan on making it dynamic, you'll have to change it a bit (and insert a distance formula between the missile and the target).

d = SquareRoot((x2-x1)^2+(y2-y1)^2) - classical formula. ^2 represents power, can be simplified without using Pow function. x2-x1 is Δx.

We will still work with proportions. We know that our missile has a certain speed in one second v, and frequency μ. It will still need to move at a distance of v*μ in a cycle. In the example I gave, that would be 800*0.035 which is 28.

Now back to proportions, we know that the current distance is d. So we can get the correct proportions on x and y like this:

d ................... v*μ
dx .......................... x+
dy ......................... y+

x+ = v*μ*dx/d
y+ = v*μ*dy/d

Hope the formula is right as I didn't test it. Let me know. ;)

-Daelin