Room Mapping System
This system uses the navmesh to build a picture of what kind of shape an interior cell takes. This allows you to ask questions like:
- How many rooms in this cell?
- What room am I in?
- Who's in this room with me?
- What kind of things are in this room?
- What rooms are adjacent to this room?
- How many exits does this room have?
- Where are the exits from this room?
- Where are the exits from this cell?
- Roughly what size is a room? And by extension which room is the biggest/smallest?
- Roughly where is the center?
- How far is the actual path between two actors? (They may be physically close but there might also be a wall in the way).
Any actor or object ref can be tracked for room change events.
If Belethor room == 1 & Player room == 1 then Belethor and the player are in the same room.
If Player room changes to 2. Should Belethor follow the player?
I hope to eventually be able to give you an idea of the purpose of the room though this could never be absolutely definitive.
Here's a video of me plodding around a couple of cells. The player is tracked for room change events. Every time the player changes room we get an event to tell you which room I was in and which room I'm in now. AutoRoomMap is turned on so every time I change room the system maps out the current room with soul gems - It's a visual debugging functionality to make sure the map is right.
API surface thus far:
;======================================================================================== ; Room Detection (Experimental)(WIP) ==================================================== ;======================================================================================== ; Register a form for reference room change events. ; Registrations survive save + reload. ; Event On_MGF_ActorRoomChange(Actor akActor, Int OldRoom, Int NewRoom) ; akActor: The actor that changed room. ; OldRoom: The index of the room akActor came from. ; NewRoom: The index of the room akActor is now in. Function RoomTrackActor(Form akForm, ObjectReference ObjRef) Global Native ; Unregister this for reference for room change events. Function RoomUntrackActor(Form akForm, ObjectReference ObjRef) Global Native ; Untrack all references. Function RoomUntrackAll(Form akForm) Global Native ; Is this reference registered for room change events on this form. Bool Function RoomIsTrackedActor(Form akForm, ObjectReference akRef) Global Native ; Returns a list of all references registered for tracking on this form. ObjectReference[] Function RoomGetTrackedActors(Form akForm) Global Native ; Returns whether this form has been registered in the room system. ; Returns 0 = opening, 1 = stair, -1 = not registered. Int Function RoomIsRegisteredStatic(Form akForm) Global Native ; RoomRegisterStatic(Form akForm, int aiType, string asFile). ; When registering an opening, stand in the center of the opening and face the 'door jamb', so that you're facing parallel ; with the dividing wall and at 90 degrees from the angle of the opening. ; The more centered you are in both the x, y axis the better the results generally. ; Type: 0 = opening, 1 = stair ; FileName: filename only (no path separators). Eg: "mymod.json" Function RoomRegisterStatic(ObjectReference akRef, Int Type, String FileName) Global Native ; Attempts to add a boundary where akActor is standing. Returns true for success. ; Stand in the center of the opening and face parallel with the dividing wall. ; The system will try to find the closest, parallel edge to create a new boundary. ; Boundaries are saved to json <FileName> Bool Function RoomAddBoundary(String FileName) Global Native ; Attempts to remove a boundary within Radius of the player. Returns true for success. ; Removes all manual boundaries within <Radius> from all jsons. Bool Function RoomRemoveBoundary(Float Radius = 64.0) Global Native ; Returns how many manual boundaries in the current cell. Int Function RoomGetOverrideCount() Global Native Function RoomRegisterObjectsAs(Form[] akForms, int aiRole, string asModName) native global Function RoomUnregisterMod(string asModName) native global String[] Function RoomGetClassificationScores(int aiRoom) Global Native Function RoomUnregisterStatic(ObjectReference akRef) Global Native ; Remap the current cell again. Function RoomRemapCell() Global Native ; Force the system to ignore a particular door reference. ; Need to call RoomRemapCell() afterwards to update the room map. ; Added this after discovering a door buried in a wall in Dragonsreach messing up the room mapping... ; Unlike RoomIsIgnoredDoorEid() this affects a single reference. Function RoomIgnoreDoorRef(ObjectReference ObjRef) Global Native ; Opposite of RoomIgnoreDoorRef(). Function RoomUnignoreDoorRef(ObjectReference ObjRef) Global Native ; Returns true if this reference is in MGF's door reference ignore list. Bool Function RoomIsIgnoredDoorRef(ObjectReference ObjRef) Global Native ; Is defined (via json) as a 'weird door' the system should ignore. Eg: Display cases, shackles. ; This is essentially a string check of ObjRef's base EditorID against MGF's list of strings to ignore. Bool Function RoomIsIgnoredDoorEid(ObjectReference ObjRef) Global Native ; Returns boundary midpoints as flat [x,y,z, ...] float array. ; These are the positions of the entrances/exits to a room. ; RoomIndex: The index of the room to check. Float[] Function RoomGetBoundaryMidpoints(Int RoomIndex) Global Native ; Returns the navmesh triangle count of the room. ; RoomIndex: The index of the room to check. Int Function RoomGetTriangleCount(Int RoomIndex) Global Native Int Function RoomGetTriangleForRef(ObjectReference ObjRef) Global Native Int Function RoomGetTriangleFlags(ObjectReference ObjRef) Global Native ; Tries to return the center position of the navmesh for the room with the specified clearance around it. ; Useful for placing markers etc. Always check the returned array.Length > 0 to check for failure. ; Function will always try to return the best point even if the clearance isn't fully met or a clearance of 0.0 is requested. ; Note that this is the navmesh center and not the room center really. Float[] Function RoomGetCenter(Int RoomIndex, Float Clearance = 0.0) Global Native ; This would be a more 'exact' center of the room geometrically. Probably still not perfect because of the navmesh shape. ; Though it might be floating in air a bit or inside some object like a pillar or fireplace etc. ; Also check that length > 0 for failure. Float[] Function RoomGetCentroid(Int RoomIndex) Global Native ; Get the area covered by the navmesh associated with this room. ; Not the actual area of the room. But should be a decent indicator of room size. Float Function RoomGetArea(Int RoomIndex) Global Native ; Returns total number of rooms detected in player's current cell Int Function RoomGetCount() Global Native ; Returns the indices of all connecting rooms. ; RoomIndex: The index of the room to check. Int[] Function RoomGetAdjacentRooms(Int RoomIndex) Global Native ; Returns index of actor's room within the cell. Int Function RoomGetIndexForActor(Actor akActor) Global Native ; ; Returns index of reference's room within the cell. Int Function RoomGetIndexForRef(ObjectReference akRef) Global Native ; Gets the number of entrances/exits to a room. Includes load doors, interior doors, door arches (without doors) and stairs. ; RoomIndex: The index of the room to check. ; ExpandOverOpenBoundary: False - Don't go past any of the rooms boundaries. ; True - Expand over open boundaries like door arches and stairs. ; If RoomGetExitCount = 1 && RoomGetDoors == 1 then it's probably (but not certainly) a room with a single entrance with a door. ; If RoomGetExitCount = 1 && RoomGetDoors == 0 then it's probably (but not certainly) a room with a single 'open' entrance. Int Function RoomGetExitCount(Int RoomIndex, Bool ExpandOverOpenBoundary = False) Global Native ; Returns door references that are associated with a room. ; DoorTypes: 0 - any, 1 - non-load doors only, 2 - load doors only ; ExpandOverOpenBoundary: False - Don't go past any of the rooms boundaries. ; True - Expand over open boundaries like door arches and stairs. ObjectReference[] Function RoomGetDoors(Int RoomIndex, Int DoorTypes, Bool ExpandOverOpenBoundary = False) Global Native ; Returns all furniture references in a room. ; RoomIndex: The index of the room to check. ; ExpandOverOpenBoundary: False - Don't go past any of the rooms boundaries. ; True - Expand over open boundaries like door arches and stairs. ObjectReference[] Function RoomGetFurniture(Int RoomIndex, Bool ExpandOverOpenBoundary = False) Global Native ; Returns a list of object references with any of the listed keywords. ; RoomIndex: The index of the room to check. ; ExpandOverOpenBoundary: False - Don't go past any of the rooms boundaries. ; True - Expand over open boundaries like door arches and stairs. ObjectReference[] Function RoomGetRefsWithKeywords(Int RoomIndex, Keyword[] akKwds, Bool ExpandOverOpenBoundary = False) Global Native ; Same as RoomGetRefsWithKeywords but only returns a count. Int Function RoomCountRefsWithKeywords(Int RoomIndex, Keyword[] akKwds, Bool ExpandOverOpenBoundary = False) Global Native ; Returns references in <RoomIndex> of type <FormType>. ; FormType: https://ck.uesp.net/wiki/GetType_-_Form ; ExpandOverOpenBoundary: False - Don't go past any of the rooms boundaries. ; True - Expand over open boundaries like door arches and stairs. ObjectReference[] Function RoomGetRefsOfType(Int RoomIndex, Int FormType, Bool ExpandOverOpenBoundary = False) Global Native ; Returns all actors in a room. ; RoomIndex: The index of the room to check. ; ExpandOverOpenBoundary: False - Don't go past any of the rooms boundaries. ; True - Expand over open boundaries like door arches and stairs. Actor[] Function RoomGetActors(Int RoomIndex, Bool ExpandOverOpenBoundary = False) Global Native ; Approximate navmesh path distance in game units between the positions of the two references. ; Returns -1.0 if: either ref is null / outside the navmesh. ; they are in different cells. ; the room data isn't ready yet ; no path exists within the A* node budget (8192 triangles) ; GetDistance will always be <= than RoomGetPathDistance. What's the point of this function? ; RoomGetPathDistance(PlayerRef, ObjRef) / PlayerRef.GetDistance(ObjRef) > ~1.4 means that there is a significant difference between ; direct distance to the object and the pathing distance to the object. ; IE: Object could be through a wall or on another floor. ; Despite the name this works in exterior cells too though be aware that it has a distance limit due to the triangle budget above and ; the object must be in the same cell. ; Same navmesh island: A* on triangle adjacency graph. ; Different islands: Dijkstra on the room boundary graph, straight-line between boundary midpoints. ; Less precise but handles multi-level cells. Float Function RoomGetPathDistance(ObjectReference ObjRef1, ObjectReference ObjRef2) Global Native ; Returns a flat array of the navmesh vertices that constitute this room. ; Array elements are in triplets. [0] = x1, [1] = y1, [3] = z1, [4] = x2, [5] = y2, [6] = z2 etc Float[] Function RoomGetNavmeshVertices(Int RoomIndex) Global Native ; Places MarkerForms at every vertex that constitute the room. ; Easy visualization of the room limits. References are spawned with persist = false. ; But it's your responsibility to manage the returned object references (cleanup). ObjectReference[] Function RoomMap(Int RoomIndex, Form MarkerForm) Global Native
Edited by Monoman1
0 Comments
Recommended Comments
There are no comments to display.