wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Resources > Code Resources > Scripts
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 04-06-2009, 02:45 PM   #1
Gwypaas
User
 
Join Date: Oct 2007
Posts: 170

Submissions (2)

Gwypaas is on a distinguished road (11)

Default Projectile System

Note - This system does not handle any physics, this is purely for moving units in different ways.

Documentation:
Collapse JASS:
=====================================================================================
 ------------------------ Projectile System made by Gwypaas -------------------------

 Use local Projectile p = Projectile.create(<unit>, <Remove Projectile?>) to create a new particle, if you set the boolean to true
 then the projectile will be removed upon finish of the movement. You can also do this with any of the premade types or your own.
 then the syntax would be
 local <Yourtype> p = <YourType.create(<unit>, <Remove Projectile?>)
 
 Then choose what type of movement you want.
 
 Then let the system do the rest <3

 NOTE --- This system DOES NOT handle any physics.

 This system is able to handle premade function pretty much "inserts" code into the timer callback
 You can see the usage of theese by viewing the "Jump", "Slide For Time" and "SLide Towards Unit"
 methods.
 
 
 This system is coded upon the polymorphism part of JASSHelper and when you create a new struct then extend it from on of the premade types.
 
 Check out the heavily commented Jump Struct for further information.
 
 These are the interface methods that you can use:
 
 method onLoop takes nothing returns nothing
 This method gets called on every interval and no of the premade types uses it.
 
 method privOnLoop takes nothing returns nothing
 This is the onloop method that the premade stuff uses.
 
 method onReach takes nothing returns nothing
 This method gets called upon reach of the target. Note - The premade types does not use it.
 

 With the use of the Projectile.create(<unit>, <Should get Removed?>) you create a basic projectile that 


 If you use custom methods and wants to destroy the projectile then set the projectiles "end" variable to true
 and it will be destroyed on the next timer interval.

 The theta = The normal angle you use when you calculate 2d stuff and it's of course in radians
 the phi = The "height" angle that specifies at which height direction it should go and it's also radians.

=====================================================================================
 -------------------- Premade methods in the Projectile struct ----------------------
 method Slide takes real x, real y, real speed returns nothing
 method SlideXYZ takes real x, real y, real z, real speed returns nothing
 method SlideTowardsAngle takes real theta, real phi, real speed, real distance returns nothing
 
 -------------------- Premade methods in the Extenions structs ----------------------
 method Jump takes real x, real y, real speed, real maxH returns nothing
 method SlideTowardsUnit takes unit target, real speed returns nothing
 method SlideXYZLiveTime takes real x, real y, real z, real speed, real TimeLiving returns nothing
 

 ------------------- Premade methods to get the mathematic values -------------------
 
     These methods are inline friendly
 method GetPhi takes real x, real y, real z returns real
 method GetTheta takes real x, real y returns real
 method GetDistance takes real x, real y, real z returns real
 method SetVelocityX takes nothing returns nothing
 method SetVelocityY takes nothing returns nothing
 method SetVelocityZ takes nothing returns nothing
 
 
 These methods are not inline friendly
 method SetVelocities takes nothing returns nothing
 method SetEverything takes real x, real y, real z returns nothing
=====================================================================================




Now to the code:
Collapse JASS:
library ProjectileSystem
globals
    // WARNING DO NOT MAKE THE VALUE BELOW TOO SMALL OR THE PARTICLE WILL CONTINUE TO SLIDE FOREVER.
    private constant real FINISH_THRESHOLD = 10 // How close it must be to the target to be considered finished.
    private constant real MIN_SPEED = .025 // The minimum speed a projectile can have before it's considered finished
    
    constant real PROJECTILE_TIMER_PERIOD = 0.02
    private constant boolean EXTRA_DEBUG_MODE = false // The "extra" debug mode which shows more messages.
    private constant real FPS = 1/PROJECTILE_TIMER_PERIOD

    
    private Projectile array Datas
    private integer N = 0
    private timer T = CreateTimer()
endglobals



interface ProjectileBase
    boolean end // Setting this to true will destroy the struct on the next interval.
    boolean remUnit // Set this to true if you want to remove the unit
    
    unit u // The projectile
    
    real x // The current x
    real y // The current y
    real z // The current z
    
    real resistance = 1// If you want the projectiles to have friction or similar 
    //then use the right formula to get the resistance the system should use and set
    // this variables to it. resistance 1 = no resistance, less than 1 = slowing down, more than 1 = speeding up.
    
    // Velocities
    real xV
    real yV
    real zV 
    
    real tx // The target x
    real ty // The target y
    real tz // The target z
    
    real theta // Angle
    real phi //Z Angle
    real rho // radius / speed
    
    
    real distLeft // The distance that is left to the target
    
    static location tloc = Location(0,0) // The location used to determine terrain height
    
    method onLoop takes nothing returns nothing defaults nothing // What you do on each loop
    method privOnLoop takes nothing returns nothing defaults nothing // What the struct you are extending does on each loop
    method onReach takes nothing returns nothing defaults nothing // What you do when the projectile reaches it's target
    
