• 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] Memory leak or optimization problem?

Status
Not open for further replies.
Level 8
Joined
Jan 14, 2005
Messages
105
Hello, hoping someone can help me optimizing this trigger.

What this trigger is:
It periodically checks if the Hero "GetOwningPlayer(GetFilterUnit()) == Player(1)" is in 90 degrees in front of the enemy's unit "Enemy[a]" and there should be no pathing blocker in between "YTpc".

As you can see, it's pretty unoptimized, since I made it in a rush, and I don't know if it leaks. I tried cleaning every leak that I know, but there must still be something that I missed.

This is made in v1.31 btw.

JASS:
function AILineofSightFunc01 takes nothing returns boolean
    return GetDestructableTypeId(GetFilterDestructable()) == 'YTpc'
endfunction

function AILineofSightFunc02 takes nothing returns boolean
    return GetOwningPlayer(GetFilterUnit()) == Player(1) and IsUnitVisible(GetFilterUnit(), Player(2))
endfunction

function Trig_AI_Line_of_Sight_B_Actions takes nothing returns nothing
  local integer a
  local integer b
  local integer c
  local integer i
  local integer maxdistance
  local location array l
  local location k
  local location m
  local rect n
  local real r
  local destructable d
  local group g
  local boolean v

  set a = udg_tempInt_1
  set maxdistance = 10
  set g = null

  set m = GetUnitLoc(udg_Enemy[a])
  set r = GetUnitFacing(udg_Enemy[a])
  set i = 0 //number of locations checked all throughout

  //check straight line first
  set c = 1
  loop
  exitwhen c > maxdistance
    //checking for obstacles
    set k = PolarProjectionBJ(m, (c*100), r)
    set n = RectFromCenterSizeBJ(k, 200, 200)
    set d = null
    set d = RandomDestructableInRectBJ(n, Condition(function AILineofSightFunc01))
    if d == null then //if no obstacles found, continue searching
      set i = i + 1
      set l[i] = PolarProjectionBJ(m, (c*100), r)
    else
      set c = maxdistance
    endif
    call RemoveLocation(k)
    call RemoveRect(n)
    set c = c + 1
  endloop

  //check right side (negative 11.25 degrees * 4)
  set b = 1
  loop
  exitwhen b > 4
    set c = 1
    loop
    exitwhen c > maxdistance
      set k = PolarProjectionBJ(m, (c*100), r-(b*11.25))
      set n = RectFromCenterSizeBJ(k, 200, 200)
      set d = null
      set d = RandomDestructableInRectBJ(n, Condition(function AILineofSightFunc01))
      if d == null then //if no obstacles found, continue searching
        set i = i + 1
        set l[i] = PolarProjectionBJ(m, (c*100), r-(b*11.25))
      else
        set c = maxdistance
      endif
      call RemoveLocation(k)
      call RemoveRect(n)
      set c = c + 1
    endloop
    set b = b + 1
  endloop

  //check left side (11.25 degrees * 4)
  set b = 1
  loop
  exitwhen b > 4
    set c = 1
    loop
    exitwhen c > maxdistance
      set k = PolarProjectionBJ(m, (c*100), r+(b*11.25))
      set n = RectFromCenterSizeBJ(k, 200, 200)
      set d = null
      set d = RandomDestructableInRectBJ(n, Condition(function AILineofSightFunc01))
      if d == null then //if no obstacles found, continue searching
        set i = i + 1
        set l[i] = PolarProjectionBJ(m, (c*100), r+(b*11.25))
      else
        set c = maxdistance
      endif
      call RemoveLocation(k)
      call RemoveRect(n)
      set c = c + 1
    endloop
    set b = b + 1
  endloop
  call RemoveLocation(m)

  set m = null
  set k = null
  set n = null
  set d = null

  set v = false
  //Check all created locations
  set b = 1
  loop
  exitwhen b > i
    call GroupClear(g)
    set g = GetUnitsInRangeOfLocMatching(40, l[b], Condition(function AILineofSightFunc02))
    if IsUnitGroupEmptyBJ(g) == false then
      set v = true   //The AI found the hero!
    endif
    call DestroyGroup(g)
    call RemoveLocation(l[b])
    set l[b] = null
    set b = b + 1
  endloop
  set g = null

  //Check if the AI found the hero or not
  if v then
    call TriggerExecute( gg_trg___AI_Hostility )
  else
    call TriggerExecute( gg_trg___AI_Hostility_Reduce )
  endif
endfunction

//===========================================================================
function InitTrig_AI_Line_of_Sight_B takes nothing returns nothing
    set gg_trg_AI_Line_of_Sight_B = CreateTrigger(  )
    call TriggerAddAction( gg_trg_AI_Line_of_Sight_B, function Trig_AI_Line_of_Sight_B_Actions )
endfunction
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
This may help: [vJASS] - [Snippet] IsPathBlockerInBetween

