HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Region problems ?

06-11-2004, 06:36 PM#1
Mjukland
I need some help with a trigger. Ok, here goes.

I have made a trigger that creates 128*128 sized regions all over my map. a region array with 1768 regions to be exact. I've also made a player array, with the size of 1768 to "check" wich player that owns wich region.

Now I need a trigger that checks when a specific unit-type enters a region that is not owned by the units team. And when it enters it should take controll of that region.

Like in Dungeon Keeper, where the imps takes controll of the ground.

The only way I could do this was by using a periodic timer event, where it looped through the number of imps and then for each imp looped through the 1768 regions to check if they stood in a region not owned by their team.

Say you have 10 "imps" then every 0.5 second it would do this check 17680 times. The map then becomes unplayable because of the lag :P
06-11-2004, 06:52 PM#2
Aiursrage2k
Have local trigger spawn for every region. Give the local trigger the event unit enters region[index]. Then add any conditions you might need. Add a trigger action to call function foobar. Then save the in game the trigger handle.
SaveCacheInt(index,I2S(H2I(this)),"Trig",gamecache)

Then in foobar you get the triggering trigger, and this will give you the index of the region.
GetCacheInt(I2S(H2I(this)),"Trig",gamecache)
06-11-2004, 07:06 PM#3
Mjukland
Umm... ok, I'm not so good with jass so I did'nt understand most of what you were saying.

Could you do the event in jass for me ? :)

And I have no idea what you meant with the game cache stuff. :/

thx.
06-11-2004, 07:26 PM#4
Narwanza
Here is a way I thought of. Since the TriggerRegisterRegionEvent(spelling is wrong most likely) takes a boolexpr you could do something like this. *note* Sytax is not perfect as I am writing from memory, check the function names don't CnP this. This also requires the local handle vars. What you need to do is create a local trigger and then assign the region value it has with the local handle vars. local handle vars can be obtained at http://kattana.users.whitehat.dk/viewfunc.php?id=252

Code:
function Check takes nothing returns boolean
    return (GetPlayerId(GetOwningPlayer(GetFilterUnit())) != udg_PlayerArray[GetHandleInt(GetTriggeringTrigger())] and (GetUnitTypeId(GetFilterUnit()) == '(unit-type of imp)')
endfunction

function Action takes nothing returns nothing
    set udg_PlayerArray[GetHandleInt(GetTriggeringTrigger())] = GetPlayerId(GetOwningPlayer(GetEnteringUnit()))
endfunction

function init takes nothing returns nothing
    local trigger t = null
    local integer x = 0
    loop
        exitwhen x > 1767
        set t = CreateTrigger()
        call SetHandleInt(t,x)
        call TriggerRegisterEnterRegion(t,udg_RegionArray[x],Filter(check))
        call TriggerAddAction(t,function Action)
        set x = x + 1
        set t = null
    endloop
    set t = null
endfunction
06-11-2004, 07:49 PM#5
Aiursrage2k
Wrongo, I will post a proper version when I get home.
06-11-2004, 08:31 PM#6
Narwanza
The way I did this is much more efficient than what you are proposing.
06-11-2004, 08:51 PM#7
Mjukland
Thanks for all help, I understand the functions, i think :) , but I cant get this with handles? Im not very good with jass :/
06-12-2004, 12:13 AM#8
Mjukland
This is what I've done so far. I get no trigger erorrs but the code does'nt seem to do anything. I also have a special effect in every region, there were a strange thing that occured though. When the loop in the "init" function goes from more than 0 to 1200, all special effects dissapears and all regions is set to player 0 ??? When I had the loop go from 0 - 1150 nothing happend.