endinterface

    
struct Projectile extends ProjectileBase


    // Some inline friendly methods for easier creating of your own extensions
    method GetPhi takes real x, real y, real z returns real
        return Atan2(SquareRoot((x-.x) * (x-.x) + (y-.y) * (y-.y)), (z-.z))
    endmethod
    
    method GetTheta takes real x, real y returns real
        return Atan2((y - .y), (x - .x))
    endmethod
    
    method GetDistance takes real x, real y, real z returns real
        return SquareRoot((.x-x) * (.x-x) + (.y-y) * (.y-y) + (.z-z) * (.z-z))
    endmethod
    
        
        
    // Inline friendly Set Methods
    method SetVelocityX takes nothing returns nothing
        set .xV = Sin(.phi) * Cos(.theta) * .rho
    endmethod
    
    method SetVelocityY takes nothing returns nothing
        set .yV = Sin(.phi) * Sin(.theta) * .rho
    endmethod
    
    method SetVelocityZ takes nothing returns nothing
        set .zV = Cos(.phi) * .rho
    endmethod
    
    // Not inline friendy but easier to use.
    method SetVelocities takes nothing returns nothing
        set .xV = Sin(.phi) * Cos(.theta) * .rho
        set .yV = Sin(.phi) * Sin(.theta) * .rho
        set .zV = Cos(.phi) * .rho
    endmethod

    method SetEverything takes real x, real y, real z returns nothing
        set .phi = Atan2(SquareRoot((x-.x) * (x-.x) + (y-.y) * (y-.y)), (z-.z))
        set .theta = Atan2((y - .y), (x - .x))
        set .distLeft = SquareRoot((.x-x) * (.x-x) + (.y-y) * (.y-y) + (.z-z) * (.z-z))
        
        set .xV = Sin(.phi) * Cos(.theta) * .rho
        set .yV = Sin(.phi) * Sin(.theta) * .rho
        set .zV = Cos(.phi) * .rho
    endmethod
    
    
    static method Callback takes nothing returns boolean
        local Projectile p 
        local integer i = N
        local real sl 
        local boolean b
        local real tz
        loop
            exitwhen i == 0
            set p = Datas[i]
            set sl = (RAbsBJ(p.xV) + RAbsBJ(p.yV) + RAbsBJ(p.zV)) / 3
            set b = sl <= MIN_SPEED and sl >= -MIN_SPEED
            if p.distLeft <= FINISH_THRESHOLD or p.end == true or b then
                if p.onReach.exists == true then
                    call p.onReach()
                endif
            
                call p.destroy()
                set Datas[i] = Datas[N]
                set N = N - 1
                if N == 0 then
                    call PauseTimer(T)
                endif
            else
                
                set p.xV = p.xV * p.resistance
                set p.yV = p.yV * p.resistance
                set p.zV = p.zV * p.resistance
                
                set p.x = p.x + p.xV
                set p.y = p.y + p.yV
                set p.z = p.z + p.zV
                
                call MoveLocation(.tloc, p.x, p.y)
                set tz = GetLocationZ(.tloc)
                
                if p.onLoop.exists == true then
                    call p.onLoop()
                endif
                
                if p.privOnLoop.exists == true then
                    call p.privOnLoop()
                endif
                
                call SetUnitX(p.u, p.x)
                call SetUnitY(p.u, p.y)
                call SetUnitFlyHeight(p.u, p.z - tz, 0)
                
                call SetUnitFacing(p.u, p.theta * bj_RADTODEG)
                
                // I know that this doesn't seem efficient but I need this for moving targets :)
                set p.distLeft = p.GetDistance(p.tx, p.ty, p.tz) 
            endif

            set i = i-1
        endloop
        return false
    endmethod
    
    method Start takes nothing returns nothing
        if N == 0 then
            call TimerStart (T, PROJECTILE_TIMER_PERIOD, true, function Projectile.Callback)
        endif
        set N = N + 1
        set Datas[N] = this
    endmethod
    
    
    static method create takes unit u, boolean RemoveProjectile returns Projectile
        local Projectile p = .allocate()
        set p.u = u
        set p.x = GetUnitX(p.u)
        set p.y = GetUnitY(p.u)
        set p.z = GetUnitFlyHeight(p.u)
        
        set p.resistance = 1

        call UnitAddAbility(p.u, 'Amrf')
        call UnitRemoveAbility(p.u, 'Amrf')
        
        
        set p.end = false
        set p.remUnit = RemoveProjectile
        
        return p
    endmethod


    method Slide takes real x, real y, real speed returns nothing
        set .rho = speed
        set .distLeft = .GetDistance(x,y,0)
        set .phi = .GetPhi(x,y,0)
        set .theta = .GetTheta(x,y)
        
        call .SetVelocityX()
        call .SetVelocityY()
        call .SetVelocityZ()
        
        set .tx = x
        set .ty = y
        set .tz = 0
        
        call .Start()
    endmethod
    
    method SlideXYZ takes real x, real y, real z, real speed returns nothing
        set .rho = speed
        set .theta = .GetTheta(x,y)
        set .phi = .GetPhi(x,y,z)
        set .distLeft = .GetDistance(x,y,z)
        
        call .SetVelocityX()
        call .SetVelocityY()
        call .SetVelocityZ()
        
        set .tx = x
        set .ty = y
        set .tz = z
        
        call .Start()
    endmethod

    
    method SlideTowardsAngle takes real theta, real phi, real speed, real distance returns nothing
        set .rho = speed
        set .theta = theta
        set .phi = phi
        
        set .tx = .x + (Sin(.phi) * Cos(.theta)) * distance
        set .ty = .y + (Sin(.phi) * Sin(.theta)) * distance
        set .tz = .z + Cos(.phi) * distance
        set .distLeft = .GetDistance(.tx, .ty, .tz)
        call .SetVelocityX()
        call .SetVelocityY()
        call .SetVelocityZ()
        call .Start()
    endmethod
    
    method onDestroy takes nothing returns nothing
        debug if EXTRA_DEBUG_MODE then
            debug call BJDebugMsg("Instance ID = " + I2S(this) +" || End Results:  x = " + R2S(GetUnitX(.u)) + " : y = " + R2S(GetUnitY(.u)) + " : z = " + R2S(GetUnitFlyHeight(.u)))
        debug else
            debug call BJDebugMsg("Instance ID = " + I2S(this))
        debug endif
        if .remUnit then
            call RemoveUnit(.u)
        endif
        set .u = null
    endmethod
