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

[JASS] DyS's Question Thread

Status
Not open for further replies.
Level 7
Joined
Mar 6, 2006
Messages
282
I want to ask questions ALL the time, but hold off until it's a big enough reason to start a thread. So I'm making this thread where I can ask all these little questions!


Click the awesome Myrmadon picture to go to my latest question.





Don't reply to any of my previous questions unless you really think there's something I might be missing. I only post a new question once I'm satisfied with the answer to my current question.









[Question 1]

In my map, I have multiple copies of each item. These items correspond to each other, so I need to use a function to get an item's corresponding copy. This is how I have it set up right now...

JASS:
itemlist[0] = A
itemlist[1] = copy of A
itemlist[2] = B
itemlist[3] = copy of B
itemlist[4] = C
itemlist[5] = copy of C
itemlist[6] = D
itemlist[7] = copy of D


If I need to get an item's copy, then I do:



JASS:
function GetItemCopy takes integer whichItem returns integer

     local integer index = 0

     loop
          exitwhen index > item list length

          if ( whichItem == itemlist[index] ) then

               return itemlist[ index + 1 ]

          endif

          set i = i + 1
     endloop

     return null

endfunction


Is there a better way to do it?

Edit: Damn, it would kind of suck, but I could delete all my items and make new ones with the Object hack, order the item codes correctly, and then just do GetItemTypeId(item) + 1 haha. Also, anyone know any good reads on these IDs? I wanna know more about them, like, how they translate etc.
 
Last edited:
Level 7
Joined
Mar 6, 2006
Messages
282
set hash = InitHashtable()

set itemA = someItem
set itemB = otherItem
call SaveItemHandle(hash, GetHandleId(someItem), 0, otherItem)

function GetItemCopy takes integer whichItem returns integer
return LoadItemHandle(hash, whichItem, 0)
endfunction

Tbh, I never used a hashtable before, though it seemed like the right thing to do. I think I read somewhere that hashtables were slower than just calling variables, so I tried doing it with a large array. Are hashtables slow? I'm going to do some tests now.

This is for recipes btw.
 
Level 7
Joined
Mar 6, 2006
Messages
282
Whoa, I was just experimenting... and this works the same as a hashtable but it's faster?

JASS:
// itemA = 'I001'
// itemB = 'I00B'
// itemC = 'I01C'
// itemD = 'I00X'

set itemlist[ 'I001' - 'I000' ] = itemcopyA
set itemlist[ 'I00B' - 'I000' ] = itemcopyB
set itemlist[ 'I01C' - 'I000' ] = itemcopyC
set itemlist[ 'I00X' - 'I000' ] = itemcopyD

function GetItemCopy takes integer whichItem returns integer
      return itemlist[ whichItem - 'I000' ]
endfunction

I got the idea from deathismyfriend in another thread!

deathismyfriend said:
Unless you mean something like this.

unitTypeArray[ 'H001'] = 0

In the case above you can't use 'H001' as an index. You would then need to use a hashtable.

You CAN use those ID's in an array, you just need to reduce it by subtracting the ID by it's base, where 'I000' would be the item base.

I need to know what you guys think about this ASAP so I can start writing my trigger, lol.
 
The subtraction method is fine. You won't see it used in systems, though, because JNGP allows you to choose specific rawcodes. e.g. if someone decides to ignore the custom item convention of starting with 'I', and they do something like 'ZXF4', you'll get:
0x5a584634 = 1515734580
1515734580 - 1227894832 (integer value of 'I000') = 287839748

Which, of course, is out of the array range.

For personal mapping, this won't always matter. It just means you have to keep to the 'IXXX' pattern, and you won't be able to store most preset wc3 items into the array. And I don't think the editor uses all the ascii characters for rawcodes, so you might be limiting yourself to several hundred or a thousand items. Systematically, a hashtable will circumvent all that because the keys can be anything within the integer limit. While it is true that hashtables are slower than arrays, you have to bear in mind that they are still very fast. You can run them every 0.03 seconds without issue. Even every 0.005 seconds.

For your own map, use subtraction if you like it better and if it works for you. If you are releasing the system or if you want the privilege to use any rawcode, use a hashtable.

P.S. You wanted to read up on rawcodes, see:
http://wiki.thehelper.net/wc3/Jass_Primitive_Types#integer

EDIT: In your case, the max rawcode to use would be 'I0P/'
 
Level 7
Joined
Mar 6, 2006
Messages
282
Lots of great info there PurgeandFire, yay. I'm gonna use this in my map then because I have very specific needs for knowing an item's copy for upcoming skills too, so if this works well, I'm gonna put it to use.

