Any way to export the "Cell Grid" column of "Use

Post » Wed Mar 11, 2015 11:59 am

I'm trying to compile a list of exactly where each kind of animal spawns, and with what frequency.

If I pick an actor in the CK (for example, "LvlAmbientCreatures" which draws from the "LCharAmbientCreatures" list) then I can select "Use Info" and get a list of all the instances of that actor in the Tamriel worldspace, including its Cell Grid coordinates. I can then look up which part of the map each of those Cell Grids is in to determine which Hold contains that spawn point.

But I want to do this for dozens of such leveled actors, each of which has hundreds of placements in the world. Surely there must be some way to automate this process, at least to get the list of Cell Grid data in text (CSV?) format for a single actor? Can TES5Edit do this somehow, if the CK can't?

User avatar
Klaire
 
Posts: 3405
Joined: Wed Sep 27, 2006 7:56 am

Post » Wed Mar 11, 2015 12:19 pm

You can get reference data with a TES5Edit script. You could probably be improve this one, but it gets the job done:

Spoiler
unit UserScript;const  targetFormID = $000EC968; //LvlAmbientCreatures (replace with the formID of whatever you're looking for)var  targetRecord: IInterface;  targetString: string;  output: TStringList;function Initialize : integer;begin  targetRecord := RecordByFormID(FileByIndex(0), targetFormID, True);  targetString := GetElementEditValues(targetRecord, 'Record Header\FormID');  output := TStringList.Create;  output.Add('Outputting cell references for ' + targetString);  output.Add('');end;function Process(e: IInterface): integer;var  s: string;  cell: IInterface;begin  Result := 0;    if (GetElementEditValues(e, 'NAME') <> targetString) then    Exit;  // skip records that are not references  s := Signature(e);  if (s <> 'ACHR') and (s <> 'REFR') then    Exit;    // go through plugin structure tree up to find group record (GRUP) of reference  cell := GetContainer(e);  while Assigned(cell) and (ElementType(cell) <> etGroupRecord) do    cell := GetContainer(cell);    if not Assigned(cell) then    Exit;  // get CELL record of GRUP record  cell := ChildrenOf(cell);    if not Assigned(cell) then    Exit;  //add cell data to output  output.Add(GetElementEditValues(cell, 'Record Header\FormID'));  end;function Finalize : integer;var filename : string;begin  filename := ScriptsPath + GetElementEditValues(targetRecord, 'EDID') + '_refdata.csv';  AddMessage('Saving output to ' + filename);  output.SaveToFile(filename);  output.Free;end;end.

  1. Load up the plugin you want to investigate in TES5Edit.
  2. Select the "Worldspace" record header. Then hold CTRL and click the "Cell" record header, so they're both selected.
  3. Right-click either and Apply Script.
  4. Paste the script above in the window, and save it for future uses.

It'll output a .csv into your TES5Edit\Edit Scripts directory.

User avatar
I’m my own
 
Posts: 3344
Joined: Tue Oct 10, 2006 2:55 am

Post » Wed Mar 11, 2015 12:52 am

You can just use

cell := LinksTo(ElementByName(e, 'Cell'))

to get the cell record of reference.

Also Name(targetRecord) instead of GetElementEditValues(targetRecord, 'Record Header\FormID')

User avatar
^~LIL B0NE5~^
 
Posts: 3449
Joined: Wed Oct 31, 2007 12:38 pm

Post » Wed Mar 11, 2015 6:43 am

Thanks, this seems to work!

Next, any suggestions about the best way to translate the resulting cell coordinates into Holds? Does the cell itself have a property that references a Location record that could be followed up the chain to something like WhiterunHoldLocation?

User avatar
jessica robson
 
Posts: 3436
Joined: Mon Oct 09, 2006 11:54 am

Post » Tue Mar 10, 2015 9:33 pm

I rigged up a spreadsheet to handle the mapping of cell coordinates to holds (so i.e. -18,-7 is about where Falkreath, the Reach and Whiterun all come together), but now I notice a new issue:

Some of the references found by this script are located in CELL 0xD74, which is the "persistent worldspace cell" that seems to cover the entire worldspace. Since that cell itself has no useful coordinates to determine which hold its references are in, is there some other way? Can I do some calculation on the reference's own coordinates within this particular cell to translate it back to the coordinate system used by all the other cells?

User avatar
Red Bevinz
 
Posts: 3318
Joined: Thu Sep 20, 2007 7:25 am

Post » Wed Mar 11, 2015 9:52 am

All persistent references in a worldspace are located in a single persistent cell since game loads all of them regardless the position of player, you can translate reference position back to grid value

{  Find the first persistent exterior reference and calculate it's cell grid coordinates}unit userscript;function Process(e: IInterface): integer;var  cell: IInterface;  c: TwbGridCell;begin  if Signature(e) <> 'REFR' then    Exit;    // parent CELL of reference  cell := LinksTo(ElementByName(e, 'Cell'));    // if parent CELL is persistent and exterior  if GetIsPersistent(cell) and (GetElementNativeValues(cell, 'DATA') and 1 = 0) then begin    c := wbPositionToGridCell(GetPosition(e));    AddMessage('Found exterior persistent reference: ' + Name(e));    AddMessage(Format('Cell grid coordinates: %d,%d', [c.X, c.Y]));    Result := 1;    Exit;  end;end;end.
User avatar
Chenae Butler
 
Posts: 3485
Joined: Sat Feb 17, 2007 3:54 pm

Post » Wed Mar 11, 2015 7:19 am

Ah, and it looks like wbPositionToGridCell() just literally divides by 4096 and rounds down -- easy enough.

Now one last pipe dream: has anyone ever come up with a good way to take arbitrary Tamriel worldspace coordinates and decide which Hold they're within? Some exterior cells have an XLCN which can be walked back up to an ancestor location with LocTypeHold, but many exterior cells have no XLCN defined.

Maybe another angle to come at this is crime reporting -- if the player commits a witnessed crime in an exterior cell with no XLCN, how does the game decide which Hold's jurisdiction covers that spot to add the bounty?

User avatar
stevie trent
 
Posts: 3460
Joined: Thu Oct 11, 2007 3:33 pm


Return to V - Skyrim