• 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.

Help With Projectile/Missile system math formule

Status
Not open for further replies.
Level 17
Joined
Nov 13, 2006
Messages
1,814
so question who can i do this what is on picture, because i want make a missile engine what could make many movement style, atm only parabola and arc thing work

[trigger still just on test phase, this is why dont work the deallocate part]

B. also question the best way for accelerating missile thing, atm i got only a ideea about minSpeed, MaxSpeed, AccRate, i allways add accrate to speed till it reach max speed, have better way?)

C. how can i make homing missile what follow the target and i want parabola/arc style, if distance between target and missile changed each time, then i cant set the max distance what is based in both parabola/arc calculation because when target move then max distance also changed



JASS:
function Missile takes unit launcher, unit target, real collision, real x1, real y1, real x2, real y2, real speed, real maxspeed, real accelerate, real arc, real arcdist, boolean parabola, real height, real dmg1, real dmg2, real aoe, real dmg3, boolean homing returns nothing
    local integer i
    local real dx = x2 - x1
    local real dy = y2 - y1

    set udg_MS_Index = udg_MS_Index + 1
    set i = udg_MS_Index

    set udg_MS_X[i] = x1
    set udg_MS_Y[i] = y1
    set udg_MS_Angle[i] = Atan2(y2 - y1, x2 - x1)
    set udg_MS_MaxDist[i] = SquareRoot(dx * dx + dy * dy)
    set udg_MS_Speed[i] = speed
    set udg_MS_Launcher[i] = launcher

    if arc != 0 then
        set udg_MS_ArcDist[i] = arcdist
        set udg_MS_ArcAngle[i] = udg_MS_Angle[i] + arc
        set udg_MS_Arc[i] = true
    else
        set udg_MS_ArcDist[i] = 0
        set udg_MS_ArcAngle[i] = 0
        set udg_MS_Arc[i] = false
    endif

    if parabola then
        set udg_MS_MaxHeight[i] = height
        set udg_MS_Parabola[i] = true
    else
        set udg_MS_MaxHeight[i] = 0
        set udg_MS_Parabola[i] = false
    endif

    if speed != maxspeed then
        set udg_MS_MaxSpeed[i] = maxspeed
        set udg_MS_Accelerate[i] = accelerate
        set udg_MS_SpeedUp[i] = true
    else
        set udg_MS_SpeedUp[i] = false
        set udg_MS_MaxSpeed[i] = 0
        set udg_MS_Accelerate[i] = 0
    endif

    if dmg1 != 0 then
        set udg_MS_Dmg_On[i] = true
        set udg_MS_Dmg[i] = dmg1
        set udg_MS_Collision[i] = collision
    else
        set udg_MS_Dmg_On[i] = false
        set udg_MS_Dmg[i] = 0
        set udg_MS_Collision[i] = 0
    endif

    if dmg2 != 0 then
        set udg_MS_Dmg_Ex_On[i] = true
        set udg_MS_Aoe_Dmg[i] = dmg2
        set udg_MS_Dmg_Area[i] = aoe
    else
        set udg_MS_Dmg_Ex_On[i] = false
        set udg_MS_Aoe_Dmg[i] = 0
        set udg_MS_Dmg_Area[i] = 0
    endif

    set udg_MS_Dmg_Ex[i] = dmg3

    if homing then
        set udg_MS_Homing_Target[i] = target
        set udg_MS_Suicide[i] = true
    else
        set udg_MS_Homing_Target[i] = null
        set udg_MS_Suicide[i] = false
    endif

    set udg_MS_Player[i] = GetOwningPlayer(launcher)
    set udg_MS_Homing[i] = homing
    set udg_MS_Unit[i] = CreateUnit(Player(15), 'ewsp', x1, y1, 0)
    call UnitAddAbility( udg_MS_Unit[i], 'Arav' )
    call UnitRemoveAbility( udg_MS_Unit[i], 'Arav' )

endfunction

