[Trigger] Get Triggering Region/Rect?

Level 10
Joined
Jan 30, 2020
Messages
275
Is there still no way of getting the triggering Region/Rect?

I know this was impossible 10 years ago, but is it sill impossible?

  • GetTriggeringRect
    • Events
      • Unit - A unit enters MainArenaNorth <gen>
      • Unit - A unit enters MainArenaSouth <gen>
      • Unit - A unit enters MainArenaWest <gen>
      • Unit - A unit enters MainArenaEast <gen>
    • Conditions
    • Actions
      • Set temp_region = (Entire map) <-- But "Event Response - Get entered region", it does not exist.
      • Custom script: set udg_temp_region = GetTriggeringRect() <-- Does something like this exist?
I want to do almost the same thing, for a unit, with some conditions, etc. but refer to the entered region.

I can ofc do a work-around with X number of triggers, but I'd hope that was not needed.
 
Level 12
Joined
Jan 1, 2018
Messages
530
It is possible, just not in GUI I think, because the GUI event convert a rect (called a region in GUI) to a region (confusing I know).
The function to get the triggering region is constant native GetTriggeringRegion takes nothing returns region.
 
Level 13
Joined
May 10, 2009
Messages
868
The problem with that event in GUI is that it hides the truth from the map maker. Unfortunately, the editor calls them "regions" everywhere, but their real type is "rect". The event works with "region" on the other hand.

This is what happens, in truth. When the game loads your trigger events, a real region is created and copies the size of the rect mentioned in the event. From now on, the new region is used.

For example:
  • Events
    • Unit - A unit enters Region 000 <gen>
    • -------- Region 000 <gen> is a rect --------
Upon map save, this is what the event turns into
JASS:
// The following line of code is responsible for adding "a unit enters region" event to a trigger.
call TriggerRegisterEnterRectSimple( gg_trg_Trigger_Name, gg_rct_Region_000 )

// Let's see how that function really works internally
function TriggerRegisterEnterRectSimple takes trigger trig, rect r returns event
    local region rectRegion = CreateRegion() // Creates a new "region"

    call RegionAddRect(rectRegion, r) // This copies the size of the rect mentioned
    // in the GUI event and passes it to the newly created region.

    return TriggerRegisterEnterRegion(trig, rectRegion, null) // Finally, this line will add the
    // event to your trigger, and will only accept the new "region". The "rect" that was pre-placed
    // on the map is now useless.
endfunction
GetTriggeringRegion() native will return the actual region that triggered the event, but it has nothing to do with rects.

It's possible to do what you want, but you'd have to edit the event yourself and use a hashtable to associate a rect with a region, and use GetTriggeringRegion to retrieve the rect. However, that might now be a problem for you, because you'll have to ditch the old event and use a custom script in order to add new events to triggers.
 
Level 6
Joined
Mar 7, 2011
Messages
124
you could push GUI to do what you want, but
it would be awkward, making for some complex GUI
duplicate some logic, making changing triggered rects more of a process
and it might have performance issues if you had lots of rects or units that are triggering the event
to implement this feature with GUI you'd put all your evented rects into a rect array. when a unit-enters-rect event was triggered, you'd then iterate the array until you found the rect which contained the triggering unit

i don't love this approach because you're essentially reimplementing a large part of the logic for the unit enters rect event, just to stick with the GUI toolset. at the same time, i don't hate it either, because you're not really introducing any real problems. the biggest headache will be maintaining your evented rect array, and that's not that bad
the biggest draw to this approach is that you get to keep your GUI event, which makes it simple to handle that event with more GUI code

id recommend this approach if youre either not familiar with JASS (or another programming language) or your interest is mainly making the game, rather than coding logic

