• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[System] Custom Projectiles

Level 18
Joined
Jan 21, 2006
Messages
2,552
It's good to see you giving me a link to where this mysterious "proof" is located at. All you've done is claim that it is better, over and over; and then whine when I show you real proof and call me a troll. Dude stay out of my thread you're trolling, and you're not benefiting this in any way other than spamming messages. You have nothing to say, and I have nothing to learn from you. Go away.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Again, you're simply asking me to re-do work that I have already done. I have told you already do not post back here and I'm serious - it is clear that you've got nothing to offer other than arguments based on words and opinions.

Anachron said:
If you do, you can compare our systems, if not, then for the hell don't claim your system to be the best out there.

Anachron said:
In fact I've proven more points that my system is better.

Don't post back here again, Anachron. I'm not going to waste my time going on your stupid goose chases; if you want to prove it to me then go ahead, but if all you're going to do is throw words at me then leave, nobody likes a troll.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Why are you lot even arguing over the speed of different solutions etc...

Considering people still use GUI, who cares if one is even 10% faster than the other.

The only real comparision points are functionality and robustness. Both of these should be pretty clearly difined and are ultimatly what makes the system useful to people.
Arguing which does this better is also pointless as if yours does do something the other does not, the end user will decide by comparing your systems him/herself.

Ultimatly you will always have to trade efficency for functionality. The more simple a routein is, the faster it will execute.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Okay I have just finished finalizing the fix for projectile's remaining in groups even if they are destroyed (would pose a problem if those indexes were refurbished and used again) - the best answer I could think of was using two hash-tables to efficiently maintain a list of which groups a projectile is stored in. It isn't very useful to the user, and at the moment it is simply internal - there won't be any change to the interface.

If any problems are found, please tell me so I can address them.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Okay I've updated the first post with the up-to-date system code, with a bug related to projectile-groups fixed. There are also some syntax updates, and I've removed method kill takes nothing returns nothing as it just adds confusion to destroying projectiles. Now projectiles may simply be destroyed by the default destroy method.

There's still some maintenance for version 2.0b; if you're going to download this download version 2.0 for now.

Okay I think I fixed it. It was a bad check in the setTargetPos method that would reject the command unless the unit moved in all 3 dimensions (usually units only move in 2 dimensions). It should be fixed now, I always encourage people to report problems/bugs to me though so I can address them. This means that 2.0b is now completely stable; I don't think there are any other mindless problems.

** Edit - Other than the debug message that I forgot in there **

By the way there are a couple of models in there that I swiped from a different map (awaiting approval before I actually use them) - these are not my models, do not use them in any way/shape/form; if they become acceptable to use in my test-map then credit will still be due to the original creator, of whom I will post his name upon approval to use them.

Also worth mentioning, when a projectile's speed is 0.00 (or the distance to the target is 0.00) the system will no longer wait the periodic interval before recognizing it. The onFinish( ) method will be executed immediately after onStart( ), before the end of the create method. I don't know who would use a projectile system for an instant projectile, but now the functionality is all there.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
This system was made awhile ago; I was only beginning to modularize my coding techniques when it was made. I wanted to completely remake the system but lately I'm focused more on real life; that being University and employment.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
You'd think so; it seems like it would be a lot more complicated if I were to eliminate the two hash-tables used for projectile/group referencing. There are only 255 hashtables available in any single game but I find that for a projectiles system using 3 is inconsequential. You can have up to 84 scripts in a map that actively use 3 hash-tables if you're looking to exceed that limit, which is an enormous amount for any size of project.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I don't care what you used, nor is it very important at this point. If I feel a need to come back and modify this (this isn't like a life-long project) I will, though it will probably be a complete re-script of everything.

Okay, well this was necessary. I've fixed a bug brought to my attention by Bribe that resulted when a projectile's target was removed from the game before the projectile reached it. The projectile would relay off at a terrible tangent and I don't believe it would be recycled properly. The bug has been fixed, and I've also included yet another member for users to take advantage of, the targetZOffset member. When a projectile is launched or setTargetPos is used this value is taken into consideration; this serves purposeful when setTargetPos is being called automatically internally such as when a target-vector is being updated to match the position of a tracked target (using activeTargetFollow).

