HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

TerrainPathability == Crash

08-31-2009, 08:59 PM#1
darkwulfv
So, I brought this up to Dusk weeks ago and it left both of us baffled. His library (TerrainPathability) was causing fatal errors in my map when the map was closed, and then suddenly 7 seconds into every game, every time. Neither of us could figure out why. I found the problem to be caused by TP by disabling all the systems in the map and systematically enabling them. Whenever TP was enabled, the map crashed. When it was disabled, the map ran fine.

Once 1.24 and the new Jasshelper were released, as well as a new version of TerrainPathability, I thought I'd give it another shot and see if it worked. Well, now the map doesn't even make it past loading before it fatals.

The only way TerrainPathability is ever referenced is by his Knockback system; I don't use TP any other way.

If anyone has some insight onto what the heck is going on (Vexorian's opinion would be nice, since it could be something with Jasshelper), please post. His script is below, as well as the map. TerrainPathability is under the "Scripts" folder. It is disabled.

Collapse JASS:
library TerrainPathability initializer Initialization
//******************************************************************************
//* BY: Rising_Dusk
//* 
//* This can be used to detect the type of pathing a specific point of terrain
//* is, whether land, shallow water, or deep water. This type of detection
//* should have been easy to do using natives, but the IsTerrainPathable(...)
//* native is very counterintuitive and does not permit easy detection in one
//* call. For that reason, this library was developed.
//*
//* The system requires a dummy unit of some sort. There are no real
//* requirements upon the dummy unit, but it needs a non-zero movement speed.
//* More importantly than the dummy unit, though, it needs a custom windwalk
//* based unit ability with a 0.00 duration and no fade time. Both of those
//* raw id's (for the unit and windwalk dummy) need to be configured below.
//*
//* There is an objectmerger call available for those of you too lazy to build 
//* your own windwalk based ability. Simply uncomment it below and save once,
//* then close and reopen your map and recomment the line.
//*
globals
    constant integer TERRAIN_PATHING_DEEP                           = 1
    constant integer TERRAIN_PATHING_SHALLOW                        = 2
    constant integer TERRAIN_PATHING_LAND                           = 3
    constant integer TERRAIN_PATHING_WALKABLE                       = 4
    
    private unit Dummy                                              = null
    private constant integer DUMMY_UNIT_ID                          = 'hfoo'
    private constant integer DUMMY_WINDWALK_ID                      = 'win&'
    private constant player OWNING_PLAYER                           = Player(15)
    
    //* These variables shouldn't be adjusted
    private real WorldMinX                                          = 0.
    private real WorldMinY                                          = 0.
endglobals

////! external ObjectMerger w3a ANwk win& anam "Collision Ability" ansf "" Owk3 1 0.0 Owk4 1 0 Owk2 1 0.0 Owk1 1 0.0 acdn 1 0.0 ahdu 1 0.0 adur 1 0. aher 0 amcs 1 0

function IsTerrainPathingType takes real x, real y, integer terrainPathingType returns boolean
    local boolean b = false
    if terrainPathingType == TERRAIN_PATHING_DEEP then
        set b = not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
    elseif terrainPathingType == TERRAIN_PATHING_SHALLOW then
        set b = not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
    elseif terrainPathingType == TERRAIN_PATHING_LAND then
        set b = IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)
    elseif terrainPathingType == TERRAIN_PATHING_WALKABLE then
        call SetUnitPosition(Dummy, x, y)
        set b = GetUnitX(Dummy) == x and GetUnitY(Dummy) == y and not (not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
        call SetUnitX(Dummy, WorldMinX)
        call SetUnitY(Dummy, WorldMinY)
    endif
    return b
endfunction

private function Initialization takes nothing returns nothing
    set WorldMinX = GetRectMinX(bj_mapInitialPlayableArea)
    set WorldMinY = GetRectMinY(bj_mapInitialPlayableArea)
    set Dummy = CreateUnit(OWNING_PLAYER, DUMMY_UNIT_ID, WorldMinX, WorldMinY, 0.)
    call UnitAddAbility(Dummy, DUMMY_WINDWALK_ID)
    call UnitAddAbility(Dummy, 'Avul')
    call IssueImmediateOrderById(Dummy, 852129)
    call SetUnitX(Dummy, WorldMinX)
    call SetUnitY(Dummy, WorldMinY)
endfunction
endlibrary
08-31-2009, 10:13 PM#2
Rising_Dusk
I can't believe that it's TerrainPathability, though, because OD uses TerrainPathability in exactly the same form as it is submitted and you use. It seems very inconsistent, like you might have a name conflict somewhere or somehow that PJASS isn't reporting and JassHelper is handling strangely.
08-31-2009, 10:43 PM#3
Bobo_The_Kodo
Collapse JASS:
library TerrainPathability initializer Initialization
//******************************************************************************
//* BY: Rising_Dusk
//* 
//* This can be used to detect the type of pathing a specific point of terrain
//* is, whether land, shallow water, or deep water. This type of detection
//* should have been easy to do using natives, but the IsTerrainPathable(...)
//* native is very counterintuitive and does not permit easy detection in one
//* call. For that reason, this library was developed.
//*
//* The system requires a dummy unit of some sort. There are no real
//* requirements upon the dummy unit, but it needs a non-zero movement speed.
//* More importantly than the dummy unit, though, it needs a custom windwalk
//* based unit ability with a 0.00 duration and no fade time. Both of those
//* raw id's (for the unit and windwalk dummy) need to be configured below.
//*
//* There is an objectmerger call available for those of you too lazy to build 
//* your own windwalk based ability. Simply uncomment it below and save once,
//* then close and reopen your map and recomment the line.
//*
globals
    constant integer TERRAIN_PATHING_DEEP                           = 1
    constant integer TERRAIN_PATHING_SHALLOW                        = 2
    constant integer TERRAIN_PATHING_LAND                           = 3
    constant integer TERRAIN_PATHING_WALKABLE                       = 4
    
    private unit Dummy                                              = null
    private constant integer DUMMY_UNIT_ID                          = 'hfoo'
    private constant integer DUMMY_WINDWALK_ID                      = 'win&'
    private constant player OWNING_PLAYER                           = Player(15)
    
    //* These variables shouldn't be adjusted
    private real WorldMinX                                          = 0.
    private real WorldMaxY                                          = 0.
endglobals

////! external ObjectMerger w3a ANwk win& anam "Collision Ability" ansf "" Owk3 1 0.0 Owk4 1 0 Owk2 1 0.0 Owk1 1 0.0 acdn 1 0.0 ahdu 1 0.0 adur 1 0. aher 0 amcs 1 0

function IsTerrainPathingType takes real x, real y, integer terrainPathingType returns boolean
    local boolean b = false
    if terrainPathingType == TERRAIN_PATHING_DEEP then
        set b = not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
    elseif terrainPathingType == TERRAIN_PATHING_SHALLOW then
        set b = not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
    elseif terrainPathingType == TERRAIN_PATHING_LAND then
        set b = IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)
    elseif terrainPathingType == TERRAIN_PATHING_WALKABLE then
        call SetUnitPosition(Dummy, x, y)
        set b = GetUnitX(Dummy) == x and GetUnitY(Dummy) == y and not (not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
        call SetUnitX(Dummy, WorldMinX)
        call SetUnitY(Dummy, WorldMaxY)
    endif
    return b
endfunction

private function Initialization takes nothing returns nothing
    set WorldMinX = GetRectMinX(bj_mapInitialPlayableArea)+16
    set WorldMaxY = GetRectMaxY(bj_mapInitialPlayableArea)-16
    set Dummy = CreateUnit(OWNING_PLAYER, DUMMY_UNIT_ID, WorldMinX, WorldMaxY, 0.)
    call UnitAddAbility(Dummy, DUMMY_WINDWALK_ID)
    call UnitAddAbility(Dummy, 'Avul')
    call IssueImmediateOrderById(Dummy, 852129)
    call SetUnitX(Dummy, WorldMinX)
    call SetUnitY(Dummy, WorldMaxY)
endfunction
endlibrary

Welcome :)
You had GetWorldBounds() same dimensions as bj_mapInitialPlayableArea -> dummy was being created on very edge of map -> crash
08-31-2009, 10:56 PM#4
darkwulfv
Thanks Bobo, but the question is, why would it only crash for me, not Dusk?
PS: Your fix changed nothing. It still crashes at the exact same spot (before the map finishes loading; approx 3/4 of the way in). Sorry.

