unit treelodpatcheralt;

// This is copied and modified code from Skyrim - Tree LOD files patcher.pas



//============================================================================
function AddTreeFormID(Element: IInterface):boolean;
begin
  Result := False;
  if (Signature(Element) = 'REFR') and (Signature(LinksTo(ElementBySignature(Element, 'NAME'))) = 'TREE') then begin
    slREFRTREELOD.Add(GetLoadOrderFormID(Element));
    Result := True;
  end;
end;

//============================================================================
procedure ReadBTTFile(aFileName: string);
var
  fsRead: TFileStream;
  reader: TBinaryReader;
  NumTypes, NumTrees, TreeType: Integer;
  i, t, formid: integer;
  x, y, z, rot, scale: single;
  r, f: IInterface;
begin

  fsRead := TFileStream.Create(aFileName, fmOpenRead);

  try
    reader := TBinaryReader.Create(fsRead);
    NumTypes := reader.ReadInteger;
    for i := 1 to NumTypes do begin
      TreeType := reader.ReadInteger;
      NumTrees := reader.ReadInteger;
      for t := 1 to NumTrees do begin
        x := reader.ReadSingle;
        y := reader.ReadSingle;
        z := reader.ReadSingle;
        rot := reader.ReadSingle;
        scale := reader.ReadSingle;
        formid := reader.ReadInteger;
        f := GetFileByFormID(formid);
        r := RecordByFormID(f, LoadOrderFormIDtoFileFormID(f, formid), False);
        if not Assigned(r) then begin
          if slMissingTrees.IndexOf(formid) = -1 then begin
            // last ditch effort, typically the mod that creates the world also adds tree - non issue when LODGen for trees is used and load order matches
            r := RecordByFormID(GetFile(MasterOrSelf(LODGenWorld)), LoadOrderFormIDtoFileFormID(f, formid), False);
            if not Assigned(r) then
              MyMessage('  ' + IntToHex(formid, 8) + ' not found. Generate tree LOD for this load order.')
            else if not AddTreeFormID(r) then begin
              MyMessage('  ' + IntToHex(GetLoadOrderFormID(r), 8) + ' found, but not a TREE. FormID in file was ' + IntToHex(formid, 8) + '.  Generate tree LOD for this load order.');
              //slMissingTrees.Add(formid);
            end;
          end;
        end
        else begin
          if not AddTreeFormID(r) then begin
            // last ditch effort, typically the mod that creates the world also adds tree - non issue when LODGen for trees is used and load order matches
            r := RecordByFormID(GetFile(MasterOrSelf(LODGenWorld)), LoadOrderFormIDtoFileFormID(f, formid), False);
            if not AddTreeFormID(r) then begin
              MyMessage('  ' + IntToHex(GetLoadOrderFormID(r), 8) + ' found, but not a TREE. FormID in file was ' + IntToHex(formid, 8) + '.  Generate tree LOD for this load order.');
              //slMissingTrees.Add(formid);
            end;
          end;
        end;
        reader.ReadInteger; // unknown int
        reader.ReadInteger; // unknown int
      end;
    end;
  finally
    reader.Free;
    fsRead.Free;
  end;
end;

//============================================================================
procedure TreeWorldspace(aName: string);
var
  wspath, sFileName: string;
  F: TSearchRec;
  slv: TStringList;
  x, y: integer;
begin
  MyMessage('Scanning ' + sWorld + ' *.BTT files to build a list of trees with LOD');

  sFileName := Lowercase(wbGameName + '-' + sWorld + '_trees');

  slREFRTREELOD := LoadStringListCache(sFileName);

  if bUseTreeCache then
    if slREFRTREELOD.Count > 0 then begin
      MyMessage('  Loaded ' + IntToStr(slREFRTREELOD.Count) + ' trees with LOD from cache');
      exit;
    end

  slREFRTREELOD.Clear;

  slMissingTrees := TStringList.Create;
  slMissingTrees := LoadStringList('missing_trees');

  wspath := sDataPath + 'meshes\terrain\' + aName + '\Trees\';
  if FindFirst(wspath + '*.BTT', faAnyFile, F) = 0 then try
    slv := TStringList.Create;
    slv.Delimiter := '.';
    slv.StrictDelimiter := True;
    repeat
      slv.DelimitedText := F.Name;
      x := StrToIntDef(slv[2], 0);
      y := StrToIntDef(slv[3], 0);
      //MyMessage('Reading: ' + F.Name);
      ReadBTTFile(wspath + F.Name);
    until FindNext(F) <> 0;
  finally
    FindClose(F);
    slv.Free;
  end;

  MyMessage('  Found ' + IntToStr(slREFRTREELOD.Count) + ' trees with LOD');
  slREFRTREELOD.SaveToFile(CachePath + sFileName + '.txt');

  //slMissingTrees.SaveToFile(CachePath + 'missing.txt');
  slMissingTrees.Free;

end;

end.