The first post will be updated shortly; also worth mentioning I have fixed a "bug" in the test-map that would cause projectiles to be launched from the ground when you are jumping - this has been fixed and the projectiles launch from your current position, factoring in the unit's fly-height.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Another update; we're on version 2.1.1 - notice I've also replaced the version letters (a, b, c, ...) with another decimal.

Anyways, this is a relatively minor update; though it provides considerable usability enhancements. I've merely removed a state flag FLAG__onFinish that would prevent a projectile from executing its onFinish callback response method, and I'm not really sure why I implemented it in the first place.

It's a good thing I set up the order of things the way I did, because it is now possible (simply be removing the functionality of FLAG__onFinish from the system) to launch your projectiles from their onFinish method. If you launch the projectile again it will keep the same properties however so I suggest keeping an eye on it so that nobody runs into any problems (when trying to use them in this way).
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
enumNearby, could be used for projectile collision, so I was looking at the code and found some substantial room for optimization.

JASS:
    static method enumNearby takes projectilegroup g, real x, real y, real z, real radius returns nothing
        local real x2
        local real y2
        local real z2
        local vector v                  // To minimize repeated array lookups.
        local integer i = DATA__size - 1
        local projectile p
        
        set radius = radius * radius    // The math is performed only once.
        
        loop
            exitwhen i < 0              // Comparison to constant 0 is faster.
            set p = DATA__stack[i]
            set v = p.VECTOR__position
            set x2 = v.x - x
            set y2 = v.y - y
            set z2 = v.z - z
            if ((x2 * x2) + (y2 * y2) + (z2 * z2) <= radius) then
                call g.add(p)
            endif
            set i = i - 1
        endloop
    endmethod

It would be flexible if you made DATA__stack readonly as it would allow users such as myself to iterate through every projectile manually.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
So instead of using radius*radius just use another local variable. I suppose that would speed things up slightly, when there are a substantial amount of projectiles. For only a few projectiles it would probably slow things down. I really don't have feelings either way.
 
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

Freaks ... if I remember I started with vJass for 2 days and after reading all 12 pages about this system and after I saw the codes, my brain burns now.

Actually I have to say that I nearly didn't understand what you are talking here, because it's to high for me. But I like the system, looks good, works great ( so far as I can see ), it's fast and has no leaks, what you want more? =)

Also I checked Anachron system too and I understand the same as here .. NOTHING, but this system is cool too.

It's cool to have different systems with the same function at all, because everyone do his own way to create something like that. There isn't just one way to do that. Again I like both! and somehow I liked the "battle" between Berb and Anachron :p

Greetings and Peace
Dr. Boom
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Using the new Table I developed you can make projGroupTable a TableArray, projGroupTableRev another TableArray, projectilegroup.table a TableArray except for the -1 key which could just be a regular Table.

JASS:
globals
    private TableArray projGroupTable
    private TableArray projGroupTableRev
endglobals

private module GroupMod
    
    private static TableArray table
    private static Table tb
    
    private static method onInit takes nothing returns nothing
        set projGroupTable = TableArray[8191]
        set projGroupTableRev = TableArray[8191]
        set table = TableArray[8191]
        set tb = Table.create()
    endmethod
endmodule
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
I don't think it would be wise of me to promise anything, but there's always that slim chance. I wasn't under the impression there was much demand for this system to be recoded completely.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
He can do that if he wants to. I would not be offended even if I was going to recode it and release an updated library - I just don't see the point in it these days nobody plays Warcraft III any more and most of them just play DotA anyways.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Any chance of seeing this updated with the "total rewrite" you told me about?

I've just finished re-reading the 7 pages of this thread (I guess it depends how many posts you are displaying per page). I've seen some comments that I had overlooked (such as making the stack array readonly) and a few other functionality updates.

Earlier I had dismissed some suggestions to make modules that improve user-functionality, but later I implemented the ProjectileArt module which does just this.

Currently I am trying to make an efficient means of geometric collision detection and it has given me a couple of pointers on how I could improve the efficiency of this system even further. For example, I'm very surprised that nobody suggested removing many of my local variables and replacing them with static variables so the memory does not have to be allocated/deallocated on each call (which would seem to help out the loop method by a little).

