• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] How to check if terrain is walkable?

Status
Not open for further replies.
Level 12
Joined
Jan 2, 2016
Messages
973
I have a trigger:
JASS:
  function FlightRequiresWalkable takes nothing returns boolean
      if GetIssuedOrderId() == OrderId("blink") and not IsTerrainPathable(GetOrderPointX(), GetOrderPointY(), PATHING_TYPE_WALKABILITY) then
          call IssueDelayedOrder(GetTriggerUnit(), "stop", "immediate", null, 0, 0)
      endif
      return false
  endfunction

//during initialization:
  call TriggerRegisterAnyUnitEventBJ( pr, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
  call TriggerAddCondition( pr, Condition( function FlightRequiresWalkable ) )
And the Delayed Order function does:
JASS:
  function IssueDelayedOrder takes unit u, string order, string ordType, unit target, real x, real y returns nothing
      local timer t
      local integer id
      if ordType == "immediate" then
          set t = GetFreeTimer()
          set id = GetHandleId(t)
          call SaveUnitHandle(udg_Table, id, 'unit', u)
          call SaveStr(udg_Table, id, 'ordr', order)
          call TimerStart(t, 0.00, false, function DelayedImmediateOrder)
          set t = null
      elseif ordType == "target" then
          set t = GetFreeTimer()
          set id = GetHandleId(t)
          call SaveUnitHandle(udg_Table, id, 'unit', u)
          call SaveStr(udg_Table, id, 'ordr', order)
          call SaveUnitHandle(udg_Table, id, 'targ', target)
          call TimerStart(t, 0.00, false, function DelayedTargetOrder)
          set t = null
      elseif ordType == "point" then
          set t = GetFreeTimer()
          set id = GetHandleId(t)
          call SaveUnitHandle(udg_Table, id, 'unit', u)
          call SaveStr(udg_Table, id, 'ordr', order)
          call SaveReal(udg_Table, id, 'tarx', x)
          call SaveReal(udg_Table, id, 'tary', y)
          call TimerStart(t, 0.00, false, function DelayedPointOrder)
          set t = null
      endif
  endfunction
But it doesn't work, and the unit keeps "blinking" to watter terrain and into forests...
How do I PROPERLY check if terrain is walkable?

EDIT: Actually, seems like the order given wasn't "blink" and that's why the trigger wasn't kicking in... Now it prevents me from blinking on the ground... I can only blink in water... The logic is stunning me..

EDIT 2: Actually, now I think I can make something, which will work..
When I remove the "not" from the condition - I can move around on the ground, but can't enter water (which is good, although weird, because of the syntax Blizzard has chosen). Now I can make a custom function to create a unit on the desired coordinates, and then compare the unit's coordinates to the original ones, if they aren't the same (or at least close) - it will return false xP

EDIT 3: Okay... I kind a managed to get it working.. Here are the triggers if you are having issues with similar problem :p
JASS:
  function IsPointWalkable takes real x, real y, real tollerance returns boolean
      local unit d = CreateUnit(Player(15), 'hfoo', x, y, 0)
      local real dist = (GetUnitX(d) - x)*(GetUnitX(d) - x) + (GetUnitY(d) - y)*(GetUnitY(d) - y)
      call RemoveUnit(d)
      set d = null
      return dist < tollerance*tollerance
  endfunction
JASS:
  function FlightRequiresWalkable takes nothing returns boolean
      local real x
      local real y
      local integer id
      if GetIssuedOrderId() == OrderId("divineshield") then
          set id = GetUnitTypeId(GetTriggerUnit())
          if id == 'E00U' or id == 'E00V' or id == 'E00W' then
              set x = GetOrderPointX()
              set y = GetOrderPointY()
              if IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) or not IsVisibleToPlayer(x, y, GetTriggerPlayer()) then
                  call IssueDelayedOrder(GetTriggerUnit(), "stop", "immediate", null, 0, 0)
                  call DisplayTextToPlayer(GetTriggerPlayer(), 0, 0, "Can't fly to that position!")
              elseif not IsPointWalkable(x, y, 100) then
                  call IssueDelayedOrder(GetTriggerUnit(), "stop", "immediate", null, 0, 0)
                  call DisplayTextToPlayer(GetTriggerPlayer(), 0, 0, "Can't fly to that position!")
              endif
          endif
      endif
      return false
  endfunction
I did the condition in this "tree shape" to make it as light as possible, and not to do unnecessary checks, unless the other conditions are fulfilled.
 
Last edited:
Status
Not open for further replies.
Top