I was wondering the limit too, so I tested, hehe. Thanks for telling me the rawcode for that; I'm gonna read that link you posted.

7z81.jpg
 
Level 7
Joined
Mar 6, 2006
Messages
282
Double posting because....


[Question 2]

Wtf vJASS

Hate this gosh darn confusing shit. Anyway, I'm on a mission to be more efficient and I can't help but wonder about this fabled syntax. Here's what bugs me:

1.) Idk how the fck this sht compiles; how am I supposed to write code if I don't know how efficiently the compiler translates it BACK into JASS.

2.) And yeah, BACK into JASS. If we're talking about bare-bones scripting in WC3, and efficiency is so hella important, isn't JASS the best way to go? Honestly, I feel like vJASS is like GUI, as GUI is to JASS. Isn't that why we're stripping BJ's and using the minimal stuff in the first place?

ARGH. Someone explain why vJASS is of any importance, because right now, to me, it seems like a layer of computer science added to JASS, so computer science nerds can script comfortably.

Edit: I'm drunk and angry... ROAR!!
 
If you really don't care about any of the vJASS OOP features, then you should at least use the freeform globals block. It is the most useful option, and essentially the building block for most of the vJASS structures.

Before vJASS, we had to make variables in the GUI variable editor. The war3map.j starts with a globals block (just one), and it declares all the variables in the map. All the GUI variable editor globals are listed there (prefixed udg_). jasshelper will just read your globals block and move those globals over to that block.

If you want to really know the internals of vJASS features, then the best way is to just view the raw map code. You can view the raw code in a little box by creating an error, e.g:
JASS:
globals
    a b
endglobals

If you need to know how a certain feature works, I'll be happy to answer. Covering all the vJASS features would take too long.

It may seem overwhelming when you see all the vJASS features. You really don't need all of them. In resources, we only use a few (structs, modules, libraries, globals, and the keywords, pretty much). You'll get used to them over time. They are quite useful.

Also, efficiency really isn't as "hella" important (are you from California?) as people make it out to be. It is important, and vJASS is quite efficient, but there are a lot of other aspects of code that are necessary, e.g. portability, interface, etc. vJASS helps out on those fronts A LOT compared to regular JASS. If you were to code everything that vJASS does using regular JASS, you can easily get lost or make errors.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
1. Use an MPQ editor to extract the compiled jass code.
2. vjass isn't like GUI, because GUI does not provide access to some of jass' API. vjass adds features (limited OOP) features to jass and allows access to all of jass' API. If you don't like OOP, go jass, but if you think you need that feature, use vjass. There are also other alternatives if you really dislike vjass, like cjass, zinc or wurst.

so computer science nerds can script comfortably
I thought nerds were masochists...
 
Level 7
Joined
Mar 6, 2006
Messages
282
Yeah Purge, I think it was you or someone else who told me about the globals block, and I found that insanely useful. And I would also do the errors like you said, to see the real script whenever I could. Also, valid points made. I guess I have to wait until I find another feature of vJASS useful.

And na, I'm from Boston. I only said 'hella' because I had previously used 'fucking' and I don't want to sound redundant.

@ chobibo

What do you mean, vJASS allows access to JASS's API ?
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
You can use all the native jass functions.

You can use all of the native jass functions in jass as well.

vJass mainly allows more readable code. Better efficient code. Global private variables. Easier system management. Private functions libraries structs and methods. Constant variables that aren't dreadful to read like in jass. You can declare global variables in a global block anywhere instead of only the map header or variable editor. And many other things.
 
Level 7
Joined
Mar 6, 2006
Messages
282
[Question 3]

This is a small question.

All over a map's script you may have the Player() function everywhere. It takes an integer and returns a player.

My question is, why use that when you can make a new global array with each player in it, and then just use Player[] instead of Player() ?
 
Last edited:
Level 7
Joined
Mar 6, 2006
Messages
282
you're right, you can do this.. but for what reason?

so you would set
Player[1] = Player(0)
Player[5] = Player(4) ...(?)

what could you do with that?

I figured it would be more efficient so you aren't calling Player() every time you need to get a player. I also figured that getting a variable was faster than calling a function. But there must be something I'm missing, or else everyone would be doing this.
 
I figured it would be more efficient so you aren't calling Player() every time you need to get a player. I also figured that getting a variable was faster than calling a function. But there must be something I'm missing, or else everyone would be doing this.

It is more efficient. And you're right, it has been done:
http://www.thehelper.net/threads/getplayer.122661/

