System Projectile

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I still think that it would be better to just mathematically calculate collision (see my example in the JASS discussion thread about this). :rolleyes:
Why not just try out how it works in terms of speed? I mean, if you are really interested in making this system good, you should at least consider trying it once, just to go sure its really slower than your approach.
 

Kenny

Back for now.
Reaction score
202
How do you recommend I implement it with homing projectiles?

I am not sure when to recalculate a projectile's collision time / how frequently to do it.

To me it just seems complicated to add it to something that has so much utility (ie. has multiple 'finish' conditions and stuff).

But if you have an easy way of doing it (which is also still accurate) I would love to hear it.
 

Azlier

Old World Ghost
Reaction score
461
Rectwraps would be easy to use, yes. But efficiency is veddy veddy important in projectile systems, and rectwraps do some operations when creating, moving, and destroying themselves that would not be useful in this situation to the best of my knowledge. It'd probably be better to hack together a homemade rectwraps that doesn't use those extra operations.
 

Viikuna

No Marlo no game.
Reaction score
265
The easiest way to do homing, is probably to have angle speed or turn rate or some value like that for x/y rotation ( example: xecollider ), and leave z arc unaffected by homing.

( Thats how wc3 projectiles work anyways. Of course you gotta change total lenght of arc, so projectile dont hit the ground too early )



Also, Im not sure about the speed of those rect thingies you are trying to put together, but all you really need is one GroupEnumUnitsInRange + filter, and it should be pretty fast.


If you worry ablout projectile on projectile collinsion, just dont use locust but corpses instead. ( There is some old thread in wc3c about this. Sorry about not remembering it in that thread you had here aboout projectile on projectile collinsions )

Corpses are unselectable, but their animations work just fine. You just gotta suspend corpse decay and everything is all right. They naturally get grouped by GroupEnumUnitsInRange.

edit. Of course this is only an option for guys who dont use ladder wc3 abilities like raise dead, but trigger their abilities instead.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I am not sure when to recalculate a projectile's collision time / how frequently to do it.
You recalculate it every time a missile:
- is created
- changes move direction instantly
- every 0.x seconds for homing missiles
- is slowed/fastened

This equals up to only one comparison for linear missiles and n comparisons for homing missiles.
To me it just seems complicated to add it to something that has so much utility (ie. has multiple 'finish' conditions and stuff).
This doesn't change anything in the utility you can add. It just replaces EnterRect and UnitEntersRange by a mathematical function.

But if you have an easy way of doing it (which is also still accurate) I would love to hear it.
I posted everything in the JASS discussion thread about projectile systems some time ago.
And in terms of accuracy, you probably can't do better than by calculating the ETA mathematically.
 

Viikuna

No Marlo no game.
Reaction score
265
I know that GroupEnumUnitInRange aint too fast, but I find it hard to believe that there could be any faster way to do actions for all units in a circular area around the projectile.

Its just one function call + that filter thingy, after all.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
I know that GroupEnumUnitInRange aint too fast, but I find it hard to believe that there could be any faster way to do actions for all units in a circular area around the projectile.

Its just one function call + that filter thingy, after all.
This is not the point. The problem of periodic enumeration is, that:

a) you can not determine the *exact* collision spot and thus can not create something like reflection, impulses, etc. ... but yes, for this system, this point doesnt really matter.

b) depending on the collision size of the missiles and the move speed, you need an extremely high check intervall

Beating the problem down to vector algebra highly reduces the number of periodic checks.
Missiles, that are not changing direction or move speed wouldn't require periodic checks at all.
 

Viikuna

No Marlo no game.
Reaction score
265
How fats that calculation would be?

If theres lot of outside sources changing projectiles direction or homing or stuff like that, you need to recalculate that shit again.
 

Zwiebelchen

You can change this now in User CP.
Reaction score
60
How fats that calculation would be?

If theres lot of outside sources changing projectiles direction or homing or stuff like that, you need to recalculate that shit again.
There was this discussion starting at page 3 of this thread: http://www.thehelper.net/forums/showthread.php?t=145882&page=3
I also posted the code for the calculation at the bottom of the page. Its a lot of maths, but I am still sure that - if used very smart - it would still be faster than UnitEntersRange.
 

Viikuna

No Marlo no game.
Reaction score
265
Isnt that about projectile on projectile collinsions? You still need to detect when projectile hits some unit, and you can really foresee where those units are gonna be.

-GroupEnum does both projectile on projectile collinsions and projectile on unit collinsions.

-That unit comes in range is delayed as hell, and looks really fucking ugly. I have used it and it sucks.

-That region stuff would othwerwise be cool, but we dont really have circular regions.



The thing is that you cant really create a fast generic projectile system. You have to compensate and design your map so that you can do more with less projectiles.

More with less, lols.

Of course if you are making some shooting map, where there is only bullets that move straight and with constant velocity, this aint the system for you.

This should be more about normal wc3 projectiles, such as archer arrows, stor bolts and carrior swarms.

At leats this is how I see it.
 

