| 08-04-2003, 02:08 AM | #61 |
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 | |
Quote:
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 |
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 | |
Quote:
It does =) |
| 08-04-2003, 12:25 PM | #65 |
My apologies then :). I misunderstood you. |
| 08-04-2003, 02:52 PM | #66 |
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 |
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 |
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 | |
Quote:
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 |
@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 |
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 | |
Quote:
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 |
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 |
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 |
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 |
