Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - epinter

Pages: [1] 2 3 4
1
I'm mostly interested in converting DDS to TEX in a bulk.
Spoiler for Video:
1. Download the latest TQRespec - https://github.com/epinter/tqrespec/tags (At this moment it is https://github.com/epinter/tqrespec/releases/tag/v1.1.0 (TQRespec-1.1.0.zip)).
2. Unzip archive.
Further as in the video:
3. Create .bat file (with any name) in folder where texconverter-cli.exe and paste:
Spoiler for _DDS TO TEX.bat:
@echo off
setlocal EnableDelayedExpansion

set "SkipIfAlreadyExist=0"
set "DeleteOriginalAfterConversion=1"

set "ShowSkipped=1"
set "ShowDeleted=1"

REM Check if texconverter-cli.exe is in the folder with the batch file
set "TexConverter=%~dp0%texconverter-cli.exe"
if not exist "%TexConverter%" (
   echo "%TexConverter% does not exist!"
   goto :EXIT
)

REM Check if the arguments have been passed
if "%~1"=="" (
    echo Error: No arguments passed!
    goto :EXIT
)

REM Processing each argument
for %%A in (%*) do (
   if exist "%%A" (
      REM If argument is folder
      if exist "%%A\*" (
         call :processFolder "%%A"
      ) else (
         REM If argument is file
         
         REM Check if .dds or .DDS extension
         set "isDDS_file=0"
         if "%%~xA" == ".dds" (
            set "isDDS_file=1"
         )
         if "%%~xA" == ".DDS" (
            set "isDDS_file=1"
         )
         
         if "!isDDS_file!" == "1" (
            REM If TEX file already exist
            if exist "%%~dpnA.tex" (
               if "%SkipIfAlreadyExist%"=="1" (
                  if "%ShowSkipped%"=="1" (
                     echo "%%A" skipped.
                  )
               ) else (
                  REM Delete TEX that already exist
                  del /F /Q "%%~dpnA.tex"
                  
                  if "%ShowDeleted%"=="1" (
                     echo "%%~dpnA.tex" DELETED.
                  )
                  
                  REM Convert
                  "%TexConverter%" -i "%%A" -o "%%~dpnA.tex"
                  
                  REM If the conversion was completed without errors,
                  REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
                  REM and original file deletion is enabled
                  if !ERRORLEVEL!==0 if exist "%%~dpnA.tex" if "%DeleteOriginalAfterConversion%"=="1" (
                     del /F /Q "%%A"
                     
                     if "%ShowDeleted%"=="1" (
                        echo "%%A" DELETED.
                     )
                  )
               )
            ) else (
               REM If TEX file not already exist, then just convert
               "%TexConverter%" -i "%%A" -o "%%~dpnA.tex"
               
               REM If the conversion was completed without errors,
               REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
               REM and original file deletion is enabled
               if !ERRORLEVEL!==0 if exist "%%~dpnA.tex" if "%DeleteOriginalAfterConversion%"=="1" (
                  del /F /Q "%%A"
                  
                  if "%ShowDeleted%"=="1" (
                     echo "%%A" DELETED.
                  )
               )
            )
         ) else (
            echo Error: %%A not have .dds extension!
         )
      )
   ) else (
      echo Error: %%A not exist!
   )
)

echo:
echo Done^!
goto :EXIT

