• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Trigger] Claiming ground, complicated shit

Status
Not open for further replies.
Level 4
Joined
Aug 6, 2014
Messages
87
I thought about giving players some kind of these numbers, idk the name of these numbers:

1, 2, 4, 8, 16, 32, 64, 128, 256, 1028 (10 players) to make a claiming system like this:
Each claimable area has it's own variable and when the variable has the values of 3, player 1 and 2 should be able to build in there, if it has the value of 32 only player 6 is able to build in there, now I've thought about this but I actually have 0 idea how to deal with that that each player gets the unique ID in a variable and also that the area variable is getting edited and those values for whoever who's with his main unit, a created unit by triggers, in the area and types -claim, and with -share (red-lightblue) he can assign the players the allows to build with him.

the thing Idk about now is to make the command,
function whos checking whos allowed to build in the region,
and the variables for the values,
the created unit somehow needs to be attached to a player in a varible, so I can check that the created unit is in the region.

If anybody can help me with that, I'd be so thankful.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
The easiest method is to use a boolean array... it is kind of the same but is slightly more performing but uses more data storage... for some stupid reason.

If you do want to use bitshifting/bitmasking, using modulo is your best option:
JASS:
function IntHasBit takes integer var, integer position returns boolean
    set var = var / Pow(2, position)
    return ModuloInteger(var, 2) == 1
endfunction

function IntSetBit takes integer var, integer position, boolean value returns nothing
    if (IntHasBit(var, position)) then
        if (!value) then
            set var = var - Pow(2, position)
        endif
    else
        if (value) then
            set var = var + Pow(2, position)
        endif
    endif
endfunction

However, the second one doesnt work... because it uses a local variable.
You need something like this:
JASS:
function SetBuildAllowed takes integer position, boolean value returns nothing
    if (IntHasBit(udg_BuildAllowed, position)) then
        if (!value) then
            set udg_BuildAllowed = udg_BuildAllowed - Pow(2, position)
        endif
    else
        if (value) then
            set udg_BuildAllowed = udg_BuildAllowed + Pow(2, position)
        endif
    endif
endfunction

To make it a bit better:
JASS:
function IntHasBit takes integer index, integer position returns boolean
    return ModuloInteger(udg_Storage[index] / Pow(2, position), 2) == 1
endfunction

function IntSetBit takes integer index, integer position, boolean value returns nothing
    local integer pow = Pow(2, position)
    if (ModuloInteger(udg_Storage[index] / pow, 2) == 1) then
        if (!value) then
            set udg_Storage[index] -= pow
        endif
    else
        if (value) then
            set udg_Storage[index] += pow
        endif
    endif
endfunction

With this, you only need an integer array called "Storage".
Then you can store everything in it that you want.

