System My Simple Projectile System

Exfyre

hmm...
Reaction score
60
MySimple Projectile System


I found out that there was already a projectile system called Simple Projectile System, which I had originally intended on naming this. Therefore, to avoid conflicts, I renamed this to MySPS.

Requires:
-JASS NewGen Pack
-Key Timers 2

JASS:
//                                                                                               
// My                                                                                              
// .-.                  .       .--.                 .       .        .-.         .              
//(   ) o               |       |   )       o       _|_   o  |       (   )       _|_             
// `-.  .  .--.--. .,-. | .-.   |--'.--..-. . .-. .-.|    .  | .-.    `-. .  ..--.|  .-. .--.--. 
//(   ) |  |  |  | |   )|(.-'   |   |  (   )|(.-'(   |    |  |(.-'   (   )|  |`--.| (.-' |  |  | 
// `-'-' `-'  '  `-|`-' `-`--'  '   '   `-' | `--'`-'`-'-' `-`-`--'   `-' `--|`--'`-'`--''  '  `-
//                 |                        ;                                ;  By Exfyre - v1.1
//                 '                     `-'                              `-'                    
//      What is SPS?
//      ¯¯¯¯¯¯¯¯¯¯¯¯
//          -SPS allows you to add simple projectiles, with trajectory, quite easily.
//
//      How to implement?
//      ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          -Create a new trigger object called SPS, go to "Edit -> Convert to Custom Text," and paste
//           this code into the trigger.
//          -Copy the Model file in the import section (F12) to your map
//          -Copy the dummy unit "Dummy Caster" from this map to yours
//
//      Functions:
//      ¯¯¯¯¯¯¯¯¯¯
//          SPS_Add(real x, real y, integer projectiles, real scaling, real power,
//                  real angle, real rotation, string model, string post, real spreadXY, real spreadZ,
//                  boolean follow, code func)
//              -x, y:  This is the starting location of the projectile
//              -projectiles:  # of projectiles to be created
//              -scaling:  scaling size of the model to be attached
//              -power:  the inital velocity of the projectile (as a percentage of 100, see globals to change power constant)
//              -angle:  the angle of the shot in Z direction, from ground level (90 being straight up)
//              -rotation:  firing angle in the XY plane (90 being North)
//              -model:  model of the projectile while in air
//              -post:  effect to play when the projectile hits the ground
//              -spreadXY:  spread of the shot (when int projectiles > 1) in the XY direction (random)
//              -spreadZ:  spread of the shot (when int projectiles > 1) in the Z direction (odered)
//              -follow:  when set to true, the camera will follow the projectile through the air
//              -func:  The function you want to run after the projectile hits
//      Wrappers:
//      ¯¯¯¯¯¯¯¯¯
//          SPS_GetEndX()  returns real
//          SPS_GetEndY()  returns real
//          SPS_GetHurter()  returns unit
//          SPS_GetAbilId()  returns integer

library SPS uses T32
//configurables
globals
    private constant integer DUMMYUNIT='h001'
    private constant real GRAVITY = 1000  //How fast the missles fall
    private constant real POWERC = 40  //multiple for power
endglobals
//endconfigurables

globals
    private location L = Location(0,0)
    unit Hurter
    real EndX
    real EndY
    integer AbilId
endglobals

