• 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.

Counting number of players in a rect

Status
Not open for further replies.
Level 15
Joined
Aug 7, 2013
Messages
1,338
Hi,

I am trying to write a function that returns the number of players in rect, based on whether their hero is in it (versus a peon/footman).

This function works when I enter a region, but when I leave a region and immediately enter another, it returns the wrong value (0). It flip flops every other region.

Thus if my hero entered regions in this order:

r1 --> r2 --> r3

it would display: 1, 0, 1 for the player count

JASS:
function getPlayerCountInRect takes rect r returns integer
	local integer i = 0
	local integer count = 0
	loop
		exitwhen i == TOTAL_PLAYERS
		if isUnitInRect(playerDatum[i].pc.u, r) then
			set count = count + 1
		endif
		set i = i + 1
	endloop
	return count
endfunction


JASS:
function isLocInRect2 takes location whichLoc, rect whichRect returns boolean
	local real x = GetLocationX(whichLoc)
	local real y = GetLocationY(whichLoc)
	if x >= GetRectMinX(whichRect) and x <= GetRectMaxX(whichRect) and y >= GetRectMinY(whichRect) and y <= GetRectMaxY(whichRect) then
		return true
	endif
	return false
endfunction

function isUnitInRect takes unit whichUnit, rect whichRect returns boolean
	return isLocInRect2(GetUnitLoc(whichUnit), whichRect)
endfunction


JASS:
    static method leaveMain takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local player p = GetOwningPlayer(GetTriggerUnit())
        local integer pid = GetPlayerId(p)
        local CreepRegion cr
        if GetTriggerUnit() == playerDatum[pid].pc.u then
            set cr = findCreepRegion(GetTriggeringRegion())
            if playerDatum[pid].creepRegion == cr.creepTableId then
                set playerDatum[pid].creepRegion = -1
                set playerDatum[pid].creepFreq = 0
            endif
            set cr.totalPlayers = cr.totalPlayers - 1
        endif
        return false
    endmethod
    
    static method enterMain takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local player p = GetOwningPlayer(GetTriggerUnit())
        local integer pid = GetPlayerId(p)
        local CreepRegion cr
        if GetTriggerUnit() == playerDatum[pid].pc.u then
            set cr = findCreepRegion(GetTriggeringRegion())
			call print("players in rect: " + I2S(getPlayerCountInRect(cr.rRect)))
            set playerDatum[pid].creepRegion = cr.creepTableId
            set playerDatum[pid].creepFreq = cr.freq
            set cr.totalPlayers = cr.totalPlayers + 1
        endif
        return false
    endmethod
 
Try This

I simple function to brute force check it. It should work for your needs. If your rects are large and/or contain a large number of units and this function is called a lot then I suggest using a state based system with enters/leaves region events. However, since this works on rects and not regions you can get away with more dynamic use.
JASS:
function CountPlayersInRect takes rect R returns integer
    local group G=CreateGroup()
    local unit Unit
    local integer Ret=0
    local integer Pid
    local boolean array Counted
    call GroupEnumUnitsInRect(G,R,null)
    loop
        set Unit=FirstOfGroup(G)
        exitwhen Unit==null
        call GroupRemoveUnit(G,Unit)
        if IsUnitType(Unit,UNIT_TYPE_HERO)then
            set Pid=GetPlayerId(GetOwningPlayer(Unit))
            if not Counted[Pid]then
                set Counted[Pid]=true
                set Ret=Ret+1
            endif
        endif
        set Unit=null
    endloop
    call DestroyGroup(G)
    set G=null
    return Ret
endfunction
 
Status
Not open for further replies.
Top