HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

NEW! JASS function pack, please contribute

08-04-2003, 02:08 AM#61
Peppar
Ah but I thought I convinced you that you could use the globals
already defined in Blizzard.j for that purpose. Hm. At least I
THINK you can. No promises though... :P

EDIT: Made a function which made use of Blizzard.j globals.
Worked like a charm.
08-04-2003, 03:40 AM#62
dataangel
Quote:
Originally posted by Peppar
Ah but I thought I convinced you that you could use the globals
already defined in Blizzard.j for that purpose. Hm. At least I
THINK you can. No promises though... :P

EDIT: Made a function which made use of Blizzard.j globals.
Worked like a charm.


But you simultaneously convinced me that I'd run into trouble with multiple instances of the trigger running since they don't have trigger scope -- and you convinced me that there WILL be threads if said triggers have waits (which they do).
08-04-2003, 04:03 AM#63
Peppar
As long as YOUR function doesn't have Waits you can be certain
that the variables you use remain untouched until the function
ends.

Calling other functions (with call or with ForGroup) will also not
create opportunities for external functions to mess up your
global variables.

I'm sorry if I have caused confusion.
08-04-2003, 05:28 AM#64
dataangel
Quote:
Originally posted by Peppar
As long as YOUR function doesn't have Waits you can be certain
that the variables you use remain untouched until the function
ends.


It does =)
08-04-2003, 12:25 PM#65
Peppar
My apologies then :). I misunderstood you.
08-04-2003, 02:52 PM#66
Peppar
Made a function to iterate player groups...
Code:
function IterateForce_Enum takes nothing returns nothing
    if ( bj_forceRandomConsidered == 0 ) then
        set bj_forceRandomCurrentPick = GetEnumPlayer()
    endif
    set bj_forceRandomConsidered = bj_forceRandomConsidered - 1
endfunction

function IterateForce takes force whichForce, integer playerIndex returns player
    set bj_forceRandomCurrentPick = null
    set bj_forceRandomConsidered  = playerIndex
    call ForForce( whichForce, function IterateForce_Enum )
    return bj_forceRandomCurrentPick
endfunction
08-04-2003, 04:28 PM#67
Peppar
The HandleToInteger and IntegerToForce converts a handle (any
variable that has handle as its "ancestor" can be painlessly
converted to a handle) to an integer. You can even convert it back
into any handle-derived variable you want (e.g. unit, item, force,
player, group, playercolor...), but I think it is best to stick to the
type it originally had :P.

I kid you not. Try it.

The idea popped up when someone found out that return-
statements inside blocks (if, loop) aren't tested for validity and
thus can return a variable of the wrong type. Can't remember who
or when or even where, though.

There are some other functions which rely on it, because there is
no enum-variable of type Force in Blizzard.j. I use an integer to
keep track of which Force is currently in focus. I have tested them
somewhat but there might still be several bugs...

I don't know what this has for an effect in the long run, if it will
mess upp the scripting system or something . :ggani: It is still
useful in this one case.

Code:
function HandleToInteger takes handle h returns integer
    if ( h != null ) then
        return h
    endif
    return 0
endfunction

function IntegerToForce takes integer i returns force
    if ( i != 0 ) then
        return i
    endif
    return null
endfunction

// Returns true if the force is empty
function IsForceEmpty_Enum takes nothing returns nothing
    set bj_isUnitGroupEmptyResult = false
endfunction
function IsForceEmpty takes force whichForce returns boolean
    set bj_isUnitGroupEmptyResult = true
    call ForForce(whichForce, function IsForceEmpty_Enum)
    return bj_isUnitGroupEmptyResult
endfunction

// Adds all players of a force to a force
// Requires: HandleToInteger, IntegerToForce
function ForceAddForce_Enum takes nothing returns nothing
    call ForceAddPlayer(IntegerToForce( bj_forceCountPlayers ), GetEnumPlayer())
endfunction
function ForceAddForce takes force sourceForce, force destForce returns nothing
    set bj_forceCountPlayers = HandleToInteger(destForce)
    call ForForce(sourceForce, function ForceAddForce_Enum)