Dusk: I find it confusing too, but I swear it's TP. Whether PJASS or JassHelper is acting strange, I cannot say, so I'd like Vex/Pitzer/etc.'s input as well. It's not a naming conflict, as your library is private and I (obviously) have no other libraries by the same name as yours. And besides, a naming conflict would make a syntax error, not a fatal crash error.
08-31-2009, 11:52 PM#5
Bobo_The_Kodo
Quote:
PS: Your fix changed nothing. It still crashes at the exact same spot (before the map finishes loading; approx 3/4 of the way in). Sorry.
It crashed there for me before I made that change, and now it doesn't! :<

Try putting return as the first line of the init function and see if it still crashes
09-01-2009, 12:23 AM#6
Rising_Dusk
Quote:
Originally Posted by Bobo_The_Kodo
You had GetWorldBounds() same dimensions as bj_mapInitialPlayableArea -> dummy was being created on very edge of map -> crash
Quote:
Originally Posted by Bobo_The_Kodo
It crashed there for me before I made that change, and now it doesn't! :<
That crashes? Fuck Troll-Brain. I'll go fix the library now.
09-01-2009, 02:01 AM#7
darkwulfv
Quote:
Try putting return as the first line of the init function and see if it still crashes
This works, but obviously breaks the library. I've yet to get your "+/- 16" fix to work for me.