Regarding your code, maybe change this:
vJASS:
    if IsUnitGroupEmptyBJ(g) == false then
      set v = true   //The AI found the hero!
    endif
To this:
vJASS:
if FirstOfGroup(g) != null then
  set v = true
endif

I assume the latter is more efficient. But aside from that it looks like you're clearing all of the leaks.

Also, is this meant to work for Players 1 and 2? Because Player(1) and Player(2) are equal to Player 2 and 3.
 
Last edited:
Level 8
Joined
Jan 14, 2005
Messages
105
Thanks for the help!

Sadly , the first trigger I posted has a noticeable performance issue when running it periodically. I tried limiting the number of times it runs, but it can only do so much without sacrificing the gameplay. My friend even got a crash upon reloading the map. Do you think using rects would be more efficient instead of groups?

Also, is this meant to work for Players 1 and 2? Because Player(1) and Player(2) are equal to Player 2 and 3.[/code]
Sorry forgot to mention it. Player(1) is the Hero and Player(2) is the enemy[a], so yes Players 2 and 3.

EDIT:
Please disregard the trigger causing the crash. He tested the map again now with the trigger disabled and it still crashes upon reload.
 
Last edited:
Level 16
Joined
Sep 29, 2008
Messages
366
you have a boolexpr leak in set g = GetUnitsInRangeOfLocMatching(40, l, Condition(function AILineofSightFunc02))
this Condition(function AILineofSightFunc01) and this Condition(function AILineofSightFunc02) are boolexpr and they leak


define them as

JASS:
local boolexpr filter = Condition(function AILineofSightFunc02)
...
set g = GetUnitsInRangeOfLocMatching(40, l[b], filter)
call DestroyBoolExpr(filter)
set filter = null
Same for "Condition(function AILineofSightFunc01)"


In other way, it's strongly recommended use of coordinates instead locations.

translation samples from location to coords (these are just suggestions to improve the code)
JASS:
local real x = GetUnitX(udg_Enemy[a])
local real y = GetUnitY(udg_Enemy[a])

local real iDegree = r-(b*11.25)

//these vars replace use of PolarProjectionBj

local real targetX = c*100 * Cos(iDegree * bj_DEGTORAD)
local real targetY = c*100 * Sin(iDegree * bj_DEGTORAD)


//replace RectFromCenterSize with this one
set n = Rect(x-200,y-200,x+200,y+200)

Replace location arrays with coords array
JASS:
local real array lx
local real array ly
....

//replace set l[i] = PolarProjectionBJ(m, (c*100), r)  with

set lx[i] = c*100 * Cos(r * bj_DEGTORAD)
set ly[i] = c*100 * Sin(r * bj_DEGTORAD)

//use GroupEnumUnitsInRange instead GetUnitsInRangeOfLocMatching

set filter = Condition(function AILineofSightFunc02)
call GroupEnumUnitsInRange(g,lx[b],ly[b],40,filter)
call DestroyBoolExpr(filter)
set filter = null
...

 
Level 8
Joined
Jan 14, 2005
Messages
105
you have a boolexpr leak in set g = GetUnitsInRangeOfLocMatching(40, l, Condition(function AILineofSightFunc02))
this Condition(function AILineofSightFunc01) and this Condition(function AILineofSightFunc02) are boolexpr and they leak


define them as

JASS:
local boolexpr filter = Condition(function AILineofSightFunc02)
...
set g = GetUnitsInRangeOfLocMatching(40, l[b], filter)
call DestroyBoolExpr(filter)
set filter = null
Same for "Condition(function AILineofSightFunc01)"


In other way, it's strongly recommended use of coordinates instead locations.

translation samples from location to coords (these are just suggestions to improve the code)
JASS:
local real x = GetUnitX(udg_Enemy[a])
local real y = GetUnitY(udg_Enemy[a])

local real iDegree = r-(b*11.25)

//these vars replace use of PolarProjectionBj

local real targetX = c*100 * Cos(iDegree * bj_DEGTORAD)
local real targetY = c*100 * Sin(iDegree * bj_DEGTORAD)


//replace RectFromCenterSize with this one
set n = Rect(x-200,y-200,x+200,y+200)

Replace location arrays with coords array
JASS:
local real array lx
local real array ly
....

//replace set l[i] = PolarProjectionBJ(m, (c*100), r)  with

set lx[i] = c*100 * Cos(r * bj_DEGTORAD)
set ly[i] = c*100 * Sin(r * bj_DEGTORAD)

//use GroupEnumUnitsInRange instead GetUnitsInRangeOfLocMatching

set filter = Condition(function AILineofSightFunc02)
call GroupEnumUnitsInRange(g,lx[b],ly[b],40,filter)
call DestroyBoolExpr(filter)
set filter = null
...
Thanks for the advice. Yes, using coords seems to be the most efficient way to do this. I will be rewriting the code that way.

And thanks for reminding me of the boolexpr leak, you're right it seems to be the source of the leak.

You've been a great help!
 
Status
Not open for further replies.
Top