private struct InstanceData
    unit hurter
    unit dummy
    effect dummyeffect
    real time = 0
    real x
    real y
    real z
    real power
    real angle
    real rotation
    boolean follow
    string post
    integer abilId
    trigger t = CreateTrigger()
    private method FindD takes real power, real angle, real time returns real
        return power*Cos(angle)*time
    endmethod

    private method FindX takes real x, real rotation, real power, real angle, real time returns real
        return x + FindD(power, angle, time) * Cos(rotation)
    endmethod

    private method FindY takes real y, real rotation, real power, real angle, real time returns real
        return y + FindD(power, angle, time) * Sin(rotation)
    endmethod

    private method FindZ takes real power, real angle, real time returns real
        return (power*Sin(angle)) * time - ((GRAVITY) * (time*time) / 2.)  //D=(Vi)t+(1/2)(a)(t^2)
    endmethod

    private method IsFalling takes real power, real angle, real time returns boolean
        return 2./time*(FindD(power, angle, time)/time-power)<0
    endmethod
    
    private method periodic takes nothing returns nothing
        local real time = this.time
        local real xx = FindX(this.x, this.rotation, this.power, this.angle, time)
        local real yy = FindY(this.y, this.rotation, this.power, this.angle, time)
        local real zz = FindZ(this.power, this.angle, this.time)
        set this.time = this.time + T32_PERIOD
        call SetUnitPosition(this.dummy, xx, yy)
        call SetUnitFlyHeight(this.dummy, zz, 0.0)
        if (this.follow==true) then
            call PanCameraToWithZ(xx, yy, zz)
        endif
        if zz <= 1 and IsFalling(this.power, this.angle, time) then
            call DestroyEffect(this.dummyeffect)
            call DestroyEffect(AddSpecialEffect(this.post, xx, yy))
            call RemoveUnit(this.dummy)
            set Hurter = this.hurter
            set EndX = xx
            set EndY = yy
            set AbilId = this.abilId
            call TriggerExecute(this.t)
            call DestroyTrigger(this.t)
            call this.stopPeriodic()
            call this.destroy()
        endif
    endmethod
    implement T32x
    static method create takes integer abilId, unit hurter, real x, real y, real scaling, real power, real angle, real rotation, string model, string post, boolean follow, trigger t returns thistype
            local thistype this = thistype.allocate()
            set this.hurter = hurter
            set this.x = x
            set this.y = y
            set this.power = power*POWERC
            set this.angle = angle
            set this.rotation = rotation
            set this.post = post
            set this.follow = follow
            set this.abilId = abilId
            set this.t = t
            set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYUNIT, x, y, 0)
            set this.dummyeffect = AddSpecialEffectTarget(model, this.dummy, "origin")
            call SetUnitScale(this.dummy, scaling, scaling, scaling)
            call MoveLocation(L, x, y)
            set this.z = GetLocationZ(L)
            return this
    endmethod
endstruct

public function Add takes integer abilId, unit hurter, real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow, code func returns nothing
    local integer i = 1
    local trigger array t
    loop
        exitwhen i == projectiles+1
        set t<i> = CreateTrigger()
        call TriggerAddAction(t<i>, func)
        call InstanceData.create(abilId, hurter, x + GetRandomReal(0., spreadXY), y + GetRandomReal(0., spreadXY), scaling, power + (projectiles/2 - i) * spreadZ, angle*bj_DEGTORAD, rotation*bj_DEGTORAD, model, post, follow, t<i>).startPeriodic()
        set t<i> = null
        set i = i + 1
    endloop
endfunction

//wrappers
public function GetEndX takes nothing returns real
    return EndX
endfunction
public function GetEndY takes nothing returns real
    return EndY
endfunction
public function GetHurter takes nothing returns unit
    return Hurter
endfunction
public function GetAbilId takes nothing returns integer
    return AbilId
endfunction
//endwrappers
endlibrary</i></i></i></i>