:processFolder
REM For all DDS files in folder (with subfolders)
for /r "%1" %%F in (*.dds) do (
   REM If TEX file already exist
   if exist "%%~dpnF.tex" (
      if "%SkipIfAlreadyExist%"=="1" (
         if "%ShowSkipped%"=="1" (
            echo "%%F" skipped.
         )
      ) else (
         REM Delete TEX that already exist
         del /F /Q "%%~dpnF.tex"
         
         if "%ShowDeleted%"=="1" (
            echo "%%~dpnF.tex" DELETED.
         )
         
         REM Convert
         "%TexConverter%" -i "%%F" -o "%%~dpnF.tex"
         
         REM If the conversion was completed without errors,
         REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
         REM and original file deletion is enabled
         if !ERRORLEVEL!==0 if exist "%%~dpnF.tex" if "%DeleteOriginalAfterConversion%"=="1" (
            del /F /Q "%%F"
            
            if "%ShowDeleted%"=="1" (
               echo "%%F" DELETED.
            )
         )
      )
   ) else (
      REM If TEX file not already exist, then just convert
      "%TexConverter%" -i "%%F" -o "%%~dpnF.tex"
      
      REM If the conversion was completed without errors,
      REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
      REM and original file deletion is enabled
      if !ERRORLEVEL!==0 if exist "%%~dpnF.tex" if "%DeleteOriginalAfterConversion%"=="1" (
         del /F /Q "%%F"
         
         if "%ShowDeleted%"=="1" (
            echo "%%F" DELETED.
         )
      )
   )
)
exit /b

:EXIT
endlocal
pause
4. Create .bat file (with any name) in folder where texconverter-cli.exe and paste:
Spoiler for _TEX TO DDS.bat:
@echo off
setlocal EnableDelayedExpansion

set "SkipIfAlreadyExist=0"
set "DeleteOriginalAfterConversion=1"

set "ShowSkipped=1"
set "ShowDeleted=1"

REM Check if texconverter-cli.exe is in the folder with the batch file
set "TexConverter=%~dp0%texconverter-cli.exe"
if not exist "%TexConverter%" (
   echo "%TexConverter% does not exist!"
   goto :EXIT
)

REM Check if the arguments have been passed
if "%~1"=="" (
    echo Error: No arguments passed!
    goto :EXIT
)

REM Processing each argument
for %%A in (%*) do (
   if exist "%%A" (
      REM If argument is folder
      if exist "%%A\*" (
         call :processFolder "%%A"
      ) else (
         REM If argument is file
         
         REM Check if .tex or .TEX extension
         set "isTEX_file=0"
         if "%%~xA" == ".tex" (
            set "isTEX_file=1"
         )
         if "%%~xA" == ".TEX" (
            set "isTEX_file=1"
         )
         
         if "!isTEX_file!" == "1" (
            REM If DDS file already exist
            if exist "%%~dpnA.dds" (
               if "%SkipIfAlreadyExist%"=="1" (
                  if "%ShowSkipped%"=="1" (
                     echo "%%A" skipped.
                  )
               ) else (
                  REM Delete DDS that already exist
                  del /F /Q "%%~dpnA.dds"
                  
                  if "%ShowDeleted%"=="1" (
                     echo "%%~dpnA.dds" DELETED.
                  )
                  
                  REM Convert
                  "%TexConverter%" -i "%%A" -o "%%~dpnA.dds"
                  
                  REM If the conversion was completed without errors,
                  REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
                  REM and original file deletion is enabled
                  if !ERRORLEVEL!==0 if exist "%%~dpnA.dds" if "%DeleteOriginalAfterConversion%"=="1" (
                     del /F /Q "%%A"
                     
                     if "%ShowDeleted%"=="1" (
                        echo "%%A" DELETED.
                     )
                  )
               )
            ) else (
               REM If DDS file not already exist, then just convert
               "%TexConverter%" -i "%%A" -o "%%~dpnA.dds"
               
               REM If the conversion was completed without errors,
               REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
               REM and original file deletion is enabled
               if !ERRORLEVEL!==0 if exist "%%~dpnA.dds" if "%DeleteOriginalAfterConversion%"=="1" (
                  del /F /Q "%%A"
                  
                  if "%ShowDeleted%"=="1" (
                     echo "%%A" DELETED.
                  )
               )
            )
         ) else (
            echo Error: %%A not have .tex extension!
         )
      )
   ) else (
      echo Error: %%A not exist!
   )
)

echo:
echo Done^!
goto :EXIT

