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

(more than one) Custom Value

Status
Not open for further replies.
Level 7
Joined
Jun 16, 2008
Messages
253
Is it possible to assign more than one set of custom value to a unit?

I know there isn't any natural provision for it in the editor, but is there any way that it could be done or achieved?

For example a certain unit has a custom value of 50 which represents how much money he has, but he also has a seperate custom value of 20 which denotes his bartering skill.

I'm sure there are lots of hidden values like this that are applied to units in the game, such as the hidden lumber or gold counter that units acquire when harvesting. And I would love to know how that's done, because individual set and forget stats would be hugely useful in my map.

Could anyone help with this?
 
Level 7
Joined
Jul 20, 2008
Messages
377
Use custom values like an ID number for the unit. My advice is to assign to each unit an UNIQUE custom value. You'll need a global integer to keep track of the ID to assign to each unit. For example:

Set Unit Custom Value to assignID
Set assignID to assignID+1

Now, you can have any number of array variables whose slot correlates to this custom number.

i.e.,

MoneyofUnit[custom value of unit]

In this example, MoneyofUnit is an array of integer variables where the slot correlates to the custom value of an unit.

Get it?
 
Level 7
Joined
Jun 16, 2008
Messages
253
Wow, I od actually, that's brilliant. I guess I can just stick the units in unit groups to indicate if they are busy/idle and stuff etc. You can put them in more than one unit group can you?

Anyway thanks a lot, problem solved!

Erm... how do you change prefix from unsoved to solved?
 
Level 7
Joined
Jul 20, 2008
Messages
377
Yes, you can put units in multiple unit groups. Also, the mods are the ones that set the prefix to solved, I think. :)
 
Level 7
Joined
Jun 16, 2008
Messages
253
Ah goods to knows. Actually, I don't need unit groups as much as I thought. This unit ID thing opened up a whole vista of possibility that i wanted from the beginning (though the game complains when I make the arrays too high, also takes a memory exception to it). I actually had a note saying I wanted this very UnitID thingy, just wasn't quite solid on how to do it. Much easier when it's pointed out. :D
 
Level 7
Joined
Jul 20, 2008
Messages
377
Well, one way you can avoid the huge array issue is to constantly re-sort your arrays. When you remove or kill an unit, for example, you'd want to remove all data associated with that unit and then re-order everything so there are no gaps in your arrays (move all data in slots AFTER the slot of the unit being removed to the slot behind what you're moving), then you subtract one from assignID. That's a good way to keep away from high arrays.
 
Level 7
Joined
Jun 16, 2008
Messages
253
Cheers. I'll stick your name in the credits of map cos you solved like the hugest problem of the map. :D
 
Level 7
Joined
Jun 16, 2008
Messages
253
Um, quick question (you can keep thread Solved, mods) how would you suggest resorting arrays? I already learned about simply doing the assignID - 1 thingy from that War3 map The Obelisks or something.

But if say I have 300 units, and unit 255 dies. How would you suggest I shift the remaining 45 units back a step? I guess I could go pick every unit with custom value greater than 255, and then go set custom value to custom value - 1. But then I'd also have to do the same for every other related stat. Oh well, spose it's not that huge of a deal.

Is there a simpler way to do it, do you think?
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
You simply have 1 global integer that holds the position of the last unit in the array. When a unit is removed from the array, you first swap the unit to be removed with the last unit, then you remove the "new" last unit and decrease the global integer that holds the position of the last unit.

Example:
1-2-3-4-5-6-7 Global integer position 7 means unit 7

Remove 4: swap 4 with 7
1-2-3-7-5-6-4 Global integer position 7 means unit 4. Now remove 4:

1-2-3-7-5-6 Global integer position 6 means unit 6.

Anyway, I suggest you simply use structs and use the struct id as a custom value. Way easier.

EDIT: I just read your question was how to SORT an array... I suggest you read some wikipedia articles about that. The easiest to do is probably Insertion Sort, if you're not experienced with sorting algorithms.
 
Level 7
Joined
Jun 16, 2008
Messages
253
Unfortunately, my understanding of the above is limited. I believe I skimmed a little article that mentioned structs in the JassNewGen manual, but was completely oblivious. (I was looking for something else at the time.) But don't actually know what it means. I wouldn't bother trying to explain the whole thing to me cos it sounds involved, and it would probably be easier just for me to go read up on it.
If the struct id is just the unit ID thing I've got installed I'll feel a bit silly though.

And nope, not experienced, my knowledge of algorithms is limited to the fact that it's something brainy to do with programming that you hear about all the time on movies.
It always made me think of music for some reason. :D

I should learn fairly quickly though, when I find an article on it.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Reading your problem again, I think what I first proposed will still help you fix your problem.

Anyway, in short, a struct is a "collection" of variables which are associated with each others. For instance:

JASS:
struct FishingSystem
    unit aunit
    integer fishes
endstruct
Would basically make an object that contains a unit and an integer.
In this case, the unit in the struct would "have" an amount of fishes
Every struct that is created has its own unique identification, and basically it's the same story then: you set the custom value of a unit to the struct, and next time you can use the struct that is "stored" inside the custom value to associate it with the unit variable and the fishes variable inside the struct.

More or less, that is. It works completely different internally, but you don't really need to know if you don't know much jass...
 
Level 7
Joined
Jul 20, 2008
Messages
377
So wait, Alakon, do you need it SORTED or just where there's no hole in your array?
 
Level 7
Joined
Jun 16, 2008
Messages
253
First off- thanks Eleandor, structs sound like they will be extremely useful for the map, I'll have to try and see what I can do with them. You definitely sound right, structs would simplify a lot of things. Cheers.