v1.0
JASS:
//                                                                                               
// My                                                                                              
// .-.                  .       .--.                 .       .        .-.         .              
//(   ) o               |       |   )       o       _|_   o  |       (   )       _|_             
// `-.  .  .--.--. .,-. | .-.   |--&#039;.--..-. . .-. .-.|    .  | .-.    `-. .  ..--.|  .-. .--.--. 
//(   ) |  |  |  | |   )|(.-&#039;   |   |  (   )|(.-&#039;(   |    |  |(.-&#039;   (   )|  |`--.| (.-&#039; |  |  | 
// `-&#039;-&#039; `-&#039;  &#039;  `-|`-&#039; `-`--&#039;  &#039;   &#039;   `-&#039; | `--&#039;`-&#039;`-&#039;-&#039; `-`-`--&#039;   `-&#039; `--|`--&#039;`-&#039;`--&#039;&#039;  &#039;  `-
//                 |                        ;                                ;  By Exfyre - v1.0
//                 &#039;                     `-&#039;                              `-&#039;                    
//      What is MySPS?
//      ¯¯¯¯¯¯¯¯¯¯¯¯
//          -MySPS allows you to add simple projectiles, with trajectory, quite easily.
//
//      How to implement?
//      ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          -Create a new trigger object called MySPS, go to &quot;Edit -&gt; Convert to Custom Text,&quot; and paste
//           this code into the trigger.
//
//      Functions:
//      ¯¯¯¯¯¯¯¯¯¯
//          MySPS_Add(real x, real y, integer projectiles, real scaling, real power,
//                  real angle, real rotation, string model, string post, real spreadXY, real spreadZ,
//                  boolean follow)
//              -x, y:  This is the starting location of the projectile
//              -projectiles:  # of projectiles to be created
//              -scaling:  scaling size of the model to be attached
//              -power:  the inital velocity of the projectile (as a percentage of 100, see globals to change power constant)
//              -angle:  the angle of the shot in Z direction, from ground level (90 being straight up)
//              -rotation:  firing angle in the XY plane (90 being North)
//              -model:  model of the projectile while in air
//              -post:  effect to play when the projectile hits the ground
//              -spreadXY:  spread of the shot (when int projectiles &gt; 1) in the XY direction (random)
//              -spreadZ:  spread of the shot (when int projectiles &gt; 1) in the Z direction (odered)
//              -follow:  when set to true, the camera will follow the projectile through the air
//
//          MySPS_AddSimple(real x, real y, real scaling, real power, real angle,
//                  real rotation, string model, string post)
//              -Has same values as above.  Default fires 1 projectile, without following with camera
//
//          MySPS_AddTimed(real x, real y, integer projectiles, real scaling, real power,
//                  real angle, real rotation, string model, string post, real spreadXY, real spreadZ,
//                  boolean follow, real rate)
//              -rate:  will fire all projectiles with real rate interval between firings
//              -Other values same as SPS_Add

library MySPS uses KT

globals
    private constant integer DUMMYUNIT=&#039;h001&#039;
    private constant real PERIOD = .03125  //Period for the timer
    private constant real GRAVITY = 1000  //How fast the missles fall
    private constant real POWERC = 40  //multiple for power
endglobals

private struct InstanceData
    unit dummy
    effect dummyeffect
    real time = 0
    real x
    real y
    real power
    real angle
    real rotation
    boolean follow
    string post
endstruct

private struct TimedData
    real x
    real y
    integer projectiles
    real scaling
    real power
    real angle
    real rotation
    string model
    string post
    real spreadXY
    real spreadZ
    boolean follow
endstruct

private function FindD takes real power, real angle, real time returns real
    return power*Cos(angle* bj_DEGTORAD)*time
endfunction

private function FindX takes real x, real rotation, real power, real angle, real time returns real
    return x + FindD(power, angle, time) * Cos(rotation * bj_DEGTORAD)
endfunction

private function FindY takes real y, real rotation, real power, real angle, real time returns real
    return y + FindD(power, angle, time) * Sin(rotation * bj_DEGTORAD)
endfunction

private function FindZ takes real power, real angle, real time returns real
    return (power*Sin(angle* bj_DEGTORAD)) * time - ((GRAVITY) * (time*time) / 2.)  //D=(Vi)t+(1/2)(a)(t^2)
endfunction

private function IsFalling takes real power, real angle, real time returns boolean
    return 2./time*(FindD(power, angle, time)/time-power)&lt;0
endfunction

private function Fire takes nothing returns boolean
    local InstanceData d = KT_GetData()
    local real x = d.x
    local real y = d.y
    local real time = d.time
    local real rotation = d.rotation
    local real power = d.power*POWERC
    local real angle = d.angle
    local real xx = FindX(x, rotation, power, angle, time)
    local real yy = FindY(y, rotation, power, angle, time)
    local real zz = FindZ(power, angle, time)
    set d.time = d.time + PERIOD
    call SetUnitPosition(d.dummy, xx, yy)
    call SetUnitFlyHeight(d.dummy, zz, 0.0)
    if (d.follow==true) then
        call PanCameraToWithZ(xx, yy, zz)
    endif
    if GetUnitFlyHeight(d.dummy) &lt;= 1 and IsFalling(power, angle, time) then
        call DestroyEffect(d.dummyeffect)
        call DestroyEffect(AddSpecialEffect(d.post, xx, yy))
        call RemoveUnit(d.dummy)
        return true
    endif
    return false
endfunction