Dusk, would spawning the unit at the center of the map break anything? I think that my case may be special, as the unit might be spawning into boundary (I've got large chunks of my map painted in boundary to save on doodads and prevent huge tracts of blank land). I don't know if units in boundary causes crashes, but...

EDIT!: Haha! By changing the dummy units' placement to the center of the map (0,0) the crash no longer exists. I don't think it breaks the system either, which means that all may be well after all. Who woulda thunk it.

Hey Dusk, maybe you should mention somewhere that having painted boundary on the map may cause the system to act up, and to remedy it change the spawning x/y to a coordinate that one knows is safe?
09-01-2009, 02:06 AM#8
Rising_Dusk
/facepalm
09-01-2009, 02:11 AM#9
darkwulfv
Quote:
/facepalm
Yeah the thought didn't really occur to me (other than being unsure of how units react in boundary) until I saw that the unit was being spawned at the world bounds, not the center of the map like I thought it had been (it was before, I think). I'm a bit /facepalm too.
09-01-2009, 03:05 AM#10
Bobo_The_Kodo
Did you just do +16/-16 or actually copy the whole code i posted?
09-01-2009, 03:13 AM#11
darkwulfv
I just did the +16/-16. Why, did you change other things?

Nonetheless, the problem appears fixed now.
09-01-2009, 04:19 AM#12
Rising_Dusk
He changed the spawn location to be GetRectMaxY instead of GetRectMinY, which changes the corner of the map that the footman is spawned on. Just the +/-16 would've surely crashed in the bottom left corner.
09-01-2009, 03:55 PM#13
Troll-Brain
Quote:
That crashes? Fuck Troll-Brain. I'll go fix the library now.
Sorry if it was the issue, it always worked for me.

But it's very strange, since you use bj_mapInitialPlayableArea and not GetWorldsBound (which also work for me but because it's outside the playable map area maybe it would crash more easily)
09-01-2009, 07:31 PM#14
Bobo_The_Kodo
Quote:
But it's very strange, since you use bj_mapInitialPlayableArea and not GetWorldsBound (which also work for me but because it's outside the playable map area maybe it would crash more easily)
In this maps case GetWorldBounds is the same as bj_mapInitialPlayableArea was* the problem