If a imp enters a unit nothing happens. :(


Code:
function Trig_Regions_Actions takes nothing returns nothing
endfunction

function HandleToInt takes handle h returns integer
    return h
    return 0
endfunction

function IntToHandle takes integer i returns handle
    return i
    return null
endfunction 


function LocalVars takes nothing returns gamecache
    return InitGameCache("jasslocalvars.w3v")
endfunction

function SetHandleHandle takes handle subject, string name, handle value returns nothing
    if value==null then
        call FlushStoredInteger(LocalVars(),I2S(HandleToInt(subject)),name)
    else
        call StoreInteger(LocalVars(), I2S(HandleToInt(subject)), name, HandleToInt(value))
    endif
endfunction

function SetHandleInt takes handle subject, string name, integer value returns nothing
    if value==0 then
        call FlushStoredInteger(LocalVars(),I2S(HandleToInt(subject)),name)
    else
        call StoreInteger(LocalVars(), I2S(HandleToInt(subject)), name, value)
    endif
endfunction

function SetHandleReal takes handle subject, string name, real value returns nothing
    if value==0 then
        call FlushStoredReal(LocalVars(), I2S(HandleToInt(subject)), name)
    else
        call StoreReal(LocalVars(), I2S(HandleToInt(subject)), name, value)
    endif
endfunction

function GetHandleHandle takes handle subject, string name returns handle
    return IntToHandle(GetStoredInteger(LocalVars(), I2S(HandleToInt(subject)), name))
endfunction
function GetHandleInt takes handle subject, string name returns integer
    return GetStoredInteger(LocalVars(), I2S(HandleToInt(subject)), name)
endfunction
function GetHandleReal takes handle subject, string name returns real
    return GetStoredReal(LocalVars(), I2S(HandleToInt(subject)), name)
endfunction

function FlushHandleLocals takes handle subject returns nothing
    call FlushStoredMission(LocalVars(), I2S(HandleToInt(subject)) )
endfunction


function Check takes nothing returns boolean
    return (GetOwningPlayer(GetFilterUnit()) != udg_OwnerOfRegion[GetHandleInt(GetTriggeringTrigger(),"index")] and (GetUnitTypeId(GetFilterUnit()) == 'n000'))
endfunction

function Action takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), I2S(GetConvertedPlayerId(udg_OwnerOfRegion[GetHandleInt(GetTriggeringTrigger(),"index")])) )
    if (Check())==true then
    set udg_OwnerOfRegion[GetHandleInt(GetTriggeringTrigger(),"index")] = GetOwningPlayer(GetEnteringUnit())
    call DestroyEffectBJ( udg_SpecialOwnerGround[GetHandleInt(GetTriggeringTrigger(),"index")] )
    call AddSpecialEffectLocBJ( GetRectCenter(udg_RegionWorld[GetHandleInt(GetTriggeringTrigger(),"index")]), "Units\\Special\\Player1.MDX" )
    set udg_SpecialOwnerGround[GetHandleInt(GetTriggeringTrigger(),"index")] = GetLastCreatedEffectBJ()
    else
    endif

endfunction

function init takes nothing returns nothing
    local trigger t = null
    local integer x = 0
    loop
        exitwhen x > 1767
        set t = CreateTrigger()
        call SetHandleInt (t,"index",x)
        call TriggerRegisterEnterRectSimple(t,udg_RegionWorld[x])
        call TriggerAddAction(t,function Action)
        set x = x + 1
        set t = null
        endloop
    set t = null
endfunction



//===========================================================================
function InitTrig_Regions takes nothing returns nothing
    set gg_trg_Regions = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Regions, 1.00 )
    call TriggerAddAction( gg_trg_Regions, function Trig_Regions_Actions )
    call init()
endfunction
06-12-2004, 04:40 AM#9
Narwanza
Quote:
Originally Posted by Mjukland
This is what I've done so far. I get no trigger erorrs but the code does'nt seem to do anything. I also have a special effect in every region, there were a strange thing that occured though. When the loop in the "init" function goes from more than 0 to 1200, all special effects dissapears and all regions is set to player 0 ??? When I had the loop go from 0 - 1150 nothing happend.