public function Add takes real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow returns nothing
    local InstanceData array d
    local integer i = 1
    loop
        exitwhen i == projectiles+1
        set d<i> = InstanceData.create()
        set d<i>.x = x + GetRandomReal(0., spreadXY)
        set d<i>.y = y + GetRandomReal(0., spreadXY)
        set d<i>.angle = angle
        set d<i>.rotation = rotation
        set d<i>.power = power + (projectiles/2 - i) * spreadZ
        set d<i>.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYUNIT, x, y, 0)
        call SetUnitScale(d<i>.dummy, scaling, scaling, scaling)
        set d<i>.dummyeffect = AddSpecialEffectTarget(model, d<i>.dummy, &quot;origin&quot;)
        set d<i>.follow = follow
        set d<i>.post = post
        call KT_Add(function Fire, d<i>, PERIOD)
        set i = i + 1
    endloop
endfunction

public function AddSimple takes real x, real y, real scaling, real power, real angle, real rotation, string model, string post returns nothing
    call Add(x, y, 1, scaling, power, angle, rotation, model, post, 0, 0, false)
endfunction

private function AddViaStruct takes nothing returns boolean
    local TimedData d = KT_GetData()
    call Add(d.x, d.y, 1, d.scaling, d.power, d.angle, d.rotation, d.model, d.post, d.spreadXY, d.spreadZ, d.follow)
    if d.projectiles == 0 then
        return true
    endif
    set d.projectiles = d.projectiles-1
    return false
endfunction

public function AddTimed takes real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow, real rate returns nothing
    local TimedData d = InstanceData.create()
    set d.x = x
    set d.y = y
    set d.angle = angle
    set d.rotation = rotation
    set d.model = model
    set d.power = power
    set d.follow = follow
    set d.post = post
    set d.scaling = scaling
    set d.projectiles = projectiles
    set d.spreadXY = spreadXY
    set d.spreadZ = spreadZ
    call KT_Add(function AddViaStruct, d, rate)
endfunction

endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i>


Changelog:
v1.1 - Switched from KT to T32, added more functionality, other stuff. Map updated
v1.0 - First release


Summary:
This system creates projectiles that originate from a rotated source at an angle with a speed.

The demo map includes 3 different implementations, using a tank with 3 weapons.
-single shot
-buck shot
-carpet bomb



What I WANT to be able to do is to retrieve the X and Y coordinates of the ending location after each projectile lands, and do something with that - but I don't have any idea how to implement that.

Also, I'm sure the code can be optimized, so suggestions are welcome.
 

Attachments

  • MySPS.w3x
    149.5 KB · Views: 274

Exfyre

hmm...
Reaction score
60
whoopsy, attached the map. :)

Also, I dunno how to use T32 =/
Only reason I know how to use KT is because of that tutorial Jesus4lyf posted
 

Jesus4Lyf

Good Idea™
Reaction score
397
I should update that to use T32. :p

Actually, the speed difference isn't really important. But T32 is easy to use.
JASS:
//      How to implement?
//      ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          -Create a new trigger object called MySPS, go to &quot;Edit -&gt; Convert to Custom Text,&quot; and paste
//           this code into the trigger.

No, sorry, make your implementation instructions complete. You definitely needs something to do with dummy units to attach models to.

This should allow you to attach data to a projectile and register a on-collision Event. :thup:
Else it's a bit useless, ey? ;)

PS. Problem - everyone has written this before for themselves, except slightly differently each time. We all have another 50 features we could add to this to make it "useful", but in the process it'd become so cluttered that no one would use it. In it's current state, it is simple enough (ie. not enough innovation to make it worthwhile for people to learn your style and your interface) for everyone to have a conflicting opinion on how it could be changed to be better, or what in the interface should change, and since chances are no one will agree, no one will be quite happy with it. People will continue to use their own, and probably not this - in fact, you will probably continue to go on to make a new wizz-bang projectile system in the future, and then deprecate that also. This is the problem with projectile systems (and I expect, buff systems).
 

Sevion

The DIY Ninja
Reaction score
413
Bleh, what's up with that ASCII art? Can't anyone just do:

JASS:
/*
My System Name Here And Nothing Else :3
By: The_One_Dude

...Description and What Have You...
*/


You don't have a DoOnHit and DoOnTick and DoOnFail? :(

It'd be nice if you did. And perhaps a version that allows Unit -> Unit instead of just Coords :3
 

Exfyre