endfunction

// Removes all players of a force from a force
// Requires: HandleToInteger, IntegerToForce
function ForceRemoveForce_Enum takes nothing returns nothing
    call ForceRemovePlayer(IntegerToForce( bj_forceCountPlayers ), GetEnumPlayer())
endfunction
function ForceRemoveForce takes force sourceForce, force destForce returns nothing
    set bj_forceCountPlayers = HandleToInteger(destForce)
    call ForForce(sourceForce, function ForceRemoveForce_Enum)
endfunction

// Checks to see if the two forces contain exactly the same players
// Requires: IsForceEmpty, ForceAddForce, ForceRemoveForce
function ForcesHaveEqualContents takes force whichForce, force asWhichForce returns boolean
    local force difference = null
    if ( CountPlayersInForceBJ( whichForce ) != CountPlayersInForceBJ( asWhichForce ) ) then
        return false
    endif
    set difference = CreateForce()
    call ForceAddForce( whichForce, difference )
    call ForceRemoveForce( asWhichForce, difference )
    if ( IsForceEmpty( difference ) ) then
        call DestroyForce( difference )
        return true
    endif
    call DestroyForce( difference )
    return false
endfunction

// Checks to see if the two groups contain exactly the same units
function UnitGroupsHaveEqualContents takes group whichGroup, group asWhichGroup returns boolean
    local group difference = null
    if ( CountUnitsInGroup( whichGroup ) != CountUnitsInGroup( asWhichGroup ) ) then
        return false
    endif
    set difference = CreateGroup()
    call GroupAddGroup( whichGroup, difference )
    call GroupRemoveGroup( asWhichGroup, difference )
    if ( IsUnitGroupEmptyBJ( difference ) ) then
        call DestroyGroup( difference )
        return true
    endif
    call DestroyGroup( difference )
    return false
endfunction
08-04-2003, 05:33 PM#68
PitzerMike
Well...
The Remove first unit of group idea is not really a new find.

We have always used this method in AI scripts, as they don't allow callback functions.
08-04-2003, 06:24 PM#69
dataangel
Quote:
Originally posted by PitzerMike
Well...
The Remove first unit of group idea is not really a new find.

We have always used this method in AI scripts, as they don't allow callback functions.


Dammit all, why doesn't anyone tell me this stuff? :////

I ought to keep a better look on the AI world....
08-04-2003, 06:32 PM#70
dataangel
@Peppar: I love your method of testing if unit groups/forces are equal! I had tried using == before and ran into problems (since it just tests if the pointers pointing to the same group), and resorted to just checking if the groups had the same number of units in them (which in my particular instance worked fine).

I would do some extensive testing on it though. What I discovered in playing around with my new IterateGroup function is that if I directly pass it the result of one of the blizz functions like GetAllunitsinrect or whatever, then it passes a unit group with only 11 units in it. If I assign a group variable to it, and then pass the variable, it gets all of them. I'm not sure how to account for the difference in behavior. I remember along time ago there was a bunch of hubub over unitgroup vars only being able to hold 12 units. I think that it maybe that if you make a new group and call CreateGroup() and then assign it to one of the blizz functions that it overrides this limit, but if you don't use CreateGroup() first that it doesn't. Someone testing will tell...