I urge people who read this to try to think subtle things which they would like to see in an updated version. I want to dismiss projectile-projectile collision though - this would be an enormous endeavor for me to promise with efficiency, as while O(n²) is really simple is it also very slow.

With my geometric collision detection, I have been working with optimizing the O(n²)-time iterations to O(nlogn)-time. For those of you who don't really know what that means...

Let n = 128

n² = 128×128
n² = 16384

nlogn = 128×log(128)
nlogn = 128×7
nlogn = 896

There are possibilities in including this kind of optimization with this projectile library (as I complete it in my geometry detection library) but I don't want to promise anything just yet.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Well I never really got to updating much of this system but I decided to sit down for a couple of hours today and review the system.

I found that by exchanging the local variables in the onLoop method with static variables, performance actually decreased (so I left it as it was).

I wanted to add a few things that I never really got around to, such as having a method operator in the projectile-group struct for referencing members of the group with array syntax. In addition, as mentioned in my previous post, I have changed the stack/size to readonly so that users can now perform iterations on the entire stack of projectiles.

I also fixed an issue with destroying the projectiles in the onUnitCollision and onDestCollision which would cause a double-free of type projectileinterface message to be displayed. In order to fix this, I had to add a new member to the projectile struct. This member is named destroyed and should be used as a method to determine whether a projectile has been destroyed. The member is automatically flagged in the onDestroy method so the user does not need to worry about this, but instead of using if (proj != 0) then the expression if not (proj.destroyed) then can be used. This makes things a little more explicit. The destroyed member is public.

See the first page of this thread for the minor updates to the code.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Alright, sorry for the double-post but this next update is way more important than the first. Firstly, I combined the two projectile group-reference hashtables so that only 2 hash-tables are required by the system. To do this I simply added 8092 to the parent index (since it uses struct values, which will never be over that amount). If anybody can see any direct implications of this please notify me, though upon some brief testing it seems to be working just as well as before.

Secondly, I removed the boundary on how many projectiles can be stored in a group by removing the array altogether. This also means that more projectile groups can be created in general, though nobody is going to notice the difference unless they've got hundreds of projectile groups (which would probably be laggy).

If anybody notices any problems with this, please tell me. I'll update the first post in a second.

Oh, and I also cleaned up some of the unused code that was lurking in the map file. If anybody wants that useless code, or wants to refer to it, it should still be in the 2.1.3 download. The new version updated will be 2.2.0 in light of the more important changes.

Another thing to note is that the member indexOf[] no longer exists (though it did in any previous version) but if you want to update it all you have to do is replace projGroup.indexOf[ X ] with projGroup[ X ] - this shouldn't be too big of a problem.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Benchmarks have proven than a FirstOfGroup/GroupRemoveUnit/null filter is way faster than coding directly in the filter and returns false.
Simply because when the filter is not null, it opens a new thread each time it's called.
http://www.wc3c.net/showpost.php?p=1132297&postcount=4

Also you shouldn't use double underscore, as it's used by the vJass preprocessor.
Yes you are not likely to conflict with it, but still.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
Benchmarks have proven than a FirstOfGroup/GroupRemoveUnit/null filter is way faster than coding directly in the filter and returns false.
Simply because when the filter is not null, it opens a new thread each time it's called.
http://www.wc3c.net/showpost.php?p=1132297&postcount=4

Also you shouldn't use double underscore, as it's used by the vJass preprocessor.
Yes you are not likely to conflict with it, but still.

out from practical experience I can tell that this is wrong (or at least it was like that one year ago)
maybe it's because this example does not have a realistic number of conditions or the test map does not have a realistic count/mix of units but when I made spells back then using filter functions over firstofgroup enumerations could make a difference between 60 fps and 5 fps
I encourage someone to test this in a "real-life" environment
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
If the group enumeration goes over a field of corpses and I'm running through these enumerations in the same thread, then I'm likely to hit an OP limit. This is especially dangerous when you've got hundreds of projectiles. In terms of performance, I've done it both ways. Neither exhibited a noticeable performance increase from the other.