hmm...
Reaction score
60
I did make this for myself, as I am trying to make a 3D pocket tanks like game and could not find anything decent that would allow the same options.

This should allow you to attach data to a projectile and register a on-collision Event.
Else it's a bit useless, ey?
Are you referring to T32 here (attaching data)?

Bleh, what's up with that ASCII art?
It's the shit. Don't hate

And perhaps a version that allows Unit -> Unit instead of just Coords :3
o_O good idea


also, right now the projectile follows the terrain, but I need it to be independent of the height of the terrain.
I tried
JASS:
//where xx, yy is x&amp;y for projectile
//zz is the absolute height above terrain of height 0
//z is the starting ground level at initial launch
    local real zz = FindZ(power, angle, time)
    call MoveLocation(L, xx, yy)
    set z2 = GetLocationZ(L)
    set zz = zz - z2 + z
    call SetUnitFlyHeight(d.dummy, zz, 0.0)

but the projectile still jumps when it encounters different terrain height.
 

Sevion

The DIY Ninja
Reaction score
413
Well, I mean like for each .periodic call, have it call a DoOnTick function :3 Like if you wanted to make it create a path effect or something :D

Actually, Cleeezzz and I both did something like that once.
 

Sevion

The DIY Ninja
Reaction score
413
The add functions don't return the struct. And the structs are private :3

But, yeah, if the functions returned the struct or the other option, that would be nice :D
 

Exfyre

hmm...
Reaction score
60
I ended up with this. Only problem is, the projectile doesn't move. It is created on the ground, and the periodic timer runs, but it doesn't move. Can T32 access the private functions outside the struct?

JASS:
library SPS uses T32
//configurables
globals
    private constant integer DUMMYUNIT=&#039;h001&#039;
    private constant real PERIOD = .03125  //Period for the timer
    private constant real GRAVITY = 1000  //How fast the missles fall
    private constant real POWERC = 40  //multiple for power
endglobals
//endconfigurables

globals
    private location L = Location(0,0)
endglobals

private function FindD takes real power, real angle, real time returns real
    return power*Cos(angle* bj_DEGTORAD)*time
endfunction

private function FindX takes real x, real rotation, real power, real angle, real time returns real
    return x + FindD(power, angle, time) * Cos(rotation * bj_DEGTORAD)
endfunction

private function FindY takes real y, real rotation, real power, real angle, real time returns real
    return y + FindD(power, angle, time) * Sin(rotation * bj_DEGTORAD)
endfunction

private function FindZ takes real power, real angle, real time returns real
    return (power*Sin(angle* bj_DEGTORAD)) * time - ((GRAVITY) * (time*time) / 2.)  //D=(Vi)t+(1/2)(a)(t^2)
endfunction

private function IsFalling takes real power, real angle, real time returns boolean
    return 2./time*(FindD(power, angle, time)/time-power)&lt;0
endfunction

private struct InstanceData
    unit hurter
    unit dummy
    effect dummyeffect
    real time = 0
    real x
    real y
    real z
    real power
    real angle
    real rotation
    boolean follow
    string post
    private method periodic takes nothing returns nothing
        local real xx = FindX(this.x, this.rotation, this.power, this.angle, this.time)
        local real yy = FindY(this.y, this.rotation, this.power, this.angle, this.time)
        local real zz = FindZ(this.power, this.angle, this.time)
        call SetUnitPosition(this.dummy, xx, yy)
        call SetUnitFlyHeight(this.dummy, zz, 0.0)
        if (this.follow==true) then
            //call PanCameraToWithZ(xx, yy, zz)
        endif
        if zz &lt;= 1 and IsFalling(this.power, this.angle, this.time) then
            call DestroyEffect(this.dummyeffect)
            call DestroyEffect(AddSpecialEffect(this.post, xx, yy))
            call RemoveUnit(this.dummy)
            call this.stopPeriodic()
            call this.destroy()
        endif
        set this.time = this.time + PERIOD
    endmethod
    implement T32x
    static method create takes unit hurter, real x, real y, real scaling, real power, real angle, real rotation, string model, string post, boolean follow returns thistype
            local thistype this = thistype.allocate()
            set this.hurter = hurter
            set this.x = x
            set this.y = y
            set this.power = power*POWERC
            set this.angle = angle
            set this.rotation = rotation
            set this.post = post
            set this.follow = follow
            set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYUNIT, x, y, 0)
            set this.dummyeffect = AddSpecialEffectTarget(model, this.dummy, &quot;origin&quot;)
            call SetUnitScale(this.dummy, scaling, scaling, scaling)
            call MoveLocation(L, x, y)
            set this.z = GetLocationZ(L)
            return this
    endmethod
