• 🏆 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!

Editor and coding questions

Status
Not open for further replies.
Level 10
Joined
Apr 9, 2004
Messages
502
I have a couple questions regarding how I can manipulate functions to simplify some the systems I've been working on. I've just gotten into using a unit indexing system to build my systems (the one bribe made) and I'm wondering if there's an efficient way to allocate an array variable to an array unit.

For instance each unit has a custom value assigned within the system so I can recall any one property by simply looking up property[custom value of manipulated unit].

However what I'm trying to do is simplify the process for stacks of variables that could normally be grouped as arrays.

The specific example I'm looking at right now is for a cooldown system I'm working on.

At the moment I have to create a new variable for each specific cooldown instance that a unit is subject to. (i.e. a unit can have up to 6 unique spells they can cast, therefore I need 6 unique cooldown arrays)

So what i was going to do was simply create 6 arrays variables Cool1[]-Cool6[] and link them such that i manipulate Cool1/2/3/4/5/6[custom value of manipulated unit] to control each cooldown instance for the specific unit I'm manipulating at that very moment.

What I'm looking for is something where I can have an array for the cooldown and manage it by referencing back to the unit custom value for lookup, essentially an array within an array

so for instance my code would be something like

for each integer A from 1 to X
set Cool[A] related to unit[custom value of manipulated unit] to XXX

I want to do it this way because at the moment I'd have to individually check each instance of the Cool1-6[] arrays rather than use a loop command to handle this more efficiently.

I just want to know if there's a simple way to stack this, I can't think of one without using a more complicated system.