But it is very trivial. You get a benefit of some microseconds at best. But it is not that bad. I wouldn't use it in systems though, because it is just an extra dependency with little functional gain versus Player(). If you are making your own map, it is A-ok.
 
Level 7
Joined
Mar 6, 2006
Messages
282
Oops, didn't mean to say 'handle', I'm still kinda knew to this stuff.

It is more efficient. And you're right, it has been done:
http://www.thehelper.net/threads/getplayer.122661/

But it is very trivial. You get a benefit of some microseconds at best. But it is not that bad. I wouldn't use it in systems though, because it is just an extra dependency with little functional gain versus Player(). If you are making your own map, it is A-ok.

Awesome, thanks! I love saving microseconds.
 
Level 7
Joined
Mar 6, 2006
Messages
282
[Question 4]

How accurate are timers? I have no clue how anyone would know this, but I'd like to get people's opinions.

I'm working on some hero AI, and it's all fine and dandy but now I'm adding a reaction timer that mimics human reaction. All of the bot's actions will be filtered through this timer and be given their own reaction time, averaging around 0.22 seconds. Some actions require greater a reaction time to emulate real-time keyboard button pressing and mouse movement + targeting.

Considering these variables, it's important that the timer can differentiate between tenths of milliseconds (which is the smallest time that a timer accepts, right?).

So before I go write this whole thing and find out that it doesn't work, how accurate are these timers?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
wc3 uses IEEE floating point, giving you 8 decimal places precision, not 10

I dont know if this is true or not, but we can argue(later)

Most likely what happens inside wc3 is, that for every logical frame all timers are checked, if they expired

The better your CPU, the faster one logical frame is, but I can say you can detect how often u it regenerates, which is every 0.005 seconds
and I tried as far as 0.001 second periodic timers, so you can get good precisition

If you are still concerned, I will say this: call TimerStart(timer, 0.00, false, callback) will fire earlier than you can react(its most likely on next logical frame, if it works that way)

PLEASE NOTE: The thing with frames is something I can not prove, but it makes sense, doesnt it?
 
Level 7
Joined
Mar 6, 2006
Messages
282
wc3 uses IEEE floating point, giving you 8 decimal places precision, not 10

Terrible wording on my part, I definitely didn't mean .0000000001 hahaha

OK, so that sounds good. Speaking of TimerStart(), I was also thinking if it's worth it to keep the timer running when it's not in use, because starting the timer again would be slower than if the timer was already running. No clue if that's true, what do you think?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
starting tiner should be relativelly light weight, and you will definately(dont now, dont care about wording st this time) lagg with you have too many of them running at once(few hundred to thousand Imo will make fps drop)
 
Terrible wording on my part, I definitely didn't mean .0000000001 hahaha

OK, so that sounds good. Speaking of TimerStart(), I was also thinking if it's worth it to keep the timer running when it's not in use, because starting the timer again would be slower than if the timer was already running. No clue if that's true, what do you think?

From a programming perspective, it is "better" to only keep it running when it is being used. It is a matter of checking a condition periodically vs. the timer being already started. On one hand, the timer is already running so you don't need to start it, but on the other, you are evaluating a condition uselessly very often (well, depending on the period). IMO, pause it when you don't need it to be running.

Also, don't you get this weird feeling when you have something running in the background when you aren't actually using it? For some reason, it bugs me, even as insignificant as it is. It gives me diarrhea. Don't let that happen to you. :thumbs_up:
 
Level 7
Joined
Mar 6, 2006
Messages
282
starting tiner should be relativelly light weight, and you will definately(dont now, dont care about wording st this time) lagg with you have too many of them running at once(few hundred to thousand Imo will make fps drop)

Just one timer, should be fine then.

From a programming perspective, it is "better" to only keep it running when it is being used. It is a matter of checking a condition periodically vs. the timer being already started. On one hand, the timer is already running so you don't need to start it, but on the other, you are evaluating a condition uselessly very often (well, depending on the period). IMO, pause it when you don't need it to be running.

Yeah, I'll probably do that.

Also, don't you get this weird feeling when you have something running in the background when you aren't actually using it? For some reason, it bugs me, even as insignificant as it is. It gives me diarrhea. Don't let that happen to you. :thumbs_up:

Lol, of course. I never trust myself to make sure that timers/periodic events are off when they're supposed to be, so I check every once in a while. This however, is barely being unused. Depending on how many computers there are, each one needs to make an action at least once every few seconds, so the timer's downtime is minimal.
 
Status
Not open for further replies.
Top