The position can be between 0 and 30.
So: 0, 1, 2, 3, 4... 28, 29, 30.
The index can be between 0 and 8191. (You should not use numbers larger than 512 if possible... it is also not necessary because then you already have 512 * 31 = 15872 booleans :D

From GUI:
Custom Script: "set udg_TempBoolean = IntHasBit(1, 2)" (1 for index, 2 for position)
This will fill your global boolean variable "TempBoolean" with wether or not that bit is set.
 
Level 4
Joined
Aug 6, 2014
Messages
87
What do you mean with position? The area?

Where can I set my GUI Trigger to JASS then? Couldn't find anything in the Wc3 World Editor
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
In Trigger Editor, you select a trigger and use Edit->Convert to Custom Text
But you could better use the header file (the blue WE iconed thing at the top of the trigger list.

The position is the position of the bit.
An integer is made out of 32 bits (at least the ones that WC3 uses).
A bit is a number of either 1 or 0 (or a boolean true/false).
According to the position of the bit, the bit's value is 2 to the power of <position>.
Starting at the end.
So the last bit is worth 1.
The one to the left of that is 2.
Then 4, 8, 16, 32, 64, 128, 512, 1024, etc, etc, etc.
The last one is a bit off... its value is... -2,147,483,648.
That is done to make negative numbers :D

The integer's value exists of all values of the bits that are true (1) added up to each other.
So if an integer is odd, the last bit is true.
If an integer divided by 2 is odd, the one but last is true.
If an integer divided by 4 is odd, the two but last is true.
Etc.
I dont know how modulo works with negative numbers and I am too lazy to find out :D

EDIT: Sorry... I should have put it through the syntax checker.
WC3 doesnt know the ! operator on booleans I guess so you need not instead.
Also, it cannot convert reals to ints... Pow() returns a real.
And... += and -= is also something JASS doesnt know :D
So:
JASS:
function IntHasBit takes integer index, integer position returns boolean
    return ModuloInteger(udg_Storage[index] / R2I(Pow(2, position)), 2) == 1
endfunction

function IntSetBit takes integer index, integer position, boolean value returns nothing
    local integer pow = R2I(Pow(2, position))
    if ModuloInteger(udg_Storage[index] / pow, 2) == 1 then
        if not value then
            set udg_Storage[index] = udg_Storage[index] - pow
        endif
    else
        if value then
            set udg_Storage[index] = udg_Storage[index] + pow
        endif
    endif
endfunction
 
Last edited:
Level 4
Joined
Aug 6, 2014
Messages
87
When I did that and pasted the code into there it can't save the map anymore, saving progress gets stuck, lol.
 
Level 4
Joined
Aug 6, 2014
Messages
87
I do have some scripting experience, In C++ but I actually understand nothing of this API and the language and the existing functions, it's so weird.

Well I've imported it into a function now, can you explain me what it does exactly and how to move on now? Like making a comand which a player can use when hes in one of the 10 base areas with his main unit and then it updates the variables with the bitmasks.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,287
1, 2, 4, 8, 16, 32, 64, 128, 256, 1028 (10 players) to make a claiming system like this:
Each claimable area has it's own variable and when the variable has the values of 3, player 1 and 2 should be able to build in there, if it has the value of 32 only player 6 is able to build in there, now I've thought about this but I actually have 0 idea how to deal with that that each player gets the unique ID in a variable and also that the area variable is getting edited and those values for whoever who's with his main unit, a created unit by triggers, in the area and types -claim, and with -share (red-lightblue) he can assign the players the allows to build with him.
What you are describing are binary flags, where each bit has a unique meaning.

In C/C++ flags are used by masking. This requires bitwise operators. JASS lacks native bitwise operator support. Bitwise operators can be simulated with functions however these are considerably slower than native bitwise operators.

The functions Wietlol posted simulate bit test and bit set instructions. These instructions are seldom seen outside of embedded systems. As such most languages lack native support for this kind of operation, instead relying on the use of a few of the common bitwise operators to simulate the behaviour. The reason bit test and set is a rare instruction is because it does not work well with common memory models. When one simulates it using normal bit wise operators it has certain implications on the memory model, specifically that a byte (or other) unit of memory is read or read and written and not just a single bit.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
To use it, you just organize your claimable areas and give them all a nice number counting up from 0.

Then you use that number as index, and you can use the player number as position.
If you want, you can use two or maybe three areas per index because there are 31 positions which is enough for 3 times 10 players.

When a player claims an area, you call the IntSetBit(area, player, true)
Where area would be the area he claims and player would be the player number.
To check if it is claimed (and thus buildable), you call the IntHasBit(area, player) and if that returns true, it is claimed.
If you want to use this in GUI, you might want to learn how to use global variables in custom scripts... simply write the same as the variable name with an "udg_" prefix.
(Same how "udg_Storage" is used.)
 
Level 4
Joined
Aug 6, 2014
Messages
87
Well alright, kinda got it til now.

Explain of my hero picking system: Specific unit of a player walks into a specific area and gains a specific hero, now my question is, how do I set the unit ID of the unit on pickup in a variable like this: Personal_Hero[(Player number of (owner of triggering unit))] = Unit ID (if units have a unique ID there, in wich they can be recalled like: "if unit of ID is in area X, then allow player to claim the area with -claim as command"

Then the command, how do I check that the unit is in there? What else do I have to put in the command trigger since we've got 2 other triggers now with the SetBuildAllowed and IntHasBit

Edit: Example trigger of my hero in JASS

( I put = point value of unit because I thought thats the unique ID )

JASS:
function Trig_Hero_Pick_PALADIN_Conditions takes nothing returns boolean
    if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'e001' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Hero_Pick_PALADIN_Func005C takes nothing returns boolean
    if ( not ( udg_Unique_Pick > 0 ) ) then
        return false
    endif
    return true
endfunction
//============This is the function where I wanna declare the personal hero varaible==================//
function Trig_Hero_Pick_PALADIN_Actions takes nothing returns nothing
    call RemoveUnit( GetTriggerUnit() )
    call CreateNUnitsAtLoc( 1, 'H000', Player(0), GetRectCenter(gg_rct_Hero_Pick_SPAWN_AREA), bj_UNIT_FACING )
    call SetUnitLifeBJ( GetLastCreatedUnit(), ( GetUnitStateSwap(UNIT_STATE_MAX_LIFE, GetLastCreatedUnit()) - 1 ) )
    set udg_Personal_Hero[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))] = GetUnitPointValue(GetLastCreatedUnit())
    if ( Trig_Hero_Pick_PALADIN_Func005C() ) then
        call DisableTrigger( GetTriggeringTrigger() )
    else
    endif
endfunction

//===========================================================================//
function InitTrig_Hero_Pick_PALADIN takes nothing returns nothing
    set gg_trg_Hero_Pick_PALADIN = CreateTrigger(  )
    call TriggerRegisterEnterRectSimple( gg_trg_Hero_Pick_PALADIN, gg_rct_Hero_Pick_PALADIN )
    call TriggerAddCondition( gg_trg_Hero_Pick_PALADIN, Condition( function Trig_Hero_Pick_PALADIN_Conditions ) )
    call TriggerAddAction( gg_trg_Hero_Pick_PALADIN, function Trig_Hero_Pick_PALADIN_Actions )
endfunction
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,287
Explain of my hero picking system: Specific unit of a player walks into a specific area and gains a specific hero, now my question is, how do I set the unit ID of the unit on pickup in a variable like this: Personal_Hero[(Player number of (owner of triggering unit))] = Unit ID (if units have a unique ID there, in wich they can be recalled like: "if unit of ID is in area X, then allow player to claim the area with -claim as command"
Each unit has a unique ID in the form of a handle. This handle is commonly known as the variable type "unit". As such Personal_Hero would be a global unit array variable. This is similar to how objects work in Java where a variable of class type is an object handle.

Then the command, how do I check that the unit is in there? What else do I have to put in the command trigger since we've got 2 other triggers now with the SetBuildAllowed and IntHasBit
You test if the rect or region contains the unit.

JASS:
native IsUnitInRegion takes region whichRegion,unit whichUnit returns boolean

function RectContainsUnit takes rect r,unit whichUnit returns boolean
    return RectContainsCoords(r, GetUnitX(whichUnit), GetUnitY(whichUnit))
endfunction

Edit: Example trigger of my hero in JASS
Why not this?
JASS:
function Trig_Hero_Pick_PALADIN_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'e001'
endfunction

function Trig_Hero_Pick_PALADIN_Actions takes nothing returns nothing
    local unit u
    local player p = GetOwningPlayer(GetTriggerUnit())

    call RemoveUnit(GetTriggerUnit())
    set u = CreateUnit(p, 'H000', GetRectCenterX(gg_rct_Hero_Pick_SPAWN_AREA), GetRectCenterY(gg_rct_Hero_Pick_SPAWN_AREA), bj_UNIT_FACING)
    call SetUnitState(u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_MAX_LIFE) - 1)
    set udg_Personal_Hero[GetConvertedPlayerId(p)] = u

    if udg_Unique_Pick > 0 then
        call DisableTrigger(gg_trg_Hero_Pick_PALADIN)
    endif

    // LDLHVRCL fix
    set u = null
    set p = null // not strictly nescescary
endfunction

//===========================================================================//
function InitTrig_Hero_Pick_PALADIN takes nothing returns nothing
     set gg_trg_Hero_Pick_PALADIN = CreateTrigger(  )
     call TriggerRegisterEnterRectSimple( gg_trg_Hero_Pick_PALADIN, gg_rct_Hero_Pick_PALADIN )
     call TriggerAddCondition( gg_trg_Hero_Pick_PALADIN, Condition( function Trig_Hero_Pick_PALADIN_Conditions ) )
     call TriggerAddAction( gg_trg_Hero_Pick_PALADIN, function Trig_Hero_Pick_PALADIN_Actions )
endfunction
 
Level 4
Joined
Aug 6, 2014
Messages
87
Oh gawd this is so complicated when I heard 2 days ago about JASS the first time.

so if I don't get it wrong u set with unit a local variable which I can recall in the IsUnitInRegion function right?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,287
so if I don't get it wrong u set with unit a local variable which I can recall in the IsUnitInRegion function right?
Local variables have a standard programming meaning. They are there to act as temporary variables to store data for the duration of the function. Although the declaration syntax is different, they are functionally identical to local variables in C/C++.

The global unit array variable udg_Personal_Hero is what persistently holds a reference to the freshly created hero unit (in the form of a handle id). You evaluate an index from that and pass it as an argument to functions like "IsUnitInRegion".

You can convert handles losslessly into integers using the GetHandleId function. These integers are unique for every object. However it is not possible (or at least safe) to convert such an integer back into a handle id for use as an argument to native function calls.

The reason it is not safe is because the game keeps a reference counter for all handles to prevent the handle id from being recycled as long as a reference to it exists. Since integers are not handles the game will not reference count the handle id an integer refers to so it may be recycled. If such an integer were to be converted back to a handle id then the object it may not represent a valid handle, or the handle may be for a different type of object resulting in possible bugs and even fatal errors. As such you will want to keep handle id's typed at as higher level as possible all the time to keep them as useful and as safe to use as possible.

Be aware that regions and rects are different. The rectangles you draw on the map in the terrain editor are actually of type "rect" despite being inappropriately called "Regions". A region is a completely different object which represents an arbitrary collection of terrain cells. It is common for regions to have the cells filled in from rects. Due to the difference in granularity a region created by filling in from a rect will often represent a different area than the rect that was used to fill it.
 
Level 4
Joined
Aug 6, 2014
Messages
87
While trying to make a -claim command I get 5 errors, prolly pasted wrong.

COMPILING:
PJASS ERROR(S) FOUND!


JASS:
function Trig_base_claim_Actions takes nothing returns nothing
endfunction

//===========================================================================
function InitTrig_base_claim takes nothing returns nothing
    set gg_trg_base_claim = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(0), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(1), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(2), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(3), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(4), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(5), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(6), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(7), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(8), "-claim", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_base_claim, Player(9), "-claim", true )
    call TriggerAddAction( gg_trg_base_claim, function Trig_base_claim_Actions )