If a imp enters a unit nothing happens. :(


Code:
function Trig_Regions_Actions takes nothing returns nothing
endfunction

function HandleToInt takes handle h returns integer
    return h
    return 0
endfunction

function IntToHandle takes integer i returns handle
    return i
    return null
endfunction 


function LocalVars takes nothing returns gamecache
    return InitGameCache("jasslocalvars.w3v")
endfunction

function SetHandleHandle takes handle subject, string name, handle value returns nothing
    if value==null then
        call FlushStoredInteger(LocalVars(),I2S(HandleToInt(subject)),name)
    else
        call StoreInteger(LocalVars(), I2S(HandleToInt(subject)), name, HandleToInt(value))
    endif
endfunction

function SetHandleInt takes handle subject, string name, integer value returns nothing
    if value==0 then
        call FlushStoredInteger(LocalVars(),I2S(HandleToInt(subject)),name)
    else
        call StoreInteger(LocalVars(), I2S(HandleToInt(subject)), name, value)
    endif
endfunction

function SetHandleReal takes handle subject, string name, real value returns nothing
    if value==0 then
        call FlushStoredReal(LocalVars(), I2S(HandleToInt(subject)), name)
    else
        call StoreReal(LocalVars(), I2S(HandleToInt(subject)), name, value)
    endif
endfunction

function GetHandleHandle takes handle subject, string name returns handle
    return IntToHandle(GetStoredInteger(LocalVars(), I2S(HandleToInt(subject)), name))
endfunction
function GetHandleInt takes handle subject, string name returns integer
    return GetStoredInteger(LocalVars(), I2S(HandleToInt(subject)), name)
endfunction
function GetHandleReal takes handle subject, string name returns real
    return GetStoredReal(LocalVars(), I2S(HandleToInt(subject)), name)
endfunction

function FlushHandleLocals takes handle subject returns nothing
    call FlushStoredMission(LocalVars(), I2S(HandleToInt(subject)) )
endfunction


function Check takes nothing returns boolean
    return (GetOwningPlayer(GetFilterUnit()) != udg_OwnerOfRegion[GetHandleInt(GetTriggeringTrigger(),"index")] and (GetUnitTypeId(GetFilterUnit()) == 'n000'))
endfunction

function Action takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), I2S(GetConvertedPlayerId(udg_OwnerOfRegion[GetHandleInt(GetTriggeringTrigger(),"index")])) )
[color=red]    if (Check())==true then
    set udg_OwnerOfRegion[GetHandleInt(GetTriggeringTrigger(),"index")] = GetOwningPlayer(GetEnteringUnit())
    call DestroyEffectBJ( udg_SpecialOwnerGround[GetHandleInt(GetTriggeringTrigger(),"index")] )
    call AddSpecialEffectLocBJ( GetRectCenter(udg_RegionWorld[GetHandleInt(GetTriggeringTrigger(),"index")]), "Units\\Special\\Player1.MDX" )
    set udg_SpecialOwnerGround[GetHandleInt(GetTriggeringTrigger(),"index")] = GetLastCreatedEffectBJ()
    else
    endif[/color]

endfunction

function init takes nothing returns nothing
    local trigger t = null
    local integer x = 0
    loop
        exitwhen x > 1767
        set t = CreateTrigger()
        call SetHandleInt (t,"index",x)
        call TriggerRegisterEnterRectSimple(t,udg_RegionWorld[x])
[color=green]        call TriggerRegisterEnterRegion(t,udg_RegionWorld[x],Filter(function check))[/color]
        call TriggerAddAction(t,function Action)
        set x = x + 1
        set t = null
        endloop
    set t = null
endfunction



//===========================================================================
function InitTrig_Regions takes nothing returns nothing
    set gg_trg_Regions = CreateTrigger(  )
    call TriggerRegisterTimerEventSingle( gg_trg_Regions, 1.00 )
    call TriggerAddAction( gg_trg_Regions, function Trig_Regions_Actions )
    call init()
endfunction