Anachron

New Member
Reaction score
53
Pros:
  • Detects projectile collisions
  • Well coded
  • You can easily get a missile by passing the unit as parameter.
  • You have MissileGrouping functions

Neutral:
  • Uses an hashtable to store data.

Cons:
  • To many used librarys. There isn't a need for all of them.
  • You use function interfaces to set events. Please use stub methods instead. (You can check how its done on my CustomMissileEngine)
  • The amount of structs for this system which are needed is horrible.
  • You don't have xyArc, neither zArc.
 

Kenny

Back for now.
Reaction score
202
Wow, haven't posted here in a while...

Anyway, I am finding it increasingly difficult to find time to update this to match my expectations, so whoever put this here, thank you.

Anarchron:

Thanks for looking over my system. I have looked over yours recently and really like it. The 'modularity' or the code is something I was hoping to do with mine after I got all the basics down.

A couple of things though:

  • I don't see how using a hashtable to store data is a neutral thing. If anything, for how I am using it, it should be a positive, because it is the safest way to do so. And it is still quite fast.
  • As for the cons. I know it uses a fair few libraries, but it is to ensure that it is as efficient as possible. I have actually tested mine against yours, and mine could handle a fair bit more projectiles on the laptop I was using. No, I did not empirically test it, so I cannot prove it, but I wouldn't say it otherwise.
  • Last time I checked, JassHelper did not handle extends properly (hense the reason for using function interfaces). In previous versions, I used an interface for the events but I changed to a safer option (there is something wrong with multiple levels of inheritence in vJass). Also, you don't need stub methods.
  • I don't see an excessive amount of structs in my script. They were developed for a reason, to be used. They allow for excapsulation and cleaner coding, as well as more efficient coding in some circumstances. Structs are good, don't be afraid of them.
  • No I do not have xyArc in this, although I wanted to some time down the track. But I am pretty sure it has zArc already (.projectArcing method).

Anywho, thanks for the comments.

This is what I wanted to get done with this system:

  • Add proper homing capabilities (with adjustable turnspeeds), that could better represent wc3 attack missiles.
  • Add destructable detection.
  • Clean up the code to make it more modular and a little more efficient.

And honestly, for the first of what I wanted to do, it is difficult due to how [ljass]SetUnitFacing()[/ljass] works with homing, arcing missiles that target units. I doubt any one will ever get it right.

It would be really nice if another projectile system out there (looking at you Anarchron) added GroupProjectilesInRange() functionality like there is in this system. As i believe it is the best way to go about it.
 

Kenny

Back for now.
Reaction score
202
I'm probably going to be updating this very soon, so if a moderator would like to take it out of the graveyard that would be awesome. :)
 

Sevion

The DIY Ninja
Reaction score
413
TBH, this could be done with just T32x. It doesn't need any of the others ;)

Actually, it doesn't even need T32x. Just hardcode a timer loop and then you get both access to T32x AND a linked list.
 

Kenny

Back for now.
Reaction score
202
Updated first posts with latest version.

@Sevion:

I understand that this system does require a fair few systems, but I find that they are all pretty important to how this system works as a whole. For example:

AIDS: Required for unit to projectile typecasting. This is probably the one system I might try to get rid of.

T32: I could just use a hardcoded timer loop, but T32 is there for a reason, to be used to get that extra speed boost.

Event: Required for the global projectile on projectile collision event. I actually find this very useful. And this functionality would be difficult without Event.

Vector: Well this one is pretty obvious. It makes maintaining this system easy and keeps the script neat. It is also heaps easy to write with.

AutoFly: Again, I could get rid of this. But it is very useful. I think every map should have something like this.

GroupUtils: Again, this is something that most maps should have. I guess I could internalise the group recycling though...

ListModule: This is important for me to keep track of both projectiles and projgroups. It functions well and I don't think there is a need to get rid of it.

Thanks for the comments though, it made me think about a few of the required systems. I might get rid of one or two of them in the future.

Edit:

I have made a build without AutoFly and everything seems fine. I will think about removing GroupUtils and possibly AIDS as well in the future (removing AIDS would mean no unit to projectile typecasting, but due to the new projgroups that form of typecasting is rarely needed).

Just did a little bit of stress testing for those who care. With projectile recycling enabled I had approximately 120 projectiles (non-homing with dest and proj collision disabled) with around 38.00 - 40.00 FPS. Without projectile recycling enabled I had approximately 120 projectile (same conditions applied) with an average FPS of around 28.00.

I did a quick comparison with Berb's system (over at THW) and found that I could handle around 120 projectiles (with similar conditions) with with an average of around 15.00 FPS.

Interesting stuff. :D
 

Sevion

The DIY Ninja
Reaction score
413
To be honest, I've never EVER had a use for any unit indexing systems... >_>

T32, the hardcoded timer loop wouldn't lose any efficiency to be honest. If there are no projectiles running, pause timer. On creation, resume timer.

Event, use stub methods ;)

Vector, with or without. I've never wanted/needed to use this system.