I agree with D4RK_G4ND4LF though I have never experienced a group iteration using a loop dominating the GroupEnumUnitsInRange filter in performance. The primary reason I do not want to use a loop with FirstOfGroup is because the OP limit also needs to be considered. I've been able to run 500 projectiles with unit collision without a drop in FPS below 60.0. If I've got a couple of units being collided with by each projectile, this runs the operations into the thousands.

There are many areas of error with these benchmarks you link to, it doesn't seem like any of them take into consideration things like system specs (which is very important when doing benchmarks). With only a single person doing the benchmarks, you cannot claim that one method of doing something is faster simply because it resulted in faster execution on a particular machine.

The "benchmark" may have some merit, but I need more real confirmation before I consider the possibilities in changing how I loop through units.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Also keep in mind Berb's computer is a beast, I can produce about 40-50 of his projectiles (without) collision enabled, on my computer, before I notice a drop in FPS. So what he says is 500 projectiles doesn't mean much to a lesser computer.

Edit: My results show that FirstOfGroup loop is a little less than twice as fast.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Edit: My results show that FirstOfGroup loop is a little less than twice as fast.

I'm still concerned about running into OP limits in the middle of execution.

I could however use a method of splitting up the operations into multiple threads... this might slow things down quite a bit though for the rest of the system while only benefiting unit-collision. I'm curious, when was this new efficiency of FirstOfGroup found? I've been told that GroupEnumUnitsInRange is faster than both, and I've been told that ForGroup is faster than GroupEnumUnitsInRange. Now I'm told that FirstOfGroup is the fastest. It seems like a bunch of nonsense to me. I'm curious, how many units is this being tested on? In the "benchmark" by Anitarf he claims it is 3x faster, rather than a little less than 2x faster - he is only testing it on 20 units though. Has anybody performed these tests on 50+ units?

Also keep in mind Berb's computer is a beast, I can produce about 40-50 of his projectiles (without) collision enabled, on my computer, before I notice a drop in FPS. So what he says is 500 projectiles doesn't mean much to a lesser computer.

I think that this would be a good time for me to actually state my system specs. I've got:
  • Intel i7 950 @ 3.8GHz
  • Nvidia GTX 465 (1 GB Video Memory)
  • 6 GB RAM

At 600 projectiles my PC still runs above 50.0 FPS, but quickly declines after that. I'm curious Bribe what kind of "noticeable" drop in FPS do you have with only 50 projectiles? What kind of machine do you have? I was able to get 150 without any noticeable drop in FPS on my MacBook Pro from 2006.

Without the limit on projectile-groups, I can have around 250~ projectiles in a projectile group until things start to get noticeable. I'm not really sure how this performs on many projectile groups separately throughout the map.

My computer runs StarCraft II at "Extreme" graphics because it is extremely processor-heavy. If you can, please tell me what kind of results you get and what kind of machine specs you're running on.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
This computer cost me less than $1000 almost a year ago. There is no excuse for having a computer that costs less than $500 unless you're a bum. What I should really do is send my code through the optimizer and then see what kind of performance I get. Usually that picks things up by almost double.

I encourage you to use this and tell me when you start to notice the FPS dropping (I'm not talking about 62-64 difference). Also please state your system specs.
 
Level 17
Joined
Apr 3, 2010
Messages
1,101
Mag you got ripped of. :L Sandy bridge all the way released this year. £300=3.4Ghz (dual core while using 2gb ram is able to use higher than 2gb ram
)
 
Level 16
Joined
Aug 7, 2009
Messages
1,403
WHAT?
This computer cost me $1700 over a year ago D:

I have:
- 4 GB RAM (Going to upgrade to 8 soon)
- Intel Duo-core Processor - 3.06 Ghz
- 256 MB of VGA

1700$ lolwut? I bought my PC this january for 500$ (without monitor, mouse and keyboard):

-AMD Triple-core CPU, 3,2 Ghz
-2x2 Gbyte DDR3 RAM (Kingmax)
-nVidia GeForce FX GT430 1Gbyte VGA (Asus)
-Gigabyte Motherboard
-500W PSU RaptoxX
-1 TByte HDD (Samsung)
 
Top