Page 1 of 1

Navigation data/meshes

Posted: Thu Jun 04, 2015 9:20 pm
by Doldol
Long story short, I was working on a death match spawn system and dreading the thought of having to setup spawn points for it, but then I realised that .nav files essentially already have detailed data of this kind, and I was thinking about just using locations marked hiding spots in the nav data as spawn points.

I was searching/looking through the forums and the repo, but I couldn't really find anything related to this. I would rather not have to completely study the nav files and parse them, as I'd think the engine already has to know all the navigation data from the map since it has to control the bots, I would rather ask the engine, if that's the case.

Posted: Thu Jun 04, 2015 9:30 pm
by necavi
https://github.com/AnthonyIacono/War3SourceV2/tree/master/Nav Here's some information on how to parse it if you can't find anything easily accessible in the engine.

Posted: Fri Jun 05, 2015 12:32 am
by Doldol
necavi wrote:https://github.com/AnthonyIacono/War3SourceV2/tree/master/Nav Here's some information on how to parse it if you can't find anything easily accessible in the engine.


Yup, I think I got it to work, quickly but dirty (my map version was 9, I only translated the code applicable to that version).

(Class is from Active State)

Syntax: Select all

import struct

class BinaryReaderEOFException(Exception):
def __init__(self):
pass
def __str__(self):
return 'Not enough bytes in file to satisfy read request'


class BR:
# Map well-known type names into struct format characters.
typeNames = {
'int8' :'b',
'uint8' :'B',
'int16' :'h',
'uint16' :'H',
'int32' :'i',
'uint32' :'I',
'int64' :'q',
'uint64' :'Q',
'float' :'f',
'double' :'d',
'char' :'s'}


def __init__(self, fileName):
self.file = open(fileName, 'rb')

def read(self, typeName):
typeFormat = BR.typeNames[typeName.lower()]
typeSize = struct.calcsize(typeFormat)
value = self.file.read(typeSize)
if typeSize != len(value):
raise BinaryReaderEOFException
return struct.unpack(typeFormat, value)[0]

def __del__(self):
self.file.close()


NAV_DIR = ["North", "East", "South", "West"]
LADDER_DIRS = ["Up", "Down"]


def read_nav_file(filename):
f = BR(filename)
magic = f.read('uint32')
version = f.read('uint32')
savebspsize = f.read('uint32')


placecount = f.read('uint16')
places = dict()
for placeindex in range(placecount):
placenamesize = f.read('uint16')
placenamechars = list()
for x in range(placenamesize):
placenamechars.append(f.read('char'))
placename = b''.join(placenamechars)
places[placeindex] = placename


areacount = f.read('uint32')
areas = dict()
for areaindex in range(areacount):
areas[areaindex] = dict()
areas[areaindex]["id"] = f.read('uint32')
areas[areaindex]["flags"] = f.read('uint16')


x1 = f.read('float')
y1 = f.read('float')
z1 = f.read('float')
x2 = f.read('float')
y2 = f.read('float')
z2 = f.read('float')
areas[areaindex]["box"] = ((x1, y1, z1), (x2, y2, z2))




NEcornerz = f.read('float')
SWcornerz = f.read('float')
areas[areaindex]["corner"] = dict()
areas[areaindex]["corner"]["NE"] = NEcornerz
areas[areaindex]["corner"]["SW"] = SWcornerz


areas[areaindex]["directions"] = dict()
for index, direction in enumerate(NAV_DIR):
connectioncount = f.read('uint32')
areas[areaindex]["directions"][direction] = {'connectioncount' : connectioncount}

areas[areaindex]["directions"][direction]["connections"] = dict()
for connectionindex in range(connectioncount):
connectingareaindex = f.read('uint32')
areas[areaindex]["directions"][direction]["connections"][connectionindex] = connectingareaindex

hidingspotcount = f.read("uint8")
areas[areaindex]["hidingspotcount"] = hidingspotcount
areas[areaindex]["hidingspots"] = dict()
for hidingspotindex in range(hidingspotcount):
hidingspotid = f.read('uint32')
areas[areaindex]["hidingspots"][hidingspotindex] = {"id" : hidingspotid}


x = f.read('float')
y = f.read('float')
z = f.read('float')
areas[areaindex]["hidingspots"][hidingspotindex]["point"] = (x, y, z)


hidingspotflags = f.read("uint8")
areas[areaindex]["hidingspots"][hidingspotindex]["flags"] = hidingspotflags


approachareacount = f.read("uint8")
areas[areaindex]["approachareacount"] = approachareacount
areas[areaindex]["approachareas"] = dict()
for approachareaindex in range(approachareacount):
approachHereID = f.read('uint32')
approachPrevID = f.read('uint32')
approachType = f.read("uint8")
approachNextID = f.read('uint32')
approachHow = f.read("uint8")
areas[areaindex]["approachareas"][approachareaindex] = {"id": approachHereID, "previd": approachPrevID, "type": approachType, "nextid": approachNextID, "how": approachHow}


encounterPathcount = f.read("uint32")
areas[areaindex]["encounterpathcount"] = encounterPathcount
areas[areaindex]["encounterpaths"] = dict()
for encounterPathindex in range(encounterPathcount):
encounterFromID = f.read('uint32')
encounterFromDirection = f.read("uint8")
encounterToID = f.read('uint32')
encounterToDirection = f.read("uint8")
areas[areaindex]["encounterpaths"][encounterPathindex] = {"fromid": encounterFromID, "toid": encounterToID, "fromdir": encounterFromDirection, "todir": encounterToDirection,}


encounterSpotcount = f.read("uint8")
areas[areaindex]["encounterpaths"][encounterPathindex]["encounterspotcount"] = encounterPathcount
areas[areaindex]["encounterpaths"][encounterPathindex]["encounterspots"] = dict()
for encounterSpotindex in range(encounterSpotcount):
encounterSpotOrderId = f.read('uint32')
encounterSpotT = f.read("uint8")
encounterSpotParametricDistance = encounterSpotT / 255.0


areas[areaindex]["encounterpaths"][encounterPathindex]["encounterspots"][encounterSpotindex] = {"orderid": encounterSpotOrderId, "T": encounterSpotT,"parametricdistance": encounterSpotParametricDistance}


placeID = f.read("uint16")
areas[areaindex]["placeid"] = placeID


for index, direction in enumerate(LADDER_DIRS):
ladderConnectionCount = f.read('uint32')
for ladderconnectionindex in range(ladderConnectionCount):
ladderConnectID = f.read('uint32')


earliestOccupyTimeFirstTeam = f.read('float')
earliestOccupyTimeSecondTeam = f.read('float')
areas[areaindex]["team1eop"] = earliestOccupyTimeFirstTeam
areas[areaindex]["team2eop"] = earliestOccupyTimeSecondTeam


laddercount = f.read('uint32')


return {"areas": areas,
"places": places,
"laddercount": laddercount,
"filename": filename,
"magic": magic,
"version": version,
"savebspsize": savebspsize,
"areacount": areacount,
"placecount": placecount
}


# And ladder stuff goes here


Thaaankksss!