:processFolder
REM For all TEX files in folder (with subfolders)
for /r "%1" %%F in (*.tex) do (
   REM If DDS file already exist
   if exist "%%~dpnF.dds" (
      if "%SkipIfAlreadyExist%"=="1" (
         if "%ShowSkipped%"=="1" (
            echo "%%F" skipped.
         )
      ) else (
         REM Delete DDS that already exist
         del /F /Q "%%~dpnF.dds"
         
         if "%ShowDeleted%"=="1" (
            echo "%%~dpnF.dds" DELETED.
         )
         
         REM Convert
         "%TexConverter%" -i "%%F" -o "%%~dpnF.dds"
         
         REM If the conversion was completed without errors,
         REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
         REM and original file deletion is enabled
         if !ERRORLEVEL!==0 if exist "%%~dpnF.dds" if "%DeleteOriginalAfterConversion%"=="1" (
            del /F /Q "%%F"
            
            if "%ShowDeleted%"=="1" (
               echo "%%F" DELETED.
            )
         )
      )
   ) else (
      REM If DDS file not already exist, then just convert
      "%TexConverter%" -i "%%F" -o "%%~dpnF.dds"
      
      REM If the conversion was completed without errors,
      REM and converted file exist (its possible, that texconverter-cli.exe will complete without errors but will not create a converted file),
      REM and original file deletion is enabled
      if !ERRORLEVEL!==0 if exist "%%~dpnF.dds" if "%DeleteOriginalAfterConversion%"=="1" (
         del /F /Q "%%F"
         
         if "%ShowDeleted%"=="1" (
            echo "%%F" DELETED.
         )
      )
   )
)
exit /b

:EXIT
endlocal
pause
Now you can convert DDS to TEX and TEX to DDS by drag&dropping the required files and/or folders onto the corresponding .bat file.
At the beginning of each .bat file there is:
Spoiler for Settings:
set "SkipIfAlreadyExist=0"
set "DeleteOriginalAfterConversion=1"

set "ShowSkipped=1"
set "ShowDeleted=1"
And you can change the "settings" at your discretion (changing from 0 to 1 or from 1 to 0).
Spoiler for Settings description:
SkipIfAlreadyExist:
Set to 1: If during conversion (e.g. DDS to TEX) it is found that there is already a corresponding TEX file for such DDS, then simply ignore (skip) such file.
Set to 0: If during conversion (e.g. DDS to TEX) it is found that there is already a corresponding TEX file for such DDS, the TEX file will be first deleted and then converted again.

DeleteOriginalAfterConversion:
Set to 1: When the conversion is successful (only successful) (e.g. DDS to TEX) the original file is deleted (i.e. the DDS file will be deleted and only the converted TEX file will remain).
Set to 0: Never delete the original file after conversion.

ShowSkipped:
Set to 1: Messages will be shown about which files were skipped.
Set to 0: No messages will be shown about which files were skipped.

ShowDeleted:
Set to 1: Messages will be shown about which files were deleted.
Set to 0: No messages will be shown about which files were deleted.
Notes:
1. You can drag&drop several folders/files onto a .bat file at the same time. And also both files and folders at the same time.
2. If you want to convert a folder, then files from other subfolders of this folder will always be converted.
3. Works correctly only if the file extension is .dds/.tex or .DDS/.TEX (i.e. if the extension is .Tex or .dDs, it will not work).
4. You can create a shortcut for the .bat file(s) and place them anywhere. Drag&drop on such a shortcut will also work.

Thanks @HekTo, a nice drag and drop way to convert. :)

2
Thank you for including mod support, also for the portal unlock feature.
Btw, how to use the tex converter tool? Do I need a command prompt to do it? I'm mostly interested in converting DDS to TEX in a bulk.

It is a command line tool, you can use command prompt or powershell to run. The tex converter is simple to use, just run:
texconverter-cli.exe -i x:/tmp/TIGERMAN01.TEX -o x:/tmp/tigerman.dds"

I didn't create a feature to convert a directory with textures. I will try to do something, but for now, you can use a powershell script, like this:
Code: [Select]
Get-ChildItem -Path "x:/tmp/extracted/Resources" -Recurse -Include '*dds' | ForEach-Object {
    $outFile = $_.FullName -replace '\.dds','.tex'
    & "x:/tmp/TQRespec/texconverter-cli.exe" -i $_.FullName -o $outFile
}