JASS:
function Trig_Missile_Timer takes nothing returns nothing
    local integer i = 1
    local real x
    local real y
    local real nx
    local real ny
    local real r1
    local real ang

    loop
        exitwhen i > udg_MS_Index

        if udg_MS_CurDist[i] >= udg_MS_MaxDist[i] then
            call RemoveUnit(udg_MS_Unit[i])
            if i != udg_MS_Index then
                set udg_MS_Unit[i] = udg_MS_Unit[udg_MS_Index]
                set udg_MS_Homing_Target[i] = udg_MS_Homing_Target[udg_MS_Index]
                set udg_MS_Launcher[i] = udg_MS_Launcher[udg_MS_Index]
                set udg_MS_Player[i] = udg_MS_Player[udg_MS_Index]
                set udg_MS_X[i] = udg_MS_X[udg_MS_Index]
                set udg_MS_Y[i] = udg_MS_Y[udg_MS_Index]
                set udg_MS_Homing[i] = udg_MS_Homing[udg_MS_Index]
                set udg_MS_MaxHeight[i] = udg_MS_MaxHeight[udg_MS_Index]
                set udg_MS_SpeedUp[i] = udg_MS_SpeedUp[udg_MS_Index]
                set udg_MS_Accelerate[i] = udg_MS_Accelerate[udg_MS_Index]
                set udg_MS_Speed[i] = udg_MS_Speed[udg_MS_Index]
                set udg_MS_MaxSpeed[i] = udg_MS_MaxSpeed[udg_MS_Index]
                set udg_MS_CurDist[i] = udg_MS_CurDist[udg_MS_Index]
                set udg_MS_MaxDist[i] = udg_MS_MaxDist[udg_MS_Index]
                set udg_MS_Arc[i] = udg_MS_Arc[udg_MS_Index]
                set udg_MS_Parabola[i] = udg_MS_Parabola[udg_MS_Index]
                set udg_MS_ArcAngle[i] = udg_MS_ArcAngle[udg_MS_Index]
                set udg_MS_Angle[i] = udg_MS_Angle[udg_MS_Index]
                set udg_MS_Collision[i] = udg_MS_Collision[udg_MS_Index]
                set udg_MS_Suicide[i] = udg_MS_Suicide[udg_MS_Index]
                set udg_MS_Dmg_Ex_On[i] = udg_MS_Dmg_Ex_On[udg_MS_Index]
                set udg_MS_Dmg_On[i] = udg_MS_Dmg_On[udg_MS_Index]
                set udg_MS_Dmg[i] = udg_MS_Dmg[udg_MS_Index]
                set udg_MS_Dmg_Area[i] = udg_MS_Dmg_Area[udg_MS_Index]
                set udg_MS_Dmg_Ex[i] = udg_MS_Dmg_Ex[udg_MS_Index]
                set udg_MS_Dmg_Ex[i] = udg_MS_Dmg_Ex[udg_MS_Index]
            endif

            set i = i - 1
            set udg_MS_Index = udg_MS_Index - 1

        else

            set x = GetUnitX(udg_MS_Unit[i])
            set y = GetUnitY(udg_MS_Unit[i])

            if udg_MS_Homing[i] then
                   
            endif

            if udg_MS_SpeedUp[i] then
                if udg_MS_Speed[i] < udg_MS_MaxSpeed[i] then
                    set udg_MS_Speed[i] = udg_MS_Speed[i] + udg_MS_Accelerate[i]
                endif
            endif

            set udg_MS_CurDist[i] = udg_MS_CurDist[i] + udg_MS_Speed[i]

            if udg_MS_Arc[i] then

                set r1 = ( 4 * udg_MS_ArcDist[i] / udg_MS_MaxDist[i] ) * ( udg_MS_MaxDist[i] - udg_MS_CurDist[i] ) * ( udg_MS_CurDist[i] / udg_MS_MaxDist[i] )

                set nx = udg_MS_X[i] + udg_MS_Speed[i] * Cos(udg_MS_Angle[i])
                set ny = udg_MS_Y[i] + udg_MS_Speed[i] * Sin(udg_MS_Angle[i])
                set nx = nx + r1 * Cos(udg_MS_ArcAngle[i])
                set ny = ny + r1 * Sin(udg_MS_ArcAngle[i])
                call SetUnitX(udg_MS_Unit[i], nx)
                call SetUnitY(udg_MS_Unit[i], ny)
                set ang = Atan2(ny - udg_MS_Y[i], nx - udg_MS_X[i])
                call SetUnitFacing(udg_MS_Unit[i], ang)
                set udg_MS_X[i] = udg_MS_X[i] + udg_MS_Speed[i] * Cos(udg_MS_Angle[i])
                set udg_MS_Y[i] = udg_MS_Y[i] + udg_MS_Speed[i] * Sin(udg_MS_Angle[i])
            else
                call SetUnitX(udg_MS_Unit[i], (x + udg_MS_Speed[i] * Cos(udg_MS_Angle[i])))
                call SetUnitY(udg_MS_Unit[i], (y + udg_MS_Speed[i] * Sin(udg_MS_Angle[i])))
            endif

            if udg_MS_Parabola[i] then
                set r1 = ( 4 * udg_MS_MaxHeight[i] / udg_MS_MaxDist[i] ) * ( udg_MS_MaxDist[i] - udg_MS_CurDist[i] ) * ( udg_MS_CurDist[i] / udg_MS_MaxDist[i] )
                call SetUnitFlyHeightBJ( udg_MS_Unit[i], r1, 0.00 )

            endif
        endif

        set i = i + 1
    endloop

endfunction

//===========================================================================
function InitTrig_Missile_Timer takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent( t, 0.03, true)
    call TriggerAddAction( t, function Trig_Missile_Timer )
endfunction

formula.JPG


i am really curios how possible change the arrow faceing angle like here http://www.youtube.com/watch?v=phKhzxjLw_c&feature=player_embedded#!
 
