AGS 3.6.1

Started by Crimson Wizard, Mon 01/04/2024 20:10:49

Previous topic - Next topic

Crimson Wizard

AGS 3.6.1
Full release number:

For Editor

For Android
NOTE: the Editor now includes Android build component letting you prepare your own games for Android

For Engine/Editor developers

Released: 1st April 2024

Previous stable version: AGS 3.6.0 P11 forum thread

This release is brought to you by:

- Alan v.Drake (fixes, improvements)
- Crimson Wizard
- edmundito (iOS fixes)
- eri0o
- Walter Agazzi (fixes)


3.6.1 update focuses mainly on improving performance and usability of existing features, in both Editor and Engine.

The noteable addition to the Editor is a "Log Panel", which lets you read game logs right in the editor's window. "Goto definition" now works on game object script names and opens their respective panels. Room editor features better panning and zoom controls. Views allow to select and modify multiple frames at once.

In the engine, there's a significant improvement to script performance, which may make script-heavy games run 30-40% faster compared to AGS 3.6.0 (these were real test results on a certain game with 3D simulation). There's a big improvement to the speed of manipulating Overlays, and general speed improvement of graphics rendering primarily useful for high resolution games.

There are other fixes and improvements to various parts of the program too.
Please be sure to read "Upgrading to AGS 3.6.1" topic in the manual:

The full changelog follows.

What is new in 3.6.1

Common features:
 - Implemented Deflate compression option for sprites.
 - Removed length limits for: Game name, savegame folder, Character's script name and regular name (description), Inventory item's name (description), Mouse cursor's script name, Audioclip's script name.

 - Discontinued Source control integration functionality, removed "Put sound and sprite files in source control" option from General Settings.
 - In General Settings moved few properties to different groups for better consistency.
 - Added "Scale Character sprite offsets" property to General Settings. This property refers to scaling of Character.z and sprite offsets added by LockViewOffset script command.
 - Added TextureCacheSize and SoundCacheSize properties to Default Setup. These let configure the sizes of runtime texture and sound cache sizes respectively.
 - Added "Leave room after fade-out" event to Rooms (called "Unload" by default).
 - Added Translated property to all GUI Controls (was available only in ListBox). Translated property tells whether this control's text has to be translated, and applied text direction (in right-to-left text mode).
 - Support '\n' linebreak character in the Label's Text and potentially other text properties.
 - Improved Room Editor controls:
   Added free panning mode done by holding the middle mouse button, or alternatively - by holding Space + LMB.
   Mouse Wheel without key modifiers scrolls the room vertically; Shift + Mouse Wheel scrolls the room horizontally.
   Zoom is done by Ctrl + Mouse Wheel and room now zooms towards or outwards the cursor position.
 - In Room Editor the context menu is now displayed by RMB or Shift + RMB while editing masks.
   The individual room mode menu is merged with the "copy coordinates" command when shown.
 - In Room Editor the hint with coordinates is now also displayed when moving Objects or Characters with keyboard.
 - In Dialog Script editor support most Edit menu and context menu commands from the regular Script editor, with a few exceptions.
 - In Sprite Manager added command "View" -> "Show filenames" which toggles display of a sprite's source filename under the sprites.
 - Adjust sprites' import settings after "Crop sprite edges" command; this would ensure that these sprites are restored from source file keeping their cropped sizes.
 - During sprite export Editor will display a proper progress dialog.
 - Zoom controls in Character and View panes now allow downscaling too. View editor displays the preview sprite stretched to fill the parent panel.
 - View editor now allows to select multiple frames at once, across multiple loops too, using standard Shift + LMB and Ctrl + LMB combinations. Properties panel lets modify properties for all the selected frames at once.
 - Added "Replace with all sprites from folder" command to the View editor's context menu.
 - For Audio Clips in the project tree added "Force Reimport", "Force reimport all file(s)" and "Replace Source File" context menu commands.
 - For Output Panel added "Copy selection" context menu command.
 - Implemented Log Panel that lets you see the engine and game logs right in the Editor.
 - Improved LipSync panel looks in case user's system has display scaling option enabled.
 - "Goto Definition" command in script will now work for most of the game entities too, such as Characters, GUIs, and so forth. In that case it will find a game's entity and open a respective editor panel for it. This still does not work for some types, such as Room objects, and Views.
 - Added main menu commands for opening a Project folder and Compiled folder.
 - Added "Export Global Messages to script" menu command. This command is meant for upgraded pre-3.2 game projects, and will generate a script with a String array, moving global messages texts there.
 - For script's tabs added a context menu command for opening this script's location.
 - When run with "/compile" argument Editor will print all messages to the console (stdout), instead of displaying modal message windows.
 - For Android build target Editor now supports a directory to place plugins in.
 - When building a game for Android and Linux the Editor will now be more tolerant to missing plugins and only issue a warning instead of stopping with error.
 - Config will now be saved in UTF-8, letting to support setup program's title text in unicode.
 - For non-Windows build targets Editor will fix config containing Direct3D graphics driver option and set OpenGL instead.
 - For Color Themes: implemented character literal, braces match and braces error settings.
 - Made Editor be somewhat more tolerate to missing XML nodes in Game.agf, in many cases it will still let open a game.
 - When upgrading older game projects, Editor will insert a call to SetRestartPoint() in the end of the 'game_start' function in GlobalScript.asc. This is done to complement removal of an automatic restart point in the engine. This inserted command is safe to remove.
 - When upgrading pre-3.2 rooms with disabled SaveLoadEnabled property the Editor will reset this property and insert a comment with a warning into the corresponding room's script. This is done because this property is deprecated as is no longer accessible.
 - Fixed Editor refusing to open a game if one of the translation files is missing.
 - Fixed General Settings and Default Setup not working correctly right after importing a pre-3.* game project.
 - Fixed importing GIFs or 8-bit PNGs may lose transparent pixels if source images used other palette index than 0 for transparency.
 - Fixed Project Explorer's folders collapsing after certain user actions, such as dragging items or renaming things.
 - Fixed deleting collapsed "region" in script would sometimes lead to portion of the script undeleted but staying invisible.
 - (Possibly) Fixed a "Index out of range" exception in Script editor, related to the "script location" drop-down list, which could occur at random circumstances while
   working with the script, and any Color Theme is enabled.
 - Fixed Editor could miss some of the files when cleaning up old compiled files after the Game's Filename property is changed.

 - Support "#else" preprocessor directive.

