HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Multi-player only bug

10-26-2007, 07:56 PM#1
aaero
This bug has only occurred when testing the map online - it works fine in single player.

My desired functionality is 4 regions (actually, rects) that I put on the map at a certain point. Every player has control of only one unit, max 4 players. I want each player to stand in a different one of the regions simultaneously. Got it? One unit in each region. The regions have a distinct environmental effect so they are easy to recognize. Currently, the regions are visible, spawn appropriately - no problems there. My problem is in trying to detect is a player has a unit in each of them.

The behavior I get with multiple players is very odd. Here's the code:

Collapse JASS:
// This is the code that runs whenever a unit enters one of the regions.
function Switch_Enter_Actions takes nothing returns nothing
    local integer i = 0
    if (UnitIsHero(GetEnteringUnit()) == true) then
      set udg_S1_SwitchesFlipped = 0
      loop      
          if (HeroInRect(udg_S1_Region[i]) == true) then
             set udg_S1_SwitchesFlipped = udg_S1_SwitchesFlipped + 1
          endif
          set i = i + 1
        exitwhen i > 3
      endloop
      
      if (udg_S1_SwitchesFlipped < udg_HeroCount) then
        call DisplayTextToPlayer(GetOwningPlayer(GetEnteringUnit()), 0., 0., "You have activated this switch. As long as you stand here, the switch will remain active.")
        call DisplayTextToPlayer(GetOwningPlayer(GetEnteringUnit()), 0., 0.,"(" + I2S(udg_S1_SwitchesFlipped) + " / " + I2S(udg_HeroCount) + " switches Active.)")
      else
       call DisableTrigger(gg_trg_Stage_1_Switch_Enter)
       call EnableTrigger(gg_trg_Stage_1_Checkpoint_Reached)
       call DisplayTextToForce(GetPlayersAll(), "All switches active! Make it to the portal alive and you escape!")
      endif
    endif
endfunction

Collapse JASS:
// This is the function that might have the problem. The udg_Hero array is a
// unit array that stores the unit for a particular player. It's indexed by playerid,
// ie udg_Hero[0] is Player 1 - Red's unit.
function HeroInRect takes rect r returns boolean
    local integer i = 0
    loop
        if (IsUnitInRangeXY( udg_Hero[i], GetRectCenterX(r), GetRectCenterY(r), 250. )) then
            return true
        endif
        set i = i + 1
        exitwhen i > 3
    endloop
    
    return false
endfunction

Expand JASS:

The results were as follows (tested with two people). The udg_S1_SwitchesFlipped was always 1 - we always got a message that said "1/2 Switches Active". Sometime I got that message multiple times - up to 4 times, in fact.

I know this is a lot to look over. Thanks for reading this far, and thanks for any ideas/suggestions.
10-27-2007, 07:34 AM#2
Pyrogasm
Instead of this: IsUnitInRangeXY( udg_Hero[i], GetRectCenterX(r), GetRectCenterY(r), 250. ))
Try doing this:
Collapse JASS:
function HeroInRect takes rect r returns boolean
    local integer i = 0
    local real ux
    local real uy
    local real minx = GetRectMinX(r)
    local real maxx = GetRectMaxX(r)
    local real miny = GetRectMinY(r)
    local real maxy = GetRectMaxY(r)

    loop
        set ux = GetUnitX(udg_Hero[i])
        set uy = GetUnitY(udg_Hero[i])
        if ((ux > minx) and (ux < maxx) and (uy > miny) and (uy < maxy)) then
            return true
        endif
        set i = i + 1
        exitwhen i > 3
    endloop
    
    return false
endfunction
10-27-2007, 05:23 PM#3
Strilanc
Small warning: the 'enters region' event may fire BEFORE a unit is actually inside the region. You may want a "is almost inside" function.
10-27-2007, 06:29 PM#4
aaero
Pyro -

You're not exactly enabling my laziness. I know that making that function call (IsUnitInRangeXY) is slower than your method (and slightly more accurate, since you're using a square where I'm using a circle. I'll go ahead and use it though, since you took all the time to type it out for me :).

Strilanc -

I tested this all and it worked pretty much perfectly last night, and I came to the conclusion that you nailed the problem. My math skills were failing me - my region was a 400 x 400 box, and I was checking a circle with radius 250 from the center thinking that would give me plenty of extra space. Some simple geometry will tell you the distance from the center to a corner is ~283, which is the minimum I'd want my circle radius to be. Either way, I'll use Pyro's method but expand the bounds of the box a bit (ie minx = GetRectMinX(r) - 50, etc).

Thanks to both of you.
10-27-2007, 09:19 PM#5
Pyrogasm
Why not just make the rects bigger in the editor?

Edit: Oh, that's why.