It feels like I'd better just make the whole thing i jass xD
I should be possible to make it way cleaner...
maybe. it'd definitely make getting the triggering rect more elegant, but that's more for your sake as a developer than the map's sake. the GUI unit-enters-region event declares its region in an inaccessible scope, preventing you from comparing it later on via GetTriggeringRegion.
replacing the unit-enters-region event is a good use for JASS or Lua. a custom implementation will let you easily access the triggered rect from the event's callback, simply passing it as a global rect, and the custom approach will be more flexible if you have performance issues or other custom needs down the road

that said, it'll also start you down the slippery slope of managing a map that's both JASS and GUI. the biggest drawback to this approach comes from having a JASS event, your new custom unit-enters-rect event, that you probably want to handle, at least occasionally, with GUI code. how will you call the GUI code from your JASS? what once was a nicely organized GUI trigger - clearly stating its event, conditions, and actions - will now be split across multiple different components of your implementation separating the event from the rest. none of this is a dealbreaker, but it is to say that some parts of your code will become cleaner, while other parts will become uglier

some of these recommendations might be a bit out of date, but if you go this route you'll probably want to start with an existing event library, like https://github.com/nestharus/JASS/blob/master/lua/wc3 project/Sample/mapname/src/imports/Event/script.j

you would then use it like
JASS:
globals
    Event OnUnitEntersRect
    unit EventUnit
    rect EventRect
endglobals

//psuedo jass
private function checkRects takes nothing returns nothing
    foreach unit in units-of-interest
        foreach rect in rects-with-events
           if unit inside rect then
               set EventUnit = unit
               set EventRect = rect
               call OnUnitEntersRect.fire()
           endif
        endloop
    endloop
endfunction

public function registerRect takes rect r returns nothing
    call rects-with-events.add(r)
endfunction

private function onInit takes nothing returns nothing
    call checkRects() every .035 seconds //this is the time rate the vanilla event is based off
endfunction

hopefully units-of-interest is a small group in your map, one that you feel comfortable managing. if youre trying to check all the units on the map then you might run into performance issues using the vanilla approach. at that point, you should start looking at auto indexers, which will essentially cache that information for you to access quickly

i also like bloodsoul's suggestion as a middle ground. by wrapping the existing TriggerRegisterEnterRegion logic you get the existing logic plus your custom association between the rect and its region. this option still has the same issues as the JASS approach, connecting JASS to GUI. if you want to get this working ASAP, do bloodsoul's suggestion, if you want to make a lot of weird custom shit, go this other route

if all this is sounding horrifying, then just see how far you can get on the GUI approach
 
Last edited:
Level 10
Joined
Jan 30, 2020
Messages
275
Before your answer, I finally did this:

  • WarlockOrderPortalSouth
    • Events
      • Unit - A unit enters MainArenaSouth <gen>
    • Conditions
      • Whatever I need, unit-type checking, .
    • Actions
      • Set temp_region = MainArenaSouth <gen>
      • Trigger - Run WarlockOrderPortal <gen> (ignoring conditions)
One for each region I wanted to handle
Then have one:

  • WarlockOrderPortal
    • Events
    • Conditions
    • Actions
      • Set temp_point = (Random point in temp_region)
      • ... Whatever I wanted to do, order triggering unit to cast something at temp_point.
      • Custom script: call RemoveLocation(udg_temp_point)
This is in a folder containing all the Warlock-triggers.
It's ok structure and straight forward, but split-up in multiple triggers.

I'm a developer, working with code every (work) day. But I have not put the time to get to know jass and all the natives and find a tool that's actually good.
When I work on my map, I usually want to get things done (because I don't have that much time to put on it and right now I kind of want to get the map to a good "finished" state).
Fairly often a few lines of custom code is needed to do stuff such as lightning effects (with height), math and ofc leak-proof stuff.
 
Level 6
Joined
Mar 7, 2011
Messages
124
that's a good idea too, i didn't think of that. i like your approach, it's easier than my gui recommendation so long as you don't have too many rects that you need to do

in general i think focusing on the game aspect is a great way to fit a hobby in around work. it can be fun to just focus on making a game and not worry so much about how ideal the code is
 
Top