endfunction

native IsUnitInRegion takes region whichRegion,unit whichUnit returns boolean

function RectContainsUnit takes rect r,unit whichUnit returns boolean
    return RectContainsCoords(r, GetUnitX(whichUnit), GetUnitY(whichUnit))
endfunction
 
Level 4
Joined
Aug 6, 2014
Messages
87
Well is there a better editor than the jasshelpernewgen one? It's quite annoying that I have to close World Editor with Task manager and JassHelper.exe each time theres an error in the compile
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,287
Well is there a better editor than the jasshelpernewgen one? It's quite annoying that I have to close World Editor with Task manager and JassHelper.exe each time theres an error in the compile
That is a bug with your installation of it. Every time I get a compile error (which I get a lot more than I should as a software engineer...) it mostly hangs for well under a second and then pops up a dialog listing all the errors. This can be closed to immediately resume editing (and fixing that annoying error one accidently made).

Make sure your anti virus did not mangle JNGP. Also make sure to use the jasshelper setting to disable normal world edit syntax checking as the normal checking is extremely crash prone and incompatible with vJASS.
 
Level 4
Joined
Aug 6, 2014
Messages
87
[checked] disable WE syntax checker

and it can't be my anti-virus since I've turned it off for a week to test something.

Installation: Extracted the folder on desktop, using the Jasshelper WE from the extracted folder.
 
Status
Not open for further replies.
Top