Script API:
 - Implemented Room's "After fade-out" event.
 - Added eEventLeaveRoomAfterFadeout event for the global "on_event".
 - Added eEventGameSaved event which runs after game was saved.
 - Expanded interaction functions for Character, Object, InventoryItem, Hotspot and Region types: now they all receive respective object's pointer as a parameter, similar to GUI event functions, as well as a cursor mode this interaction was run with, if applicable.
 - Added Game.ResetDoOnceOnly(), which completely resets all DoOnceOnly instances.
 - Added Game.PrecacheSprite() and Game.PrecacheView(), which preload certain sprites and linked frame sounds into the engine's sprite cache memory.
 - Added ScriptName property to AudioClip, Character, Dialog, GUI, GUIObject, Hotspot, InventoryItem, Object.
 - Added static GetByName() function to AudioClip, Character, Dialog, GUI, GUIObject, Hotspot, InventoryItem, Object.
 - Added Object.AnimationVolume property, which works similar to Character.AnimationVolume.
 - Added static File.ResolvePath() and File.Path attribute.
 - Added support for a text formatting to a number of functions: DisplayAtY(), Character.SayAt(), Character.SayBackground(), DrawingSurface.DrawStringWrapped().

 - Updated to SDL 2.28.5 and SDL_Sound 2.0.3+.
 - Significant performance improvement to scripts. Script running speed restored to a level close to AGS 3.2.1. Testing few "script-heavy" games showed fps raise by up to 30-40% compared with 3.6.0 engine.
 - Improved performance of String objects in script.
   For instance, appending a character to a String is now roughly x2 times faster, *sequential* iteration of String.Chars[] in Unicode mode is about x12 (!) times faster (Strings in ASCII mode have relatively less improvement, because they have been faster than Unicode mode already).
 - Improved performance when creating, deleting and manipulating Overlays; allows the game to have thousands of those with much less slowing down.
 - Improved performance when updating and deleting dynamic sprites, and notifying any objects that have to redraw themselves. Engine no longer resets Graphic properties of objects referencing deleted dynamic sprite to 0.
 - Implemented "texture cache", in addition to the existing "sprite cache". The texture cache keeps textures generated from raw sprites and lets reusing them, improving performance and reducing CPU workload. The actual impact is proportional to the game's resolution and amount of simultaneously animated objects on screen.
 - WFN font renderer now too supports unicode mode and renders texts in utf-8, so long as the font contains glyphs of corresponding indexes.
 - Buttons, ListBoxes and TextBoxes now support Right-to-left text direction.
 - DrawingSurface.DrawString now supports Right-to-left text direction.
 - All the script File functions now treat paths in case-insensitive way (including subdirs), which makes them platform-independent.
 - Removed an automatic SetRestartPoint() call at startup. This is done in case user does not want to use default "restart" save slot, or has a custom save system.
 - Support handling multiple mouse clicks per game frame, similar to how multiple key presses were supported since 3.6.0.
 - When starting up, engine will now precache only first 4 or 8 loops of the starting player character's View. This is done to avoid filling sprite cache with too much sprites at once in case when the player's View contains lots of additional animations.
 - Characters will now have their graphic offsets, set by Character.z property and LockViewOffset() function, scaled along with the character's own scaling. This is done so long as the respective game option is enabled in the General Settings.
 - Ensure that character and object scaling is updated even when the game is not drawn. This fixes rare issues when their scale property did not update in time whilst the game was completely fadeout, and similar cases.
 - Allow to change Character's move speed while its moving.
 - When Character is ordered a new move command while already moving, the engine will try to make a smooth transition between old and new moving without a delay.
 - Ensure that when Overlays have identical ZOrder they will be sorted in the order of their creation. Besides convenience, this is also meant to restore historical behavior from before Overlay.ZOrder property was introduced.
 - Allow game to call DynamicSprite.CreateFromDrawingSurface() and CreateFromBackground() with zero or negative size, clamping it to 1x1, in consistency with Create().
 - Engine will now log a warning for the most incorrect parameters to Animate function instead of quitting the game.
 - Engine will now skip blocking Character.Say commands instantly while skipping a cutscene.
 - Object.SetView now lets invalid loop and frame values, and fallbacks to using loop 0, frame 0, printing a warning. This is also consistent with backwards-compatble SetObjectFrame() behavior.
 - Changed Object.SetView() to not play a frame's sound, which could lead to a duplicated sound play if Object.Animate is run right after.
 - Text Overlays internal images are now registered as dynamic sprites, and their IDs may be read from Overlay.Graphic. This lets find out their sizes using Game.SpriteWidth/SpriteHeight and optionally draw them somewhere using DrawingSurface.DrawImage.
 - Ensure all the script API is now correctly available for the plugins.
 - Engine will now safeguard plugin's reading and writing of game saves, so that any mistakes done by plugins won't affect other parts of a save.
 - Engine will disable vsync in a "infinite fps" mode, because vsync prevents getting more fps.
 - Engine will force any in-game debug messages to be displayed in message boxes, disregarding game's "Display all messages as speech" option.
 - Display critical alerts as system modal messages on all platforms that support that (unless engine is run with "--no-message-box" parameter).
 - Print some info about memory usage when reporting a "Out of memory" error.
 - Deprecated in-game "console", as practically useless.
 - Added new config settings in "graphics" section: "sprite_cache_size" (which replaces deprecated "cachemax" in "misc") and "texture_cache_size".
 - Fixed Characters may be seemingly "walking in place" for some time when arriving at destination.
 - Fixed Display and Say commands treating the second met "&" sign as a voice-over token too (they must only check the first one in string).
 - Fixed PlayMP3File() function limiting filename argument by an arbitrary number of characters.
 - Fixed speechlines were adjusting their Y position while trying to not overlap GUIs even when these GUIs are completely offscreen.
 - Fixed first Sierra-style speechline in a sequence was adjusting its Y position without need when GUIs are set to be hidden during game pause (this includes blocking speech). Normally, the speechlines are adjusting their Y position in order to not overlap GUIs, but when GUIs are hiding during speech there should not be any need to do so.
 - Fixed script behavior in case a local variable was assigned a value without being initialized with a zero memory by compiler's intruction beforehand. This is not a problem with the standard compiler, but technically could be an issue with any custom implementation.
 - Fixed old-style letterbox viewport getting broken after loading an old pre-3.5.0 save.