endstruct
endlibrary

Collapse JASS:
//=====================================================================================//
// ------------------- Projectile System Extensions made by Gwypaas -------------------//
//
// This is the library that you create your own projectile types in.
// Check out the "examples" below if you want more info
//
// Note, you NEED to do the typecasting that I do with the "local Jump p = pp" beacause
// otherwise it will give you syntax error because of how function interfaces are constructed
//
//=====================================================================================//

library ProjectileSystemExtensions requires ProjectileSystem



struct Jump extends Projectile // This is what makes it a projectile
    
    // Private variables for the method
    real jextra    
    real totalDist 
    real distDone  
    
    // The private method that gets called every interval
    method privOnLoop takes nothing returns nothing
        set .z = (4 * .jextra / .totalDist) * (.totalDist - .distDone) * (.distDone / .totalDist)
        // Credits to Moyack and Spec for this formula.
        set .distDone = .distDone + .rho
    endmethod
    
    // The method you use to start the "sliding" of your Jump 
    method Jump takes real x, real y, real speed, real maxH returns nothing
        local real td = .GetDistance(x, y,0) // Getting the distance
        set .rho = speed // Setting the speed
        set .theta = .GetTheta(y, x) // Getting the XY angle
        set .phi = .GetPhi(x,y,0) // GEtting the Z angle
        
        // Setting hte private variables
        set .distLeft = td 
        set .totalDist =  td
        set .jextra = maxH
        set .distDone = 0
        
        // Setting the Velocities based on your rho, theta and phi
        call .SetVelocityX() 
        call .SetVelocityY()
        call .SetVelocityZ()
        
        // Setting the starting position
        set .tx = x
        set .ty = y
        set .tz = 0

        
        call .Start() // Fire the sliding up
    endmethod
endstruct



struct SlideTowardsUnit extends Projectile
    unit target 
    
    method privOnLoop takes nothing returns nothing
        set .tx = GetUnitX(.target)
        set .ty = GetUnitY(.target)
        set .tz = GetUnitFlyHeight(.target)
        set .theta = .GetTheta(.tx, .ty)
        set .phi = .GetPhi(.tx, .ty, .tz)
    
        call .SetVelocityX()
        call .SetVelocityY()
        call .SetVelocityZ()
    endmethod
    
    method SlideTowardsUnit takes unit target, real speed returns nothing
        local real x = GetUnitX(target)
        local real y = GetUnitY(target)
        local real z = GetUnitFlyHeight(target)
        
        set .target = target
        
        set .rho = speed
        set .theta = .GetTheta(x,y)
        set .phi = .GetPhi(x,y,z)
        set .distLeft = .GetDistance(x,y,z)
        
        call .SetVelocityX()
        call .SetVelocityY()
        call .SetVelocityZ()
        
        set .tx = x
        set .ty = y
        set .tz = z
         
        call .Start()
    endmethod
    
    method onDestroy takes nothing returns nothing
        set .target = null
    endmethod