You can put this inside a file with extension ".ps1", this code will enter every subdirectory inside "x:/tmp/extracted/Resources" and run convert every .dds found to .tex. If you never use powershell to run scripts, maybe you will need to enable scripts execution.

Thanks for your work, I played LoC 2024 a bit, it's a huge work.  :)

3
Oh, so it could be used with mods like Xmax?  What about Legion of Champions and Soulvizier?  Does it work with those type of mods too?

Yes, it should work with any mod. The game database.arz is always loaded while software is running. When you select a mod, the ARZ from the mod is loaded over the one from the game, so the values considered are from the mod. When any mod selection is done, the current mod is unloaded and the values considered are from the game (or the mod if one is selected), the log contains messages with the modifiers loaded from database. Currently, the values used are the skill points modifier, attributes modifier, attributes increment and the skills. If you have a mod that changes the points per level, the  value from the mod will be used. While developing I used LoC 2024, the skills are listed properly.

4
Nice epinter.  Thanks for all your work on this and your other projects.  Much appreciated.   :)

Thank you  :D
I always learn something when I contribute to the community with this kind of development.

Btw, I released another version, now with mod support.

5
Recent updates added features with more options to edit the characters (edit gold, add attributes/skill points, add portals, etc). Now Linux is fully supported. The version 1.0.3 added a feature to extract all game files, a map decompiler, and a TEX converter. For now, the extract and converter are command line tools, a readme can be found at https://github.com/epinter/tqrespec/blob/master/src/main/java/dev/pinter/tqextract/README.md

6
Downloaded and opened the respec tool. But for some reason i can't chose the charecter that i want to edit?
It only shows 3 out of 5 charecters in the select menu, but when i click the "watch chraecters" button, i can see the one i wanna edit, but i can't make the respec tool to open it.
I can only archive and explore the charecter, but not open it to edit.

Any advice?

See if the characters appears in the list as "Mod". Mod characters editing are not supported.

At some point, THQ Nordic told they would support multiple simultaneous mod in Titan Quest, since then I kept waiting the feature to appear in the game to start development in TQRespec, and they never released the feature. I will take look at this when I have free time, but no promises.

7
Your changes in the text should work. The .arc is being created in a way that is not parsed correctly by TQRespec. The message "StorageType not implemented: 0" from the stacktrace above means a field in the .ARC that should be 1(uncompressed) or 3(compressed), is set as 0. How did you create this .arc ? If you tell me the tool and options used, maybe I can reproduce and fix this issue.

I placed the modified "skills.txt in the TQ AE folder and then used the "ArchiveTool.exe" that comes with the game.
The command was:
Code: [Select]
ArchiveTool.exe Text\Text_EN.arc -update skills.txt .\ 9

I published a new version(0.11.3) with the problem fixed.

8
I just started playing TQ AE again (2.10.5) and ran into a strange problem with TQRespec (0.11.2), which I haven't noticed previously in an older version of the tool. When I start TQRespec it throws an error message:
Spoiler for Hiden:
Code: [Select]
br.com.pinter.tqrespec.core.UnhandledRuntimeException: Error loading text resource
at br.com.pinter.tqrespec/br.com.pinter.tqrespec.tqdata.Txt.preload(Txt.java:70)
at br.com.pinter.tqrespec/br.com.pinter.tqrespec.Main$2.call(Main.java:180)
at br.com.pinter.tqrespec/br.com.pinter.tqrespec.Main$2.call(Main.java:170)
at javafx.graphics/javafx.concurrent.Task$TaskCallable.call(Task.java:1426)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.io.IOException: StorageType not implemented: 0
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.models.StorageType.lambda$valueOf$1(StorageType.java:38)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.models.StorageType.valueOf(StorageType.java:38)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.data.ArcFile.<init>(ArcFile.java:123)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.data.ResourceReader.<init>(ResourceReader.java:38)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.data.ResourceReader$Builder.build(ResourceReader.java:99)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.Text.loadText(Text.java:129)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.Text.loadTextFromAllPaths(Text.java:112)
at br.com.pinter.tqdatabase/br.com.pinter.tqdatabase.Text.preload(Text.java:83)
at br.com.pinter.tqrespec/br.com.pinter.tqrespec.tqdata.Txt.preload(Txt.java:68)
... 5 more