endstruct

public function Add takes unit hurter, real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow returns nothing
    local InstanceData array d
    local integer i = 1
    loop
        exitwhen i == projectiles+1
        call InstanceData.create(hurter, x + GetRandomReal(0., spreadXY), y + GetRandomReal(0., spreadXY), scaling, power + (projectiles/2 - i) * spreadZ, angle, rotation, model, post, follow).startPeriodic()
        set i = i + 1
    endloop
endfunction

endlibrary
 

Jesus4Lyf

Good Idea™
Reaction score
397
The add functions don't return the struct. And the structs are private :3

But, yeah, if the functions returned the struct or the other option, that would be nice :D
I would write this as a module, actually. That module could implement T32, and you could even make it work with calling .destroy() on the projectile at any moment. :)

Edit: Can't see anything immediately wrong with that code. You might have to do some debugging, find what's broken...
 

Sevion

The DIY Ninja
Reaction score
413
I would write this as a module, actually. That module could implement T32, and you could even make it work with calling .destroy() on the projectile at any moment. :)

This :3

And at the latest code, "hurter"? XD

The functions I would find nice are Coord -> Coord, Unit -> Coord, Coord -> Unit and Unit -> Unit.
 

Exfyre

hmm...
Reaction score
60
I would write this as a module, actually. That module could implement T32, and you could even make it work with calling .destroy() on the projectile at any moment. :)

Edit: Can't see anything immediately wrong with that code. You might have to do some debugging, find what's broken...

Could you elaborate? I have no experience with modules or their uses.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>The functions I would find nice are Coord -> Coord, Unit -> Coord, Coord -> Unit and Unit -> Unit.

And then you'll want it to hit trees and destroy them, but not gates, it should bounce off those, and then damage only enemy units, or heal only friendly units, or bounce between units along the way, oh and it needs a callback for when it passes an allied unit, and a callback for when it passes terrain that it would collide with, and if it does collide it should bounce up and hit an air unit, but otherwise it should miss it because it's 3D, and I want the projectile to give an armour aura because for some reason I think it's cool, and it needs to change to an ice model if it passes over snow terrain, and it needs to have gravity applied so it can fall short if the user doesn't aim it right, and best of all it needs to store a list of units it has passed in a serializable way so I can typecast struct data from integers to access each data attachment I want for those units and somehow not fix the number of things the projectile can hit to achieve this and not effect the 8191 limit all because I'm an efficiency whore (well, that's not actually possible :p).
PS. Problem - everyone has written this before for themselves, except slightly differently each time. We all have another 50 features we could add to this to make it "useful", but in the process it'd become so cluttered that no one would use it. In it's current state, it is simple enough (ie. not enough innovation to make it worthwhile for people to learn your style and your interface) for everyone to have a conflicting opinion on how it could be changed to be better, or what in the interface should change, and since chances are no one will agree, no one will be quite happy with it. People will continue to use their own, and probably not this - in fact, you will probably continue to go on to make a new wizz-bang projectile system in the future, and then deprecate that also. This is the problem with projectile systems (and I expect, buff systems).
I really don't think it'll happen. >_>

Edit:
JASS:
private struct DEFAULTS extends array
    // default methods
    method onHit takes nothing returns nothing
    endmethod
endstruct

module SPS
    private static constant delegate DEFAULTS default=0 // Just joking, JassHelper refuses to do private static constant delegates, you can only have private static delegates.

    private method periodic takes nothing returns nothing
        ...
            call this.onHit()
        ...
    endmethod
    implement T32x

    //etc
endmodule
 

Kenny

Back for now.
Reaction score
202
@ Jesus4Lyfs post:

I felt like releasing my projectile system, but now I am not sure. :p

However I do agree with what you are saying. It is difficult to make a system such as this have enough options to fit all map types.

Currently my projectile system does everything but allow the projectile to follow a unit, but it is possible for the user to update the velocities periodically to make up for that. And it is also possible to have a projectile use a parabola arc with a initial height instead of from 0.00, but it has to be under 300.00.