For your functions to add/remove from forces -- I don't understand why handle2int is necessary. It just looks like a quicker way to count the number of player's in the group (I'm guessing that converting a player group to an integer results in the number of players in the group).
08-04-2003, 06:56 PM#71
Peppar
Thank you :P.

I am not familiar with the 12-unit-limit for unit groups. I'll have a
glimpse at it.

About handles though, I believe that all handles are in fact
integers of some kind that refer to some internal array in the
game engine. I did the HandleToInteger on two units that were
created at map init, the printout of the two integers was
0x100006 and 0x100007. I would suspect this means that the
engine treats them as unit number 6 and 7 (I had some other
units and items in the map as well). When I converted these
numbers into "unit"-variables, they would refer to the two units
again.

So, IntegerToUnit( HandleToInteger( my_unit ) ) would be the
same as using my_unit in the first place.

Seemingly useless, this can although be used to squeeze more
variables into the blizzard globals :P.
08-04-2003, 07:53 PM#72
dataangel
Quote:
Originally posted by Peppar
Thank you :P.

I am not familiar with the 12-unit-limit for unit groups. I'll have a
glimpse at it.

About handles though, I believe that all handles are in fact
integers of some kind that refer to some internal array in the
game engine. I did the HandleToInteger on two units that were
created at map init, the printout of the two integers was
0x100006 and 0x100007. I would suspect this means that the
engine treats them as unit number 6 and 7 (I had some other
units and items in the map as well). When I converted these
numbers into "unit"-variables, they would refer to the two units
again.

So, IntegerToUnit( HandleToInteger( my_unit ) ) would be the
same as using my_unit in the first place.

Seemingly useless, this can although be used to squeeze more
variables into the blizzard globals :P.


HOLY SHIT! No that's a really big damn thing. I figured war3 already generated a unique integer for every unit in the game -- but with access to it that means this can be used to index arrays and stuff instead of a unit's custom value. Furthermore, a function could be made like GetUnit(54) and it would get the 54th unit -- no globals necessary. Just pick every unit on the map, convert them to integers, and find out which one is 54. This would be extremely useful for making JASS spells that people could copy and paste to work on different maps, since ya don't have to worry about telling them how they need to setup a global to keep track of units and triggers to manage it and all that.

Some experimentation needs to be done though:

-Are old spaces recycled if a unit dies?
-If not, how about once its corpse decays?
-If a hero dies and is revived, does it have the same integer or a new one?
-If a unit is ressurected by ressurection or animate dead or a rune does it get a new integer or its old one back?

Damn... this is proving to be the coolest thread EVER. :ggani:

BTW, peppar, could you check this out?:

http://www.wc3campaigns.com/forums/s...highlight=wait

The JASS revelations are coming a mile a minute the last few days =)

Just this morning I think I figured out how to put as much text as I want in the lobby area before a game starts on bnet (still have to test to be sure).
08-04-2003, 09:12 PM#73
Peppar
Yes it opens up quite a sum of possibilities :P. But I guess the
bottleneck would be that we won't have any idea of knowing
how high the unit numbers go, i.e. where to stop searching, if we
were to create such a function.

With global arrays we could painlessly add new values to any
variable-type. Just look up the id in the array and fetch the
value :P
08-04-2003, 09:53 PM#74
Peppar
Aha! One thing is for sure - Warcraft recycles unit IDs. I had a map
that periodically spawned a footman and printed out his ID.
When I removed a unit his ID was recycled.

One other thing though was that when I spawned new units
their IDs appeared to come sequentially (when not filling up holes
created by removing other units), and that they came two values
apart. So the list would go 12, 14, 16, 18... Pherhaps there is
some other variable created together with each unit, and if there
is there might be a chance we can affect it :P

EDIT: There is no variable created togehter with a unit, as the
units that were created at map init surely comes sequentially.
Pherhaps those IDs are trigger IDs or something.. Hm..

This is starting to get interesting :P
08-04-2003, 10:42 PM#75
Aiursrage2k
Store the heroes spell level using custom data. So 1333, would mean all the skill sets where used.
Code:
function setCustomData takes nothing returns nothing 
  local integer score = GetUnitUserData(GetLearningUnit()) 
  if GetLearnedSkillBJ() == 'A001' then//Spell code1 
     set score = score + 1 
  elseif GetLearnedSkillBJ() == 'A003' then//Spell code2 
     set score = score + 10 
  elseif GetLearnedSkillBJ() == 'A007' then//Spell code3 
     set score = score + 100 
  elseif GetLearnedSkillBJ() == 'A002' then//Ultimate 
     set score = score + 1000 
  endif 
  call SetUnitUserData( GetLearningUnit(), score ) 
endfunction 

To get its skill level, just enter the unit and the spellNumber.
Code:
Code:
function returnLevel takes unit u, integer num returns integer 
      return S2I(SubStringBJ(I2S(GetUnitUserData(u)), num,num)) 
endfunction