Second - Soga, I just want it so that if I have an array of 1000, say, (because of other related variables) that the 1000 won't be exceeded.

That if a unit that's using 255 as ID dies, then his slot of 255 will be used and not forgotten. So all I have to do is make sure the units on the map don't exceed 1000, and the array can keep getting reused.

Do you see what I mean?

EDIT: In other words, just no hole. :D
 
Level 7
Joined
Jun 16, 2008
Messages
253
I do, or at least I think I do, but I don't think that solves the problem. Besides which, what happens when the value goes up in digits, I might have a string taking 1,2, but then the money goes from 50 to 500. It'll still read like 50, and stuff up everything else.
I got attaching values and the like to a unit sweet as, thanks to Soga's ID suggestion, and now improved with Eleandor's struct's.
I just want a method for reusing the slots that dead units have vacated.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Here you are, in pseudo code:

Variables:
UnitStack - A unit array which relates to all your custom value arrays as you will see below
(All your "Custom Value" arrays)
MaxSlot - An integer which is always the next available slot in the array (defaults to 1, so you don't have problems with unallocated units (custom value 0))

Allocate new unit custom value:
Set (Unit) Custom Value = MaxSlot
Set UnitStack[MaxSlot] = (Unit)
(Initialize all "Custom Value" arrays in the same way as UnitStack)
Set MaxSlot = MaxSlot + 1

Deallocate custom value:
Set MaxSlot = MaxSlot - 1
Set UnitStack[CUSTOM VALUE OF DEALLOCATED UNIT] = UnitStack[MaxSlot]
(Do the same as above for all "Custom Value" arrays)
Set UnitStack[MaxSlot] Custom Value = CUSTOM VALUE OF DEALLOCATED UNIT
(IF THE UNIT ISN'T GONE FROM THE GAME) Set (Old Unit) Custom Value = 0


In all seriousness, structs are way less trouble and more syntactical sugar.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
You simply have 1 global integer that holds the position of the last unit in the array. When a unit is removed from the array, you first swap the unit to be removed with the last unit, then you remove the "new" last unit and decrease the global integer that holds the position of the last unit.

...

Use that if you don't want any holes.
Basically, you assume the array is filled all the way up to position last_filled_index. Yuo can assume this is true as long as you keep adding units and never remove one.
Whenever you need to add a unit, you add him at index last_filled_index+1 and increase last_filled_index.
Whenever you need to remove a unit, you put the unit at position last_filled_index at the position where the last unit was just removed. Then decrease last_filled_index. This way you again will have a filled array.

Another example:
Empty array - last_filled_index = -1
Add "5":
5 - last_filled_index = 0
Add "3"
5, 3 - last_filled_index = 1
Add "2", "6", "13"
5, 3, 2, 6, 13 - last_filled_index = 4
Remove 3:
5, 13, 2, 6 - last_filled_index = 3. You simply removed 3, then there was a hole between 5 and 2, so you put the last added integer (which is 13) there and decrease last_filled_index.
 
Level 7
Joined
Jun 16, 2008
Messages
253
I'm having a little trouble wrapping my head around the post, though I think I grasp at least the basic concept.

I have it the other way at the moment btw, I add unit to index last_filled_index then go last_filled_index + 1.

Do you think it would work if I go (roughly)
when a unit dies, I remove him from index.
Then when a unit is created I go (integer A) from integer 1 to last_filled_index,
if there is unit [index (integer A)] = none then add unit to [index (integer A)].
and then if integer A is equal to last_filled_index, go last_filled_index + 1.

That way it keeps filling up the plugs. Though, the maximum would never reduce in this method I suppose.

What dya reckon?
 
Level 7
Joined
Jul 20, 2008
Messages
377
Purple, that leaves gaps. There should be a loop in there that runs through the rest of the array to "move back" each value by one slot.
 
Level 7
Joined
Jun 16, 2008
Messages
253
Okay, I just wasn't quite sure of all the facets. Such as, if I change the last filled position to whatever position has just been vacated, how do I tell it to go back to the end of the line after or whatever?
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Purple, that leaves gaps. There should be a loop in there that runs through the rest of the array to "move back" each value by one slot.
No it doesn't. The system works an entirely different way. The array is dynamically resorted in O(1) rather than O(n).

Due to the lack of general understanding of how that method works, I plan on writing a tutorial about it tomorrow.
 
Level 7
Joined
Jul 20, 2008
Messages
377
Oh, I just took a closer look at your stuff, PP. I should've seen that it was swapping the unit at the END of the arrays with the one you are deallocating. Why didn't I think of that before?
 
Level 7
Joined
Jun 16, 2008
Messages
253
AH! Now I fully understand.

I finally understand how it actually works, instead of flipping the variable integer 'position' around, you just move the last unit into vacated spot, via custom value of vacating unit, and just -1, because the list is now just 1 shorter.

I was on a different page b4 but I gets it now.

PP, the unitstack thing looks good, means that you won't have more than one unit with the value. Hopefully though I can still do some other stuff that I've been doing that takes advantage of identical ID's. We'll see...

It looks like PP and Eleandor are pretty much on the same page anyway, their methods look parallel.

Cheers Purplepoot, Eleandor etc etc....
 
Level 7
Joined
Jun 16, 2008
Messages
253
Lol, you just really want to rub my ignorance in mah face doncha! Jks. I don't think I gave you guys credit for inventing it, just for explaining it, and for being there when I understood it. :D
 
Status
Not open for further replies.
Top