The reason for this message is the "Text\Text_EN.arc" file, which I have modified to add text for a new skill. What I did is add these lines to "skills.txt":
Code: [Select]
x3tagSkillStormBlizzard=Blizzard
x3tagSkillStormBlizzardDesc=Cast a whirlwind of icy air that slows and freezes your enemies.

Is it a known issue that modifications to the English text file break TQRespec?

Hi !

Your changes in the text should work. The .arc is being created in a way that is not parsed correctly by TQRespec. The message "StorageType not implemented: 0" from the stacktrace above means a field in the .ARC that should be 1(uncompressed) or 3(compressed), is set as 0. How did you create this .arc ? If you tell me the tool and options used, maybe I can reproduce and fix this issue.

9
Maps and the Editor / Re: Mapdecompiler updated (Eternal Embers)
« on: 13 December 2021, 17:03:56 »
@epinter
A little offtopic - is it possible for the old TQCam Tool to be updated for EE? It was a total blast to play with, but it got broken after Atlantis. Koderkrazy's cheat engine table can still edit the camera angle, but it isn't interactive as the old tool:
Spoiler for Hiden:

I think it is possible if there's a source code, and the time available.  :)

To rewrite a tool like TQCam from scratch is hard, and in my opinion it's a tool that makes the game ugly, you see everything you shouldn't. The game itself have a much better camera than TQIT, THQ Nordic have done an amazing job.

10
Maps and the Editor / Re: Mapdecompiler updated (Eternal Embers)
« on: 13 December 2021, 16:58:03 »
Hello, I have a problem with unpacking the map. When I decompiled the map, the information about the zones that the player cannot enter (the "Passable" brush on the level editor panel) is not imported.
Screen #1
P.S. I applied this zone myself, it was not in the decompiled map

For example, in the original, it is not possible to go into the river. After decompiled a level with river, do a Rebuld patch and compile the map, I can freely move into these zones.
Screen: #2, #3

Can you say something about this situation?

P.S.2. Sory for my bad English.

Hi,

I didn't have access to mapdecompiler source code until few days ago, so I can't guarantee there's nothing to be done about this. But for what I have seen in it, there's nothing specific about this kind of zones. Maybe could be something that changed in the Editor, I don't know.

11
Maps and the Editor / Re: Mapdecompiler updated (Eternal Embers)
« on: 05 December 2021, 16:42:44 »
Hey o/

It's me

Last release 10hours ago
Last edit 8 hours ago

You did not update the release, it seems.

Also, I checked the source and there are issues and lots of warnings using MSVS2019 because you're playing with the memory manually without checks and safety, although it's fine this is hard to read and can be source of issues.
It's working fine though so let's hope it stays like this.

What changed btw ? From Ragnarok to Eternal Embers ? I'm curious.

Wagi

The release is updated, I just committed after I built the exe.

Actually I changed just a few lines of code. I saw there's a lot of warnings, but to solve everything would require a time I don't have.

Looks like on every release of the game, somebody got this source and increased the "char fileNames[1024][256]" to 2048 or only a little above. But on every release of dlc, there are always a lot of new files, then the change is needed again... The stack limits the array size, so I used malloc to increase the array to 65535.

Code: [Select]
diff --git a/MAPDecomp.cpp b/MAPDecomp.cpp
index e1ee25d..cd2097d 100644
--- a/MAPDecomp.cpp
+++ b/MAPDecomp.cpp
@@ -10,6 +10,8 @@
 #define SHR_SIZE 2 /*sizeof(unsigned short)*/
 #define FLT_SIZE 4 /*sizeof(float)*/
 #define PTR_SIZE sizeof(void*)