One thought I had considered was if there was a way to use and manipulate string data to lookup a variable name and get sort of the same effect that way instead (i'd have to use a specific naming convention and filters to get the actual integer information) but again I don't think it's possible.

Right now I'm stuck at a question that's probably been answered but I couldn't find even a remotely similar thread on the subject so it might be a simple "yes this is possible" or "no this is not possible" but I'd like to know if anyone knows how I can deal with this.
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Use hashtables. They are basically 2d arrays. Use the parent key to reference the unit and the child key to store your data. You can either use bribe's unit indexer for the parent key or the GetHandleId function. You can then loop over the different child keys.

Instead of always using custom value of ... in the index, you should save the custom value to a temporary variable and use it instead. It's faster for you and for the game.
 
Level 10
Joined
Apr 9, 2004
Messages
502
I was hoping of staying away from hashtables and trying to keep everything to arrays as I thought they were faster and more efficient but just limited to the 8000ish max capacity which is bigger than I would ever expect to reach. Also I understand how to use and manipulate arrays better than I do hashtables so that's another reason I'm avoiding using them.

I'm terribly noobish when it comes to actually using and writing jass code I can do basic things but I always get screwed up in the syntax.

As for saving the variable, simple enough simplification.

I've been doing some thinking and in my case would it be an acceptable method to simply have a sub-index tied to each cooldown event and just cycle through that rather than try picking every unit and figuring out how many cooldowns they had going?

I was thinking simply track each cooldown event and just flow through each instance. I can save the specific unit and functions associated with that.

My only concern is whether this method still allows me flexibility to communicate with other variables and systems that might tie into it (i.e. systems that can affect cooldown)
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I was hoping of staying away from hashtables and trying to keep everything to arrays as I thought they were faster and more efficient
If there is a difference at all, it would be extremely miniscule. Unless you do a horrible job with your data structure, you should worry more about convience and ease over performance / efficiency.
 
Level 10
Joined
Apr 9, 2004
Messages
502
Hmmm I've read on multiple occasions that hashtables should only be used if there's a requirement for storing information that goes beyond that 8000ish limit you get with arrays and that that factor was the main advantage. Also if we're talking about operations that happen very frequently, the speed difference, might that have a much larger effect?

Side note, New question regarding memory usage and performance based on abilities created and saved to the map. I.e. how much memory does 1 ability with 4 levels or less take? I heard anything over 4 levels slows down loading by a lot. If that's the case what would be more effective, having 1 ability with 1000 levels or 1000 abilities with 1 level or 250 abilities with 4 levels? Are there factors that would reduce the load per ability (i.e. would clearing and null-ing as many fields as possible on said single-level abilities reduce the time they take and time to generate during map loading?

What will affect loading time and what will affect actual in-game performance?

Ideally I'd like to use 1 ability with numerous levels specifically because I can easily control multiple aspects by simply controlling 1 integer and adjusting the values based on the actual abilities

My main reason to ask this is I'm trying to figure out the feasibility of having automatic updating tooltips. For instance, as I add more than 1 updating parameter that changes the number of levels or base abilities grows multiplicatively
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
how much memory does 1 ability with 4 levels or less take?
Probably an amount that is trivial to every modern computer. Memory is never really an issue in WC3.

If that's the case what would be more effective, having 1 ability with 1000 levels or 1000 abilities with 1 level or 250 abilities with 4 levels?
For such dynamic support I would recommend 1 ability with 1 level and triggered effect.
 
Level 10
Joined
Apr 9, 2004
Messages
502
ok. Sounds good. Also, even if memory for a computer isn't an issue, does that not affect the map size?

I just want to make sure I don't generate lag spikes or severe slowdowns by having thousands of abilities to reference or anything of that sort.
 
Level 7
Joined
Jan 23, 2011
Messages
350
The WorldEdit malfunctions when you reach 500 custom abilities, you should know that, i think that, for your necessities(is that spelled correctly?) you should work with slk archives. DotA has a lot of abilities with a lot of levels, yet it charges in 15 seconds
 
Level 21
Joined
Dec 4, 2007
Messages
1,478
The WorldEdit malfunctions when you reach 500 custom abilities, you should know that, i think that, for your necessities(is that spelled correctly?) you should work with slk archives. DotA has a lot of abilities with a lot of levels, yet it charges in 15 seconds

Is that true? What kind of malfunctions do you know of?
 
Level 10
Joined
Apr 9, 2004
Messages
502
The WorldEdit malfunctions when you reach 500 custom abilities, you should know that, i think that, for your necessities(is that spelled correctly?) you should work with slk archives. DotA has a lot of abilities with a lot of levels, yet it charges in 15 seconds

So can I setup all of my dummy spells in the slk archive instead then? Because that's not exactly hard to manipulate
 
Level 7
Joined
Jan 23, 2011
Messages
350
I know that after a lot of abilities, when you create a new one, it just creates a previous ability and you have two abilities with the same rawcode and the only thing you can do is erase abilites

The word for "charge" and "load" is the same in spanish, and i took them as synonims

And yeah, i think you could just use the slk archives to set up your abilities. Didn't work a lot with those tables, but i don't see any reason for them to not work
 
Level 10
Joined
Apr 9, 2004
Messages
502
I'm wondering if that limit of 500 is true. Just based on the names i created anything from A000-A999 all the way to Z000-Z999 don't use any existing space. Sometimes depending on how the object editor actually creates spells it may overwrite a code but if you use the JASS Newgen editor you can define all of your custom ability rawcodes. I haven't tested my theory but I'm wondering if this is just a weird thing with the normal editor?

Regardless if you can show how I can modify the origional slk file I may opt to do that instead.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
I was hoping of staying away from hashtables and trying to keep everything to arrays as I thought they were faster and more efficient but just limited to the 8000ish max capacity which is bigger than I would ever expect to reach. Also I understand how to use and manipulate arrays better than I do hashtables so that's another reason I'm avoiding using them.
Yay, here we go again... no real offense though.
As for someone who is not really into diving into massive threads that might explain how things work in WC3, I couldnt really blame you.
But its very simple, hashtables are slower as hashtables generally have to generate an index and then load the value from an array, and in case of collision, loop through an (very small) array until it finds your data. So in common sense, they are slower.
However, when it is considered common sense to use it. Aka, if you have 2 keys, massive data, enormous high keys or skipping a shit ton of indices, use a hashtable.
If you have maybe 10 or 20 values you want to store with 2 keys going from 0 to 3/4, then you can ofcourse also use a single array, but for most cases you should be fine with a hashtable.
The difference in performance only matters (for some people) when you are doing a shitload of reading/writing on a very high frequency.

I was thinking simply track each cooldown event and just flow through each instance. I can save the specific unit and functions associated with that.
That is a very good idea. (Almost in the sense of object orientation.)
Every time a unit casts a spell, you load in a not-yet-used-index, then you can put the caster in a unit array, the timeframe in a real array and the duration or end timeframe as well, the ability in an integer/ability array, maybe a timer that expires when the cooldown ended, etc.
That way, one unit could have 8191k abilities all on cooldown without problems... as long as he is theonly unit having abilities on cooldown.
And on the other side, you could have 8191k units with each one ability that is on cooldown.

My only concern is whether this method still allows me flexibility to communicate with other variables and systems that might tie into it (i.e. systems that can affect cooldown)
This is indeed one of the drawbacks from it... you cant really have something that doesnt have any drawbacks by default, but we can work around them.
With this approach, it would be very costly to say, search for the cooldown value of unit X for ability Y as the system would have to loop through all instances of the active cooldowns to check if the caster matches and the ability matches.
In the case of hashtables, this would be very easy if you say the unit is the parent and the ability is the child. However, then you cannot really loop through the list.

In my spell cooldown system, I use a so called linked list.
Its basically an array with an arbitrary order, where each element would have the knowledge of which element the next is and which element the previous is.
And instead of 1 massive list, I have a list for each individual unit all stacked up in one array (because I can :D).
That way, I can loop through all cooldowns of a specific unit to make this search way shorter.
And I can still loop through all cooldowns by looping through all units that have a cooldown (which I put in a group).
This method, even though it sounds like it is doing way more work, is actually almost equally as fast.

The problem is, that this is not so easy to implement, and definately not in GUI.
A more easier solution would be to use the first idea again, where you just fill a massive array with all the active cooldowns and that you also have a hashtable where you store the index of the instance on the unit and the ability as keys.
This will allow you to have (probably) the fastest way of getting the values of the active cooldown by far... and there is no difference in speed when there are 8 thousand active cooldowns.
(This will however again not allow you to loop through all active cooldowns of a specific unit, for which you maybe should use the linked list approach, but you are probably not going to need it anyway.)

On a side note, that limit of "500" does exist... but it is not 500, but rather 20 thousand iirc.
In my system, I use a very powerful trick.
I have one ability that has x levels where each level has "0.1 * level" cooldown. (so with 300 levels, every value between 0.1 and 30.0 seconds)
I swap the original ability with this one, then I set the level to the approximate cooldown I want, then I activate the cooldown, then I swap them back and the cooldown remains.
So, with this one ability of 300, 400, 500 or higher (depending on the maximum cooldown of your abilities) levels can do all the cooldowns on its own.
The only other thing is that you require a swapping ability for each ability, but that one only needs 1 level and the base ability can still have full control over its other properties like tooltips.
Its something that is hard to properly implement, but really powerful when you are able to use it.
 
Level 10
Joined
Apr 9, 2004
Messages
502
Update on this.

In the spirit of getting something up and running as the basis I've modified my approach slightly.

I'm not sure how much worse it is but I've essentially setup the system when the unit is the master and all variables I want to watch are linked to them. The code looks a bit clunkier now but I instead manage data manipulation with unit groups. In that sense when i put a unit in a group, it only picks the units that are on cooldown and checks all 6 cooldown slots each to see which ones are active (active if the cooldown is greater than 0).

It's probably not as efficient but it allows me the ability to manipulate all the cooldown data at any time because 99.99% of all events are going to happen to a unit, so this way it's easy to lookup which unit I'm dealing with using custom value and then pull whatever associated variables that I've already stored to that unit. In that respect, does this make things worse or just different? Trying to figure out a bug in the system but once it's setup properly I'll get a testmap out.

In regards to your method, are you simply swapping the ability using the reverse engineering upgrade hack?
 
Status
Not open for further replies.
Top