Engine Plugin API:
 - Added IAGSStream interface, IAGSEngine.OpenFileStream() and GetFileStreamByHandle().
 - Added IAGSEngine.ResolveFilePath() method, which resolves a script path (with location tokens) into a proper system filepath.
 - Fixed IAGSEngine.GetFontType() incorrectly reporting TTF font type for WFN fonts with more than 128 characters.

 - In Editor, restored all the Character's variables available in "backward-compatible" mode. This is primarily to make it easier to import very old games.
 - Allow to run an animation over a loop with zero frames, by using the placeholder frame. This lets particular old games to continue running instead of crashing with error.
 - Fixed slower character walking speeds in pre-3.1 upscaled and high-resolution games.
 - Fixed Object.SetView() and SetObjectFrame() not treating -1 for loop and frame as "keep previous values" in older games.
 - Fixed inventory window not updated after game.top_inv_item is assigned a new value.
 - Fixed a "New Room" command in old-style dialog scripts was preventing "First time Enter room" event to be called.

 - 32-bit Windows engine is now built as "large address aware" program, which will allow it to use up to 3 GB of RAM on 32-bit systems and 4 GB of RAM on 64-bit systems (was 2 GB previously).

 - Updated port for 3.6.*.

Web / Emscripten:
 - Fixed Safari cannot switch the game into fullscreen mode.

 - Added options for setting texture cache and sound cache size.
 - Added options to disable particular graphic drivers and graphic driver selection, and fullscreen mode selection.