+#define FILENAMES_BUFFER_SIZE 65535
+#define FILENAME_SIZE 256
 
 void mkdirtofile(char* path) {
  size_t length = strlen(path);
@@ -67,7 +69,13 @@ void main(int argc, char **argv) {
  fwrite(sec, INT_SIZE, 1, wrlFile);
 
  bool outOfOrder = true;
- char fileNames[1024][256];
+
+ char ** fileNames = (char **) malloc(FILENAMES_BUFFER_SIZE * sizeof(char*));
+
+ for (int i = 0; i < FILENAMES_BUFFER_SIZE; i++) {
+ fileNames[i] = (char *) malloc(FILENAME_SIZE);
+ }
+
  eofdetect = fgetc(mapFile);
  unsigned char* buffer;
  while (!feof(mapFile) && !ferror(mapFile)) {
@@ -318,12 +326,12 @@ void main(int argc, char **argv) {
  }
  //.sd
  else if (0x18 == sec[0]) {
- sprintf_s(fileNames[1023], 255, "%s", argv[2]);
- *(fileNames[1023]+strlen(fileNames[1023])-3) = 's';
- *(fileNames[1023]+strlen(fileNames[1023])-2) = 'd';
- *(fileNames[1023]+strlen(fileNames[1023])-1) = 0;
+ sprintf_s(fileNames[FILENAMES_BUFFER_SIZE-1], 255, "%s", argv[2]);
+ *(fileNames[FILENAMES_BUFFER_SIZE-1]+strlen(fileNames[FILENAMES_BUFFER_SIZE-1])-3) = 's';
+ *(fileNames[FILENAMES_BUFFER_SIZE-1]+strlen(fileNames[FILENAMES_BUFFER_SIZE-1])-2) = 'd';
+ *(fileNames[FILENAMES_BUFFER_SIZE-1]+strlen(fileNames[FILENAMES_BUFFER_SIZE-1])-1) = 0;
 
- writeBuffer(buffer, CHR_SIZE, sec[1], fileNames[1023], "wb");
+ writeBuffer(buffer, CHR_SIZE, sec[1], fileNames[FILENAMES_BUFFER_SIZE-1], "wb");
  }
 
  //Data chunks. Output by other sections.
@@ -341,6 +349,12 @@ void main(int argc, char **argv) {
  eofdetect = fgetc(mapFile);
  }
 
+
+ for (int i = 0; i < FILENAMES_BUFFER_SIZE; i++) {
+ free(fileNames[i]);
+ }
+
+
  //close the world. open the nExt.
  fflush(wrlFile);
  fclose(wrlFile);

EDIT: I will take a look at those code issues when I have some time, at least those that are more critical

12
Maps and the Editor / Re: Mapdecompiler updated (Eternal Embers)
« on: 05 December 2021, 16:13:45 »
It's not me epinter, but one of my fellow mods.  He's getting it with Windows Defender.  Fine for him with virustotal.

Before I published the last version I uploaded some .7z with false positives. Maybe he downloaded the file as soon as I posted here ?

13
Maps and the Editor / Re: Mapdecompiler updated (Eternal Embers)
« on: 05 December 2021, 15:49:15 »
Maybe, but he's literally just tried and seen it so the latest fixes haven't worked for false positives.

I had problem with false positives in Windows Defender, but last commit fixed for me. Using virustotal.com before, I consistently saw Defender and MaxSecure detecting as trojan. After the fix, everything is green on virustotal:

https://www.virustotal.com/gui/file/5296e70c5a1d2549537b648b729ad9ee15d90bba6c40b65f4bca056f317d647a

What antivirus do you have?

14
Maps and the Editor / Re: Mapdecompiler updated (Eternal Embers)
« on: 05 December 2021, 09:00:37 »
Download the mapdecompiler.7z from releases page: https://github.com/epinter/tq-mapdecompiler/releases

15
Maps and the Editor / Re: Using the game's existing map in your mod
« on: 05 December 2021, 07:48:58 »
A build of the mapdecompiler working with Eternal Embers: https://titanquestfans.net/index.php?topic=1571

Pages: [1] 2 3 4

SimplePortal 2.3.7 © 2008-2026, SimplePortal