Last edited:
Level 7
Joined
Jan 28, 2012
Messages
266
for the first one, its easy you just have the projectile gain height for a couple of seconds, and then it begins descending, so you would start it with, initial upwards velocity of some constant, and then give it a small negative acceleration based off of the distance to target and the height of target, Now i will give the technical description.

Here is a list of the constants you will need to do this,
D, distance to target
S, speed traveled in a non vertical manner, this is a constant.
T, = D/S


HDif, height of target(HoT)- height of you,

ApexHeight, this is how much higher then then you, you want to be, a constant.
MaxHeight, if HDif is negitive then this is ApexHeight, if it is positive it is ApexHeight+HDif

Initial Upwards Velocity(IUV), this is the initial velocity all projectiles will have. a constant
Initial Deceleration(ID), a constant, this is a negative number, if it isn't well you'll have problems
TimeTillApex(TTA) = (Sqrt(IUV^2 - 4*ID*MaxHeight)-IUV)/2*ID

set Constant Vertical Acceleration After Apex(CVAA) = (HoT-MaxHeight)/((D-S*TTA)/S)


here is how it would look in jass, NOTE: some of the functions are not defined.
also, the example gives everything in units Per Second not per Warcraft standard loop time(0.0325000 seconds)

JASS:
 function SetProjectileSpeed takes unit target, unit Launcher returns nothing
    local integer HoT = GetUnitHeight(target)// this is just a function that getslocationz and unit flying height and returns the units true height
    local integer D = GetDistanceBetweenUnits(target,Launcher)// just does Sqrt((xt-xL)^2+(yt-yL)^2)
    local integer T = D/1000 // or in other words S this is a constant for the unit type)
    local integer HDif = HoT-GetUnitHeight(Launcher)
    local integer MaxH
    

    if HDif <= 0 then
         set MaxH = 400// i am using 400 as ApexHeight
    else
         set MaxH = 400+HDif
    endif
    set ProjectileZVel[ProjectilesIndex] = 800*.03
    set TTA[ProjectilesIndex] = Sqrt(800^2 - 4*100*MaxH)-800)/2*100// note in my example 800 hundred is Initial Upwards Velocity NOTE: TTA is a global, and if you use Jass it will have an udg_ infront, and you probably will want to use a longer name
    set CVAAA[ProjectileIndex] = (HoT-MaxH)/((D-S*TTA[ProjectilesIndex])/S)//CVAAA is a global, and if you use Jass it will have an udg_ infront, and you probably will want to use a longer name
endfunction

then in your movement loop you will have it
JASS:
function periodic_Missile_Movement takes nothing returns nothing
      //
      //
      if TTA[ProjectilesIndex>0 then
      set TTA[ProjectilesIndex] = TTA[ProjectilesIndex]-.03
           call SetUnitFlyingHeight(Projectile[ProjectilesIndex],GetUnitHeight(Projectile[ProjectilesIndex])+ProjectileZVel[ProjectilesIndex])
           set ProjectileZVel = ProjectileZVel[ProjectilesIndex]-3//100*.03
      else
          call SetUnitFlyingHeight(Projectile[ProjectilesIndex],GetUnitHeight(Projectile[ProjectilesIndex])+CVAAA[ProjectileIndex])
      endif
endfunction

about how to change the vertical facing, i think there is a model that can do that(made by vexorian), thought this might work too.
SetUnitLookAt takes unit whichUnit, string whichBone, unit lookAtTarget, real offsetX, real offsetY, real offsetZ returns nothing

also please note that some of the information a gave may not be exactly how you would do it(i haven't tested it yet) you might have to change a negitive sign here and there.

p.s the path you are describing is not parabolic, ie something that can be described in a quadratic equation.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
i got something, what work at moment(aftye alot googleing because most of formule just make the regular parabola and end height isnt setable):

h = max height
d = max distance
x = current distance
y0 = statying Z
y1 = ending Z
JASS:
  function ParabolaZ takes real y0, real y1, real h, real d, real x returns real
    return ((4 * h / d) * (d - x) + y1 - y0) * (x / d) + y0
  endfunction

still this work weird coz now dont have parabola, atleast now missile detect the target height

another problem dont work when i lock the height, missile dont even appear or maybe die before i can see


i use vex model after i use a tutorial and this work well atm

JASS:
function SetDummyFacing takes unit u, real angle returns nothing
    call SetUnitLookAt(u, "Bone_Head", u, Cos(angle)*1000000., Sin(angle)*1000000., 0.)
endfunction

// To make the dummy face a 3 dimensional orientation instantly:
function SetDummyOrientation takes unit u, real x, real y, real z returns nothing
    call SetUnitLookAt(u, "Bone_Head", u, x*1000000., y*1000000., z*1000000.)
endfunction

//To make the dummy always face a particular unit, for homing missiles:
function SetDummyHomingTarget takes unit u, unit target returns nothing
    call SetUnitLookAt(u, "Bone_Head", target, 0., 0., 0.)
endfunction

and ofc +rep
 
Status
Not open for further replies.
Top