Thanks to everyone who contributed to and tested this version!

Crimson Wizard

It's been less than a day, and there's already a serious bug found.

If there's an object that uses dynamic sprite, and that dynamic sprite gets deleted, and then another created and assigned, if the dynamic sprite's ID coincidentally matches the previous sprite's ID, then the object will not be visually updated.

Can be a script simple like this:
Code: ags
DynamicSprite *d = DynamicSprite.CreateFromExistingSprite(2100);
oObject1.Graphic = d.Graphic;
oExplosion.Visible = true;
d = DynamicSprite.CreateFromExistingSprite(2101);
oObject1.Graphic = d.Graphic;
oObject1.Visible = false;

This problem have been plaguing recent versions, resurfacing over and over again. Usually their reasons are optimizations to object drawing and dynamic sprite deletion. I am not sure how it was missed this time.

I must make a hotfix and make a new release now.

Crimson Wizard

The above situation is worse. It seems easy to fix for Direct3D/OpenGL, but Software renderer has its own issue that cannot be fixed easily.

During 3.6.1 development I made certain change, trying to optimize what happens when a dynamic sprite gets updated and deleted, so that it did not check each existing object in the game to see if that object has to be redrawn (because this may be slow if alot of dynamic sprites are created and deleted repeatedly). But the new variant has logical loopholes, and under certain conditions they may cause object image not be updated when it has to be, when run with Software renderer.

I would need to take more time and redesign this behavior.

The actual case when the problem happens in Software renderer:
1. Dynamic sprite created.
2. Dynamic sprite assigned to the room object.
3. Object is drawn on screen.
4. Object made invisible.
5. Dynamic sprite changed, or deleted and created again and assigned to object.
6. At least 1 draw pass with object not drawn.
7. Object made visible.
8. Next time object is drawn, it keeps the old looks from before the sprite changed.

Crimson Wizard

I'm also getting this error all the time now, and I don't remember we had this before, rather than on a rare occasion:
QuoteUnable to set EXE name/description: LoadLibrary failed

