Menu

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.

Show posts Menu

Messages - Crimson Wizard

#1101
Seeing how in Overlays mode overlays are not getting removed from memory even when they are set as "not visible on screen", I think this module works with assumption that player may return to the same place and see these objects again.

This may not be always the case. For instance, in RootBound's game, at least from the looks of it, the camera only moves forward, so any object past the camera will never bee seen again.

Perhaps it will be a good idea to add a setting that sais: "automatically remove objects that went behind the camera"?
#1102
Quote from: lafouine88 on Tue 27/08/2024 21:44:47So using the debug mode definitely helped, it semms there was a problem with the coordinates. I don't know why but when I set it to map coordinates like 2000,1400 it didn't show anywhere, but when I corrected to player.x-150; player.y-70 (which led to the same values) it worked.

This is not expected, there should not be any difference if the values are actually same. Can you post the code which you used?
#1103
Something is off in this module. I never used it myself, but I've got couple of reports from RootBound, one appeared to be an engine's bug with software renderer, and another seems to be an issue with this module.

The reason why it was not noticed maybe is because it becomes a real problem only with Software renderer.

What I found is that when some object gets past the camera, it is not marked as "not visible", and keeps growing in scale.

I did not have time to investigate this well, but quickly looking at the code in UpdateObjects function, where it calculates the distance to camera and object scale, makes me confused, because Visible flag is nowhere set, which means that it never changes to "false".

As a result, something like following happens:
Code: ags
[Script][Debug]: Object 0, zd = 203.03, f = 1.77, w = 156, h = 227
[Script][Debug]: Object 1, zd = 203.03, f = 1.77, w = 156, h = 227
[Script][Debug]: Object 2, zd = 203.03, f = 1.77, w = 156, h = 227
[Script][Debug]: Object 3, zd = 203.03, f = 1.77, w = 156, h = 227
[Script][Debug]: Object 4, zd = 3.03, f = 118.64, w = 10452, h = 15186
[Script][Debug]: Object 5, zd = 3.03, f = 118.64, w = 10452, h = 15186
[Script][Debug]: Object 6, zd = 3.03, f = 118.64, w = 10452, h = 15186
[Script][Debug]: Object 0, zd = 202.18, f = 1.78, w = 157, h = 228
[Script][Debug]: Object 1, zd = 202.18, f = 1.78, w = 157, h = 228
[Script][Debug]: Object 2, zd = 202.18, f = 1.78, w = 157, h = 228
[Script][Debug]: Object 3, zd = 202.18, f = 1.78, w = 157, h = 228
[Script][Debug]: Object 4, zd = 2.18, f = 164.81, w = 14520, h = 21096
[Script][Debug]: Object 5, zd = 2.18, f = 164.81, w = 14520, h = 21096
[Script][Debug]: Object 6, zd = 2.18, f = 164.81, w = 14520, h = 21096

Notice the gigantic object scales: 14520 x 21096, and they keep growing!

This is not a big issue in Direct3D / OpenGL, because they scale textures only when rendering them.

But Software renderer is creating transformed (scaled) overlay bitmaps in memory, which quickly occupy all available memory space and crash the program.


EDIT:
On engine's side this situation may be improved by not preparing new overlay's graphic while it's offscreen. This is easy to do for GUI and screen overlays, but bit more complicated for room objects and room overlays, as these will have to be tested against all existing cameras.
#1104
Dave Gilbert have recently reported a problem where ListBox is not arranging items far enough from each other. Maybe this have happened before to someone elese. Unlike Label control, which uses LineSpacing when wrapping text, ListBox is still using font's height to define item's height.

I am in doubts whether this will be correct to use LineSpacing in ListBox, as line spacing is meant for wrapping same text, while list box items are sort of separate entities.

Alternatively, ListBox could have an explicit "row height" property, and/or "row padding" property.
#1105
The dialog option still has a length limit of 150 bytes (150 characters in ASCII, but may be less in Unicode).

So if it has to be longer, this has to be done using a custom solution: a gui, or a Custom Dialog Rendering:
https://adventuregamestudio.github.io/ags-manual/CustomDialogOptions.html


BUT, before going any of these direction, perhaps consider giving an option a shorter name, uncheck "Say" checkbox for that option, and display the actual long text using normal command inside the dialog script instead.
#1106
AGS download links are organized in a table, which is a very good change.
#1107
@MoonBird

So, here's an experimental version of the AGS that has a text skipping config setting:
https://cirrus-ci.com/task/5372902994870272

if you download a link called "archive" it would contain the whole Editor, but you only need a file called "acwin.exe" to run the existing games.

Place "acwin.exe" in the game folder, and then insert following into the config file (acsetup.cfg):
Code: ags
[access]
speechskip=input