First of all make sure that your global RegionWorld is a rect global and not a region global. Next look at the line I added in green. That makes the if-then statement in red useless. See the boolexpr that is defined by Filter(function check) is basically like adding a condition w/out having a condition added. It takes one less handle away from every trigger and that is good. Now what the local handle vars did was it associated the region number with the trigger that was created. This way you can access which player should own which region by a simple handle variable check. If you don't understand this, it is a good time to learn that in JASS everything goes from 0 up. So Player(0) is actually Player 1 - Red. Now blizzard, the smart people that they are, decided that the general public would be happier if everything went from 1 up. This was a very bad mistake IMO. So the developers decided to create the blizzard.j. Now there are a few good functions in there like Mod, but most are just crap functions. All they do is return the natives defined in the common.j but +1 to make it so that things went from 1 up. ConverPlayerId() is one of those functions. This is basically what it says in the blizzard.j.

Code:
function GetConvertedPlayerId takes player p returns integer
    return GetPlayerId(p) + 1
endfunction

Anyway, you have to watch out for this because they can be very nasty when trying to debug JASS code. The code that I wrote for you worked from 0 up becuase in the init function x was defined as 0. This meant that the first trigger created was associated with the 0th region. If you started your region array at 1 you will have problems using the code I gave you. You can either change x and then use blizzard.j functions (Bad idea IMO) or change your array to start from 0.
06-12-2004, 09:46 AM#10
Mjukland
Ok, I understood that the function Filter (Check), would test the conditions, but you had first written filter(check), and not function filter(check), and I were just to dumb to see that the "function" were missing, that's why I made the If in the action function to test if the trigger were working. I also understood what the handles made, when I read about it. that each trigger got a number for each region kind of.

I do have my array start at 0, and still I don't know why all special effects destroys and why, ( I was wrong about which player the regions were set to ) it actually were player = null, and not player = 0.

I have a trigger that makes all regions belong to player 9 at initiziaton, and then also create a gray cross on every region to mark that.

What happens is when the loop go more then 1200 loops, there r no cross's and the regions belong to player = null when you start the map, having it loop 1150 times and it will be like normal.

and Im not sure what you meant with this ? That's probably what's making the trigger not work?

"First of all make sure that your global RegionWorld is a rect global and not a region global."

thanks for all help :D
06-12-2004, 12:39 PM#11
Narwanza
Regions and rects are 2 different animals. A rect is a rectangle, and a region is any shape.
06-12-2004, 12:53 PM#12
Narwanza
I think the problem w/your special effects is that WC3 can only handle so many models at a time and I think over 1200 is just too many special effects for it.
06-12-2004, 01:12 PM#13
Mjukland
Quote:
Originally Posted by Narwanza
I think the problem w/your special effects is that WC3 can only handle so many models at a time and I think over 1200 is just too many special effects for it.

I have a trigger that creates a special effect at all 1768 regions, all special effect works, I don't think there r a limit for how many models wc3 can handle at a time, and all regions is "owned" by player 9 at initiziation. The special effect DO show up in game.

But its like the trigger that creates the effects and that set all region to player 9 at initziaton does'nt run when having this trigger run at initziation with more than 1200 loops. When having less then 1200 it runs like normal and all effects are there. It's realy strange. I had the game display the integer x in the loop, and it stopped at 1202, when it should had displayed 1767 at the end. :(
06-12-2004, 02:11 PM#14
Cubasis
Your problem is the WC3's all-popular statement limit.

There is a behind-the-scenes limit to the number of statements a single thread/trigger can run, and normally it's not in the way, but for some pretty heavy triggers, it becomes a problem, like yours.

First of all, are you running this trigger on Map Init?
if yes, then try first making it run then after 0.1 second that the game begun.

Also, draw down all the array sizes. They do nothing but make sure that WC3 "sets them" too a default value. So just be careful not too use a element that you haven't set somewhere before. (f.ex. if you never set MyArray[1001] too anything, then if you try to access it, the trigger will crash).

If it still doesn't run to the end on a 0.1 timer. Then your only option is to improve it's performance. Or in worse case, cut it up into a few triggers.

~Cubasis
06-12-2004, 11:00 PM#15
Mjukland
Ok, it did work when I triggerd the trigger 1sec after initziation. but the condtions won't work.

call TriggerRegisterEnterRegion(t,udg_RegionWorld[x],Filter(function check))

It's something wrong with the Filter expression?

Filter(function Check)
"Invalid number of argument"

Filter(function Check())
" expected ' "