EDIT: so, I noticed that this is happening exactly after adding a new sprite.
The error goes away if I close and relaunch the Editor.
Does not happen in the latest 3.6.0 patch to me.


I just found another issue. This compiles fine:
Code: ags
  d2 = n[nide].GetNextVec();

However, there is no variable called "nide"; this was a typo and supposed to be "nid". The compiler doesn't catch this at all, and during the game the non-existent variable's value will be a random integer (I noticed this because I got an out of bounds error for the array).
I tested this to make sure and it also compiles just fine:
Code: ags
  d2 = n[nidfdlghkjshdf].GetNextVec();

The error already was in build so I assume it has been there for a long time.

Crimson Wizard

Quote from: Khris on Fri 05/04/2024 08:30:57I just found another issue. This compiles fine:
Code: ags
  d2 = n[nide].GetNextVec();

However, there is no variable called "nide"; this was a typo and supposed to be "nid".

Please tell what exactly "n" is? I tried following code in 3.6.1, and it catches the mistake:

Code: ags
struct Vec
    import int GetNextVec();

function game_start()
   Vec n[100];
   int d2 = n[nide].GetNextVec();


n is a script level array of structs:

Code: ags
// header

struct Node {
  int id;
  float x, y;
  int polyId;
  int prevId;
  int nextId;
  import Vec2D* Get();
  import Vec2D* GetPrevVec();
  import Vec2D* GetNextVec();
  import float GetAngle();

// main

#define MAX_NODES 1000

Node n[MAX_NODES];

bool Poly::IsInside(float x, float y) {
  int nid = this.firstId;
  Vec2D* min = n[nid].Get(), max = n[nid].Get(), node, s1, s2, d2;
  for (int i = 1; i < this.nodeCount; i++) {
    nid = n[nid].nextId; // move to next node
    node = n[nid].Get();
    if (node.x < min.x) min.x = node.x;
    if (node.y < min.y) min.y = node.y;
    if (node.x > max.x) max.x = node.x;
    if (node.y > max.y) max.y = node.y;
  if (x < min.x || x > max.x) return false;
  if (x < min.y || y > max.y) return false;
  s1 = new Vec2D;
  s1.y = (min.y + max.y) / 2.0;
  s1.x = 2.0 * min.x - max.x;
  Vec2D* d1 = new Vec2D;
  d1.x = x - s1.x;
  d1.y = y - s1.y;
  int cuts = 0;
  nid = this.firstId;
  for (int i = 0; i < this.nodeCount; i++) {
    s2 = n[nid].Get();
    d2 = n[nide].GetNextVec();                  ////////// <----------- error here leads to oob in GetNextVec function
    IntersectResult* ir = Intersect(s1, d1, s2, d2);
    if (ir.yes) cuts++;
    nid = n[nid].nextId;
  return cuts % 2 == 1;

I just realized: the line itself "works", but whatever n[nide] references, when its GetNextVec method is called, this.nextId is now a huge number and causes the oob error:

Code: ags
Vec2D* Node::GetNextVec() {
  if (this.nextId == -1) return null;
  Vec2D* r = new Vec2D;
  r.x = n[this.nextId].x - this.x;   /////// <------ this causes the oob error
  r.y = n[this.nextId].y - this.y;
  return r;

So apparently "nide" is inside 0...999 but n[nide].nextId is something like 104674 or 65833, i.e. random bytes I assume.

Edit: I tried
Code: ags
    d2 = n[nide].GetNextVec();
    Display("nide: %d", nide);
but the Display line correctly causes a compile time "undefined symbol" error.


Just had a 2nd weird accident:

Code: ags
    ds.DrawCircle(x ü this.Id, y, 2);

(The ü key is right next to the + key.) The above line caused the compiler to hang; it showed the box saying "Please wait while your scripts are compiled" but then nothing happened. The editor didn't really freeze either, the spinner was still spinning. It just never
 got to the next step. I had to force-close the editor.

Crimson Wizard

@Khris I remember now, @vga256 had same problem in one game, I was able to reproduce this with his game sources, but I was not able to create the minimal test case.
Even using your code from above separated into a dummy game does not cause the issue (compiler still correctly detects undefined "nide").
It seems that a number of factors are required to make this happen, and I don't know which ones.

Old compiler in 3.* versions is written in a very dirty code, and I don't feel like hacking it unless for some trivial fix, especially since we have got a new compiler by fernewelten ready in AGS 4.

Crimson Wizard

Quote from: Khris on Fri 05/04/2024 15:37:46Just had a 2nd weird accident:

Code: ags
    ds.DrawCircle(x ü this.Id, y, 2);

(The ü key is right next to the + key.) The above line caused the compiler to hang

I suppose it cannot handle UTF-8 characters in the regular code...
I might look into this, try to get compiler report a "unknown char" or similar, but cannot give any promises for the same reason as stated above.

Crimson Wizard

Quote from: Baguettator on Thu 28/03/2024 12:14:41I tried to build my game, using the AGS version, and for the first time, I got a message :
"Unable to set EXE name/description: LoadLibrary failed"

So, it seems like we found what's causing this, because it also started to happen on my PC and I was able to test this easier.
I will add a fix that worked for me.

Gal Shemesh

Hi guys! Wasn't very active recently and just dropped by to see what's new.

Congratulations on the 3.6.1 release! So glad to see that it passed its beta phase, and that many things that I reported about were fixed and suggestions that I raised to make AGS better were included! :) Thanks to everyone who took part for their effort!

As for the new bugs - it's inevitable. But I have my full faith in you all - no bug could stand in your way! :grin:

Keep up the good work and many thanks again.
Gal Shemesh,


Quote from: Crimson Wizard on Fri 05/04/2024 16:06:09@Khris I remember now, @vga256 had same problem in one game, I was able to reproduce this with his game sources, but I was not able to create the minimal test case.
Even using your code from above separated into a dummy game does not cause the issue (compiler still correctly detects undefined "nide").
It seems that a number of factors are required to make this happen, and I don't know which ones.

This was such a strange compiler bug - I spent hours trying to figure out what the conditions were, and couldn't replicate it using "simpler" code.

One thing I can say though is that, superficially, the call looks similar to Khris':
the offending code: where I could write any combination of letters in place of the "i" index, producing the same results
Code: ags
 CurrentVehicleMap[i].FlyToPosition(terrainTile.x, terrainTile.y);

CurrentVehicleMap was also a struct with several functions like FlyToPosition

I just wish I could figure out what the issue was. As CW said, switching to AGS4 did solve the compilation problem (e.g. it caught my mis-spelling of the 'i' index every time.)

Crimson Wizard


Crimson Wizard

Unfortunately, the patch is not fixing all the issues, so I cancelled it until everything is retested.

Crimson Wizard

Unfortunately there's a big confusion right now. The patched version was not updated on a website homepage, and user who reported the problem used that link instead of the one in forum post.

The reason the website was not mentioning a new link is, that for a while there's a new security rule for AGS fileserver, where I can upload new version, but cannot enable it for download. Instead I have to PM site admin (AGA) and ask him to configure permissions for these files.

This creates a latency between my patch announcement on github and forums, and the link update on homepage.

I will need to change the order of my actions, where I'll first wait for AGA's approval of new files on server, and then post a release announcement on forums.


I think the forums and GitHub link are official enough, isn't there a way for the website to just link to the GitHub Releases? Or the forum board.

Crimson Wizard

Quote from: eri0o on Tue 09/04/2024 01:03:39I think the forums and GitHub link are official enough, isn't there a way for the website to just link to the GitHub Releases? Or the forum board.

I'm editing a small xml on a file server, and the link is a regular URL, from my understanding it could be anything.

There was a small discussion on hosting several years ago, and AGA asked me to host the releases on AGS fileserver still. Although I stopped uploading Beta releases there a while ago, but mostly because of my laziness (it's faster to link to a github page when I do a quick beta update). Also, there may be unknown number of "alphas" and "betas", and I got concerned about filling the fileserver with these (and they mostly become useless after a stable release).

I don't know if github imposes any restriction on number of downloads, and having it on someone elses server may seem undesired by the AGS administration, perhaps?

Crimson Wizard

SMF spam blocked by CleanTalk