Then run "acwin.exe" to start the game (not the original game exe).

Other possible values are:
"any" - will skip speech by input and time
"time" - will skip speech by time only
#1108
Can't believe it took so long to address, but finally made a PR for this:
https://github.com/adventuregamestudio/ags/pull/2512

There will be a "window state" config saved for AGS editor, which is saved both in memory between times a dialog window is opened, and to a file between editor sessions.

This config stores individually picked windows and properties, and may be amended as necessary.
For now it will have "Select a sprite"'s window position and size, and splitter position in it; and also splitter position in the Sprite Manager, mostly for consistency (because it's the same kind of control).

If there are more windows / panels that require this, please note here.
#1109
MaskPathfinder is now the part of AGS 4 too, and AGS allows to import and load sprites in 8-bit as an option (without auto converting them to game's default format), so it's possible to have pathfinding over custom 8-bit bitmaps in script without any relation to the room.
#1110
Quote from: eri0o on Sun 25/08/2024 16:41:58This was added to ags4 in https://github.com/adventuregamestudio/ags/pull/2479 and https://github.com/adventuregamestudio/ags/pull/2494

Right, but it's not in the released version yet. Will need to update this topic when these make to the released update.
#1111
Quote from: MoonBird on Sat 24/08/2024 13:53:47This really needs to be a setting you could change from the.cfg file. With tears in my eyes, I've been forced to abandon TENS of games because I just don't manage to read half of their dialogues. :~(  I really would want to play them, but it's impossible, until someone does something to this huge accessibility problem. It just can't be that playing adventures is a priviledge of native english speakers who read fast.

There are two different situations here:
- when someone is making a game
- when the game is already released.

In the first case a game developer can implement the text skipping as a in-game setting. There's no problem here, except for developer's willingness to do so.
In the second case this would require a change in the engine to support extra config option(s) that would override the game.

BTW there's already a thread about this that you opened:
https://www.adventuregamestudio.co.uk/forums/adventure-related-talk-chat/text-speed-in-ags-games/
#1112
Quote from: Ghostlady on Sat 24/08/2024 02:38:37I would like to have it start scrolling as soon as I enter the room as opposed to the space bar.  What would I need to change for this?

Remove this:
Code: ags
void on_key_press(eKeyCode k) {
  if (k == eKeySpace) StartCredits();
}

And add this to the end of room_load:
Code: ags
function room_Load()
{
   ... other code still here ...

   StartCredits();
}

But if you do that you also need to move whole room_Load() function down the script, because the function that calls other functions must be located below them.
#1113
Quote from: lafouine88 on Fri 23/08/2024 15:27:32The game loads, but my character cannot move

Do you have these debug controls in the on_key_press somewhere?

Code: ags
  else if (mod & eKeyModCtrl)
  {
    if (keycode == eKeyA)
    {
      // Ctrl-A will show walkable areas
      Debug(2, 3);
    }
  }

If not, try inserting this code.
And then press Ctrl + A in this room, and see how the walkable areas actually look like in game.

Do you call "remove" or "restorewalkablearea" somewhere in script?
#1114
Quote from: lafouine88 on Fri 23/08/2024 13:12:04@Crimson Wizard Sorry, I would love to close this thread but I still havent' managed to make things work. The plugin you sent gets deleted by antivirus and when it doesn't it still won't work.

This is not a plugin!..
Can you tell what do you do, step by step, and what exactly happens as a result?

Quote from: lafouine88 on Fri 23/08/2024 13:12:04How did you make the colors the same as 8 bit palet ? You just need to copy RGB numbers right? Could you send me a bmp that works for you so I can try it ?

Yes, I copy RGB values from palette slots 1-15.

Here's an example of bitmap that worked for me:
https://www.dropbox.com/scl/fi/tc5fjtdx0gn8smuxgirq1/random.bmp?rlkey=qpnzknenm4osyekw9zhsgieq6&st=tkgqx7i5&dl=0
it has 2 colors: white and blue, should be imported telling that white color is transparent (for example - set transparent color from top-left pixel), then blue part becomes mask area 1.
#1115
The following is not the final plan, but an outline of an idea.

The idea of a coroutine that I had is to let ags script vm support a function which could be paused, saving state, and then restored and resumed.
Coroutine's state includes stack (local data) and execution pointer.

Pausing coroutine effectively exits them, but this cannot be done with a regular "return" statement, because "return" unwinds the stack and ends the function.
So there has to be a separate statement for pausing (e.g. "yield" or "waitfor").

Paused coroutines do not prevent engine to update, any events to happen or any script functions to run. They just stay "saved" in the engine's memory, until resumed again under certain conditions. If game is restored from a save file, restarted or exited while there are paused coroutines, these coroutines are erased from memory. (In regards to saves, please see a note in the end of this post)

I imply that in AGS coroutines must return a special type of object when returning with pause. Different languages implement this differently. As a draft I assume some kind of a "wait object" that contains:
- a reference to certain background action that has a completion flag;
- a reference to the coroutine (internal id?), because engine will need to know which coroutine to resume when the action is complete.

This hypothetical WaitObject may be a parent class for other objects, such as WalkingAction or AnimationAction etc, if necessary, but I won't expand this further there. It may also host a "on completed" event to attach user's delegates, if delegates are eventually implemented in AGS.

I suppose that functions that can start non-blocking actions will return this WaitObject or any of its extended types.

When such function is called in coroutine, you can take the returned WaitObject, and use it to pause coroutine, using "return with pause" statement, e.g:

Code: ags
WaitObject MyCutscene()
{
    // initial statements
    
    WaitObject o = player.Walk(100, 200, eNoBlock);
    waitfor o;
    
    // or just
    
    waitfor player.Walk(50, 150, eNoBlock);
    
    // more statements
}

Coroutine may have any number of "pauses", also nested into conditional blocks or loops. It finishes only when reaches real "return" (either explicit statement, or end of function).

Now, the important question is, where does coroutine returns to when pausing.
The short answer here: if it's a first pause, then it returns to where to was called from, whether engine or user's function, but is kept saved in the engine's memory.
Any following pause or return after the first one returns directly to the engine.
But this must be clarified.

Suppose you called a coroutine from another function:

Code: ags
WaitObject MyCutscene()
{
    waitfor player.Walk(100, 200, eNoBlock);
    waitfor player.Walk(50, 150, eNoBlock);
}

function on_mouse_click(MouseButton btn)
{
   if (btn == eMouseLeft)
   {
      MyCutscene();
   }
}

What happens here is this:
1. on_mouse_click is run.
2. MyCutscene() is run.
3. first non-blocking Walk is called.
4. MyCutscene pauses and returns.
5. on_mouse_click continues, and exits.
6. engine updates the game as usual.
7. player.Walk command completes.
8. Engine resumes MyCutscene(), MyCutscene continues to run.
9. second non-blocking Walk is called.
10. MyCutscene pauses and returns.
11. engine updates the game as usual.
12. player.Walk command completes.
13. Engine resumes MyCutscene(), MyCutscene continues to run.
14. MyCutscene reaches its end, and ends normally.

It should be possible to have nested coroutines.
It should be possible to call waitfor on a coroutine's return value, which effectively turns calling function into coroutine too.

There's possibly a number of unanswered problems here. And this suggestion may be different from coroutine implementation in other languages. So consider this to be a draft of idea.

In the context of AGS, there's one question that I have not yet thought through, that's saving game while there are paused coroutines.
AGS does not save the game when a function is run, but if coroutine is paused then it is not running. On another hand, saving with a paused coroutine means the coroutine's state must also be written to a save and loaded after.


#1116
Quote from: Snarky on Thu 22/08/2024 13:02:21Will the bit after the if-block run if cEgo has an iHoverBoard? Typically in AGS script you would expect that it doesn't because of the return statement, but if the script actually only runs the waitfor(cEgo.Walk) statement now and schedules the rest of the if-block for later, it won't hit that point, and the rest will run.

No, it won't run, why would it? The idea was that execution halts at "waitfor" and then proceeds with the next line.


The event-delegate idea is interesting as an optional ability of attaching a function to the "waiting completed" event.

However, if this is used as a replacement for waitForComplete, then I'm afraid that some constructs become difficult to resolve. For example, what if waitForComplete is inside "if"?

Code: ags
if (condition)
{
   waitForComplete(action);
   more commands
}

other commands

Here one part of statements is always run after event, and second part may run either instantly or after event.

Or if waitForComplete is inside a loop.

Code: ags
while (condition)
{
   waitForComplete(action);
}

Will that become a recursive delegate?


What I might propose instead, following the previous idea of Coroutine, is to let blocking function return some kind of a "WaitingObject" type, which in turn may be used in 2 ways (also simultaneously):
- returned into the engine, using specific keyword such as "waitfor" or "yield", where engine tracks its condition and resumes the coroutine when its complete.
- attached a custom callback using syntax like "WaitingObject.OnComplete += func".
#1117
Quote from: lafouine88 on Thu 22/08/2024 12:46:53@Crimson Wizard Do I need to install the engine plugin you linked? I tried what you said, carefully following the steps but it still won't work. I'm not sure if it's my bmp colors that are not good or my coding (I just copied what you wrote) but something is wrong. I understand you tried it yourself, could you send me the .bmp you used ? If I can get it to work then it's just my image format that's not right :s

That's not a plugin. I linked a patched engine executable, that should be used instead of the current one when compiling the game. If you like to use it, copy acwin.exe to the Editor's program files, overwriting existing acwin.exe (or rename existing one to have it as a backup).

Following my steps won't work without this patched engine, because there are bugs in the current official version that will prevent them from working correctly.
#1118
I think that implementing coroutines in AGS script may be a solution to this:
https://en.wikipedia.org/wiki/Coroutine

Any kind of command sequencing or making scheduled command list has a number of problems:
- for sequencing you'd need every function to have same return value type, which will allow to sequence next function; If not that, then they have to be wrapped into another function that has this standard return type (or lambda).
- for both sequencing and scheduling it will be more complicated to add anything besides function calls: conditions, loops, operations etc - these will have to be wrapped into function calls too (or lambdas), making syntax more complicated.
- specifically for scheduling, there's a problem of getting current values from global variables if they are used as arguments, because they may change before a scheduled command is called.


Coroutines are, to put it simply, functions that may be paused at certain points.
This is of course not a real plan, and this may be more difficult than I say here,
but in a very crude sense, we'd need a mechanism that
- allows to mark the script function as "coroutine", e.g. some keyword;
- engine runs such function on a dedicated "thread" (internally in ags this is called "script instance fork").
- when such function issues a "waiting for" command, it generates some kind of notification trigger for itself and passes into the engine, then suspends and waits for notification from the engine;
- engine has a list of these triggers somewhere, it checks them during game update, and raises notification for those that achieved result.
- when a "script thread" which runs a coroutine gets a notification, it continues running its function from the point where it paused last time.
#1119
I might sound quite rude saying this, but looking at these lambdas makes me shudder. I think both of the examples posted above will only make everyone confused. I mean, beginners are often confused by much simpler things, like having to write commands inside functions, having to put brackets after ifs, or writing their own functions.

Having nesting with condition is what makes it even worse. In majority of cases this likely will be a sequence with no branching, next commands are only supposed to be executed if previous ones were not interrupted.

This means that the cleaner variant of syntax is the one that assumes that case, and implies the condition check, but does not require user to write one explicitly.

I.e.:
Code: ags
waitfor( cEgo.Walk(x,y,eNoBlock) );
cEgo.Say("I will say this when I reach x and y!");
cEgo.ChangeRoom(5);

or
Code: ags
waitorcancel( cEgo.Walk(x,y,eNoBlock) );
cEgo.Say("I will say this when I reach x and y!");
cEgo.ChangeRoom(5);

where "waitfor" wraps waiting for completion, and "waitorcancel" also wraps result check and return statement.

Well, that's just a dumb example, but I'd rather propose go into the direction of this "linear" syntax.


EDIT:
But lambdas or not, I think the first problem is to support functions of type "coroutine". That is - functions that return temporarily and then enter back at the point where they stopped last time.
OR, support engine running multiple function threads at the same time.
Because right now AGS does not process player input while inside any script function.
#1120
Quote from: Babar on Thu 22/08/2024 04:14:49Sorry to interject, but I was just wondering about approaching stuff from the opposite direction as well:
Instead of investigating how to interrupt blocking functions, what about how to incorporate non-blocking functions?

Why not:
cEgo.Walk(x,y,eNoBlock);
cEgo.Say("I will say this when I reach x and y!");
cEgo.ChangeRoom(5);

And have that all work in that order, in that sequence, and if the walk is interrupted by something else, stop the function?
Because the desired functionality here doesn't appear to be wanting to interupt blocking actions, but rather, wanting to be able to have actions be non-blocking, which currently can't be.


Exactly! I was speaking about this couple of times in my past comments.

While it is technically feasible to let interrupt blocking action both with player input and a script command (from repeatedly_execute_always), - and we already have examples of that: speech, Wait, blocking video playbacks - all these may be interrupted, - the blocking nature of this "interruptible" action prevents doing anything else while its running.

It is only when the action is non-blocking (in AGS terms) - then both player and script will have full control of the game during the action.

Each action in AGS may be run non-blocking (with a very few exceptions). It is possible to have that.
@Babar when you say "which currently can't be", I assume you mean that it's not possible to have the next actions to wait until non-blocking finishes in the same script function?

The thing is that if you run action non-blocking you got to separate the continuation of the sequence. There has to be a trigger that runs next part of this sequence, currently that is something that you have to script yourself. All the newcomers have problem with that, but eventually this is something that you just have to learn.

So the question here may be put like:
How can we improve AGS scripting to let easier scripting of scheduled sequence of actions, some of which may be non-blocking, a sequence that also detects when previous action was cancelled and automatically cancels itself.

Is that it?
SMF spam blocked by CleanTalk