AutoFly, this is nice to have, true, but it's also more efficient to hardcode this.

GroupUtils could be replaced with Recycle, but then again, a private global group can be used.

ListModule, use your own next and prev members.

In fact, this is what I like to do:

JASS:
struct myStruct extends array
    private static integer instanceCount = 0
    private static integer array recycle
    private static integer recycleCount = 0
    private thistype next
    private thistype prev

    public static method create takes nothing returns thistype
        local thistype this

        if ( recycleCount != 0 ) then
            set recycleCount = recycleCount - 1
            set this = recycle[recycleCount]
        else
            set instanceCount = instanceCount + 1
            set this = instanceCount
        endif

        set thistype(0).next.prev = this
        set this.next = thistype(0).next
        set thistype(0).next = this
        set this.prev = thistype(0)

        return this
    endmethod

    private method onDestroy takes nothing returns nothing
        set recycleCount = recycleCount + 1
        set recycle[recycleCount] = this
        set this.next.prev = this.prev
        set this.prev.next = this.next
    endmethod
endstruct


Then, it's easy to do a hardcoded loop:

JASS:
struct myStruct extends array
    private static integer instanceCount = 0
    private static integer array recycle
    private static integer recycleCount = 0
    private static integer PERIOD = 0.0325
    private static timer time = CreateTimer()
    private thistype next
    private thistype prev

    private static method periodic takes nothing returns nothing
        local thistype this = thistype(0)

        if ( this.next == 0 ) then
            call PauseTimer(thistype.time)
        endif

        loop
            set this = this.next
            exitwhen this == 0
            // do stuff
        endloop
    endmethod

    public static method create takes nothing returns thistype
        local thistype this

        if ( recycleCount != 0 ) then
            set recycleCount = recycleCount - 1
            set this = recycle[recycleCount]
        else
            set instanceCount = instanceCount + 1
            set this = instanceCount
        endif

        set thistype(0).next.prev = this
        set this.next = thistype(0).next
        set thistype(0).next = this
        set this.prev = thistype(0)
        call ResumeTimer(thistype.time)

        return this
    endmethod

    private method onDestroy takes nothing returns nothing
        set recycleCount = recycleCount + 1
        set recycle[recycleCount] = this
        set this.next.prev = this.prev
        set this.prev.next = this.next
    endmethod

    private static method onInit takes nothing returns nothing
        call TimerStart(thistype.time, PERIOD, true, function thistype.periodic)
    endmethod
endstruct
 

Kenny

Back for now.
Reaction score
202
To be honest, I've never EVER had a use for any unit indexing systems... >_>

I was like that once too. Then I found a need for it, then realised how incredibly handy it is. If you have another way to do unit to projectile typecasting that is more efficient than an array look up + function call (I think), then I will change it, but for now it is the best option.

T32, the hardcoded timer loop wouldn't lose any efficiency to be honest. If there are no projectiles running, pause timer. On creation, resume timer.

You would be surprised. I originally had this only using a timer loop and it was slower than using T32, then I went and scabbed T32's internal mechanism, but that is just uncool.

Again, there is a reason these systems are released.. To be used.

Event, use stub methods

That would defeat the purpose of it being a global collision event. Also, this system does not require users to extend structs (vJass inheritence is flawed when it comes to extending structs and implementing modules, therefore I have decided to steer clear), therefore stub methods are unusable.

Vector, with or without. I've never wanted/needed to use this system.

When writing a system like this, you can be assured that you will find a need for a system like vector. It also comes down to personal preference.

AutoFly, this is nice to have, true, but it's also more efficient to hardcode this.

Actually I would say that AutoFly is as efficient as adding and removing the crow form ability when needed (they are both only adding and removing an ability, efficiency is not the problem here). The thing about AutoFly is the convenience. I, nor anybody else who imports that snippet, will ever have to do something so tedious again. That is a major plus.

GroupUtils could be replaced with Recycle, but then again, a private global group can be used.

A global group cannot be used, as that would cause problems with a single unit being added to the groups of multiple projectiles, making damage events bugged.

And I actually wrote the first version of this that used GroupUtils before Recycle was out. So yeah I could change to that, no biggie.

I've gotten rid of both GroupUtils and AutoFly in my current internal build by the way. Just testing it to see how it runs.

ListModule, use your own next and prev members.

To be honest, I could, but I see no benefit in doing so. ListModule gives me simple methods that do what I need to do. It also stops visual code bloating. It really just makes the script easy to maintain.

Also, since when could you declare onDestroy in array structs? Have I been gone that long?

And why are you using array structs anyway? I see no advantage in doing so.
 

Sevion

The DIY Ninja
Reaction score
413
What do you mean hardcoded timer loops being slower than T32???

It's the same thing... That's what T32 is. The only difference is that T32 is a module.

AutoFly is basically only 3 lines. On creation. Thus, it only affects the units you need it to.

Using your own list is actually not bloated at all. And it IS easy to maintain. Just look at my example above to see my linked list.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top