endstruct


struct SlideXYZLiveTime extends Projectile
    real maxTime 
    real timeDone
    method privOnLoop takes nothing returns nothing
        if .timeDone >= .maxTime then
            set .end = true
        endif
        set .timeDone = .timeDone + PROJECTILE_TIMER_PERIOD
    endmethod
    
    method SlideXYZLiveTime takes real x, real y, real z, real speed, real TimeLiving returns nothing
        set .timeDone = 0
        set .maxTime = TimeLiving
        set .rho = speed
        set .theta = .GetTheta(x,y)
        set .phi = .GetPhi(x,y,z)
        set .distLeft = .GetDistance(x,y,z)
        
        call .SetVelocityX()
        call .SetVelocityY()
        call .SetVelocityZ()
        
        set .tx = x
        set .ty = y
        set .tz = z
        
        call .Start()
    endmethod
endstruct
endlibrary

Changelog:
Hidden information:
180609 - Made it work better with cliffs

130309 - Made it use methods interfaces instead of function interfaces and also rewrote parts of the documentation.

070209 - Added the "Slide towards angle" method for the people that needs it.

300109(2) - Made so the user can select if a Projectile should get removed, also added movement resistance and made so all projectiles that moves slower than a specified speed are considered finished, also updated the documentation a bit.

300109 - It now uses velocities in some way but I'm not sure if it's right. I also made methods to set the velocities that are inline friendly and one that sets all but isn't inline friendly, I also made a "Set Everything" method for the lazy people, calling that will set the velocities and angles.

290109 - Made it alot easier to use by making the extensions not using the USF function that was meant to be used by the user, It's also easier to create your own types now since I've created the .GetPhi/Theta/Distance methods so you don't need to CnP the ones that I used. The methods will also be inlined due to how I made them.
Attached Files
File Type: w3x Projectile System.w3x (31.3 KB, 119 views)

Last edited by Gwypaas : 06-22-2009 at 10:11 PM.
Gwypaas is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 04-06-2009, 03:26 PM   #2
wraithseeker
User
 
Join Date: Feb 2009
Posts: 406

wraithseeker is on a distinguished road (17)

Default

Aren't velocities physics?
wraithseeker is offline   Reply With Quote
Old 04-06-2009, 03:56 PM   #3
Gwypaas
User
 
Join Date: Oct 2007
Posts: 170

Submissions (2)

Gwypaas is on a distinguished road (11)

Default

Yes you can use them in physics but in this system I only use them for movement, but that's also a sort of physics :)
Gwypaas is offline   Reply With Quote
Old 04-16-2009, 03:33 PM   #4
Vexorian
Free Software Terrorist
 
Vexorian's Avatar


Technical Director
 
Join Date: Apr 2003
Posts: 14,898

Submissions (37)

Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)Vexorian has a reputation beyond repute (1062)

Hero Contest #3 - 2nd Place

Default

Blah disappointment, when I read "ProjectileSystem" I thought it would do projectiles like blizz' attacks and spell missiles.

So it is like a 3d collision missile. I guess some will find an use.

Why do people use [jass] for documentation? that's non-sense.
__________________
Zoom (requires log in)Wc3 map optimizer 5.0
Someone should fix .wav sound in this thing.
Zoom (requires log in)JassHelper 0.A.2.A
Turns your simple code into something that is complicated enough to work.
Faster != more useful
Vexorian is offline   Reply With Quote
Old 05-19-2009, 01:40 AM   #5
General Ray
User
 
General Ray's Avatar
 
Join Date: Aug 2008
Posts: 11

General Ray has little to show at this moment (0)

Default

Now Vex, can't blame one for trying.
I must say I was also disappointed it wasn't a missile system, but good work nonetheless.
General Ray is offline   Reply With Quote
Old 06-11-2009, 01:24 PM   #6
DanThanh
User
 
DanThanh's Avatar
 
Join Date: Apr 2009
Posts: 137

Submissions (1)

DanThanh has little to show at this moment (7)

Send a message via Yahoo to DanThanh
Default

Quote:
Originally Posted by Vexorian
Blah disappointment, when I read "ProjectileSystem" I thought it would do projectiles like blizz' attacks and spell missiles.

So it is like a 3d collision missile. I guess some will find an use.

Why do people use [jass] for documentation? that's non-sense.

I agree...but i find this useful
__________________
DanThanh is offline   Reply With Quote
Old 06-18-2009, 04:57 PM   #7
Gwypaas
User
 
Join Date: Oct 2007
Posts: 170

Submissions (2)

Gwypaas is on a distinguished road (11)

Default

Fixed the movement over cliffs.
Gwypaas is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 07:27 PM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services