They are little tricks I implemented to make the projectiles look better, but it would be annoying to have to remember stuff like that for a system.

But yeah, back on topic. I think you will find it difficult to make something that is standardised enough for people to want to use. But good luck. :)
 

Exfyre

hmm...
Reaction score
60
:thup:Nice rant.

I fixed the code, so now I just would like to know how I can use Event to register OnHit events and such with your Event snippet that will allow me to access ending x and y values, the "hurter", which is a wonderful variable label, and whatever other vals I might need.

JASS:
library SPS uses T32
//configurables
globals
    private constant integer DUMMYUNIT=&#039;h001&#039;
    private constant real GRAVITY = 1000  //How fast the missles fall
    private constant real POWERC = 40  //multiple for power
endglobals
//endconfigurables

globals
    private location L = Location(0,0)
endglobals

private struct InstanceData
    unit hurter
    unit dummy
    effect dummyeffect
    real time = 0
    real x
    real y
    real z
    real power
    real angle
    real rotation
    boolean follow
    string post
    private method FindD takes real power, real angle, real time returns real
        return power*Cos(angle* bj_DEGTORAD)*time
    endmethod

    private method FindX takes real x, real rotation, real power, real angle, real time returns real
        return x + FindD(power, angle, time) * Cos(rotation * bj_DEGTORAD)
    endmethod

    private method FindY takes real y, real rotation, real power, real angle, real time returns real
        return y + FindD(power, angle, time) * Sin(rotation * bj_DEGTORAD)
    endmethod

    private method FindZ takes real power, real angle, real time returns real
        return (power*Sin(angle* bj_DEGTORAD)) * time - ((GRAVITY) * (time*time) / 2.)  //D=(Vi)t+(1/2)(a)(t^2)
    endmethod

    private method IsFalling takes real power, real angle, real time returns boolean
        return 2./time*(FindD(power, angle, time)/time-power)&lt;0
    endmethod
    
    private method periodic takes nothing returns nothing
        local real time = this.time
        local real xx = FindX(this.x, this.rotation, this.power, this.angle, time)
        local real yy = FindY(this.y, this.rotation, this.power, this.angle, time)
        local real zz = FindZ(this.power, this.angle, this.time)
        set this.time = this.time + T32_PERIOD
        call SetUnitPosition(this.dummy, xx, yy)
        call SetUnitFlyHeight(this.dummy, zz, 0.0)
        if (this.follow==true) then
            call PanCameraToWithZ(xx, yy, zz)
        endif
        if zz &lt;= 1 and IsFalling(this.power, this.angle, time) then
            call DestroyEffect(this.dummyeffect)
            call DestroyEffect(AddSpecialEffect(this.post, xx, yy))
            call RemoveUnit(this.dummy)
            call this.stopPeriodic()
            call this.destroy()
        endif
    endmethod
    implement T32x
    static method create takes unit hurter, real x, real y, real scaling, real power, real angle, real rotation, string model, string post, boolean follow returns thistype
            local thistype this = thistype.allocate()
            set this.hurter = hurter
            set this.x = x
            set this.y = y
            set this.power = power*POWERC
            set this.angle = angle
            set this.rotation = rotation
            set this.post = post
            set this.follow = follow
            set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYUNIT, x, y, 0)
            set this.dummyeffect = AddSpecialEffectTarget(model, this.dummy, &quot;origin&quot;)
            call SetUnitScale(this.dummy, scaling, scaling, scaling)
            call MoveLocation(L, x, y)
            set this.z = GetLocationZ(L)
            return this
    endmethod
endstruct

public function Add takes unit hurter, real x, real y, integer projectiles, real scaling, real power, real angle, real rotation, string model, string post, real spreadXY, real spreadZ, boolean follow returns nothing
    local InstanceData array d
    local integer i = 1
    loop
        exitwhen i == projectiles+1
        call InstanceData.create(hurter, x + GetRandomReal(0., spreadXY), y + GetRandomReal(0., spreadXY), scaling, power + (projectiles/2 - i) * spreadZ, angle, rotation, model, post, follow).startPeriodic()
        set i = i + 1
    endloop
endfunction

endlibrary

EDIT: your edit confused me
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top