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

Topics - Snarky

#1
I'm getting a syntax error I can't figure out (AGS v3.6.1). As a minimal example:

Code: ags
struct Storage
{
  Object* oArray[];
}

Object*[] GetArray()
{
  Storage s;
  Object* oArray[] = s.oArray; // <-- Error "Type mismatch: cannot convert 'Object*' to 'Object*[]'"
  return oArray;
}

It works if I do:

Code: ags
Object*[] GetArray()
{
  Object* dummyArray[];
  Object* oArray[] = dummyArray;
  return oArray;
}

... So it must have something to do with accessing it from the struct. Is there a correct syntax, or have I hit an engine limitation?
#2
Yes, it's another baffling true-life case from the Snarky Files. In this case I don't actually know the correct solution in reality, but I have a hypothesis that will serve as the answer for the purposes of this game (unless someone comes up with a different answer that turns out to be correct).

The Case
I have two sets of wireless ear buds, so that I can use one pair while charging the other. Each pair comes in a small carrying case. Last week I was listening to music while biking to work. I was in a rush as I was a bit late. I remember taking out the ear buds as I entered the office, and putting them in their case that I had been carrying in my jacket pocket. (I think the other case was also in my jacket pocket.) That is the last time I remember having them.

I put my jacket in a shared closet/wardrobe nearby, dropped off my bag by a desk (we use a hot-desk open office setup without fixed work spaces; all the ones in my usual area were taken, so I left it until I could find a free seat), and hurried to find a free meeting room for a remote meeting. The rest of the day was spent in the office: After my meeting I found a free desk in the open office area, I grabbed coffee from the kitchen zone, I went to lunch in the cafeteria, and I had another meeting in another meeting room.

At the end of the day as I was preparing to leave, I looked for the ear buds and could not find either pair. I checked my jacket, bag, trouser pockets, the area around the desk I had used and where I initially dropped my bag, the kitchen area and both meeting rooms I had used. Everyone else had already left, but when I was next in the office I checked the lost and found and asked the cleaner if she had found anything.

Where did they go?

You may ask me follow-up questions or offer theories.
#3
Moderator note: This topic was split from here: https://www.adventuregamestudio.co.uk/forums/adventure-related-talk-chat/i-started-a-devlog/

Good stuff! But this bit threw me:

Quote from: ThreeOhFoura few issues that were specifically related to the quirks of the AGS script language. For example, assigning an integer variable as the size of an array of floating point variables requires that you refer to the integer variable with the "float" type, despite the fact that you're calling an integer and that the array size cannot be a floating point variable, and yet AGS's rule for requiring an IntToFloat call to handle this conversion breaks the script. He pointed out that I could simply refer to the integer with the "float" type and that this would pass in this specific exception

It sounds like there must be some sort of misunderstanding. To use an integer variable to set the size of an array of floats, you would write something like:

Code: ags
  int arraySize = 15;
  float floatArrayDynamic[] = new float[arraySize];

This is not "referring to the integer variable with the 'float' type." The new float[arraySize] bit doesn't mean that arraySize is being used as a float; it's an instruction to "create an array of floats, with size arraySize." And the size of an array is always an int, of course.

It would be the same whatever we make an array of:

Code: ags
  bool boolArray[] = new bool[arraySize];
  AudioClip* clipArray[] = new AudioClip[arraySize];
  // ...

In each case, the bit in the brackets is giving the size of the array, and has nothing to do with the array type.
#4
Have you ever started a project from a template, changed the resolution, and discovered that even though you said yes to "Would you like AGS to automatically resize all your GUIs to the new resolution?" the UI looks completely broken? That's because while AGS resizes the dimensions of the GUIs and GUI elements, it doesn't scale the sprite graphics accordingly, so after the resize they no longer fit.

This module deals with that problem. By adding a single line to game_start() all the UI graphics are rescaled to the specified dimensions:

Code: ags
// In GlobalScript.asc
function game_start()
{
  UiScale.Rescale(2.0); // Scale the UI graphics to double the resolution
}

You can also have different horizontal and vertical scaling factors, and configure it to include or exclude GUIs and GUI Controls, Inventory Items, and Mouse Cursor Modes – in general or on an individual basis (for example if you change the graphics for part of the UI and don't want to scale those any longer):

Code: ags
function game_start()
{
  // Inventory items will not be scaled, except for iKey
  UiScale.IncludeInventoryItems = false;
  iKey.SetIncludedInScaling(true);

  // gMyNewGui (and all its controls) will be excluded from scaling
  gMyNewGui.SetIncludedInScaling(false);

  // This button will be excluded from scaling (even if the rest of its owning GUI is scaled)
  btnAlreadyEdited.SetIncludedInScaling(false);

  // Mouse Cursors are not scaled by default, but we set eModeLookat to be scaled 
  SetCursorModeIncludedInScaling(eModeLookat, true);

  // Scale by 3 horizontally and 2 vertically
  UiScale.Rescale(3.0, 2.0); 
  // If math is not your thing, you could also just put new_resolution/old_resolution, e.g.:
  // UiScale(1024.0/320.0, 600.0/200.0);  // Upscaled from 320x200 to 1024x600; works out to (3.2, 3.0)
}

Finally, you can get a report on how many scaled sprites the module creates, and a list of the sprites that have been scaled (useful to see which sprites you still need to replace):

Code: ags
function game_start()
{
  UiScale.Rescale(2.5); // You don't need to scale by whole numbers
  System.Log(eLogDebug, "UI Scale resized %d sprites:", UiScale.Count);
  String spriteList[] = UiScale.ListScaledSprites();
  for(int i=0; i<UiScale.Count; i++)
    System.Log(eLogDebug, spriteList[i]);
}

Note that this module creates scaled copies of all the UI sprites and stores them in memory (as DynamicSprites), so it will increase the memory requirements of your game—potentially by a lot (especially with high game resolutions). It should only be used as a temporary solution until you can replace the sprites, or for small/test projects.

Bugs and limitations:
-No known bugs (please report any you find)
-The module does not scale fonts, so text formatting may look strange after scaling
-There is no way in AGS to retrieve mouse cursor hotspot coordinates, so if the hotspot is not at (0,0), scaling cursors will not appropriately adjust the hotspot position; this must then be done manually using Mouse.ChangeModeHotspot(). For this reason, mouse cursor scaling is off by default
-Animated mouse cursors are not scaled. (But this could be added in future)
-The verb coin template assumes a circular verb coin, so scaling by different horizontal and vertical factors may have non-optimal results; also note that to work with the Verb Coin template, UiScale should be placed below the VerbCoin module in the script list
-The module only applies scaling to sprites that are set as UI graphics when it is called (normally on startup); if set to some other sprite later on (as another module might potentially do), that sprite will not be scaled

Version history:
-v0.4: Initial release

Download:
UiScale v0.4
#5
Quote from: Nurz on Tue 05/09/2023 16:06:02Do you mean to gradually slow down the movement when walking up the y-axis, to imitate longer traversed distance when they walk further to the background? That would be great too. It would also make sense to work vice-versa and accelerate when walking down (forth) again.

No, in this context I'm just talking about the view angles, though it's related. If your room is a flat surface extending to infinity (a single walkable area), then moving at e.g. a 30-degree angle on screen (say 10 pixels up, 20 pixels right) represents quite different movement angles in 3D space depending on the distance, because movement "away" gets increasingly foreshortened, so that small y-movements represent larger and larger distances "into" the screen. Therefore, the further away the character is, the wider the angle of movement that should use an up/down angle.

Or to explain it another way: Let's say you have a room in one-point perspective, with a road coming from the bottom left going straight into the vanishing point in the distance. Now imagine a car driving down the road, moving in a straight line (the road) across the screen. Then the car will be seen from the side when it's up close, but more and more from behind as it recedes into the distance, even though it's always moving at the same angle. To get this effect in AGS, the relative size of the different viewangles (IOW the foreshortening) has to change depending on distance.

As Crimson Wizard says, it's possible that all this is unnecessarily complicated for a 2D engine. (My bigger concern is that it might not look right unless you also do foreshortening of the movement.)

Quote from: Crimson Wizard on Tue 05/09/2023 16:14:41Besides, how many users will actually going to use this, in a 2D point & click game?

It depends on what "this" is. I think the inability to adjust the view angles is a real problem, which people regularly complain about. Just how much flexibility and built-in logic is needed to meet user needs is more debatable.

My proposal is to make it a setting very much like Scaling: set on a walkable area basis (with a sensible default), but possible to override. I'm assuming it would be a float representing the degree of foreshortening, like in Khris's calculation.

To do the "vary by distance" part you could actually just do the same as for scaling: define a max and min value and interpolate between them, so it doesn't seem all that complicated to me, but if you just want to have a single property that will be a big improvement in itself.
#6
So, this isn't quite a Black Stories mystery, but a true-life tale that happened to me the other day and had me stumped for at least half an hour, and I thought it might be fun to see if you could solve it.

The Case
The other day I thought I'd make a pot of tea. (Since the pandemic I've switched from teabags to proper brewing of loose-leaf tea in a pot, though with a kind of wire basket to retrieve the leaves afterward.) But when I took the lid off the pot I discovered I had already made one earlier, which was now cold. I decided to just heat up a cup in the microwave—I know some people find reheating to be a crime against tea, but I honestly think it tastes just fine.

So I looked around for my favorite tea mug, but I couldn't find it.

Where was it?

(Ask me any such questions as might help, or propose places to look for it.)
#7
Hints & Tips / Dreams in the Witch House
Mon 05/06/2023 08:47:39
I'm getting fed up with the rat, and I wonder if there is some way to deal with it or if the constant frustration is meant to be an unavoidable part of the game.

Spoiler
Whenever I try to poison it, it just eats the plank and bites me, with no apparent ill effect of the poison.
[close]
#8
The forums are now telling me I'm not allowed to view spoilers:



(For once, this does not seem to have anything to do with CleanTalk; it's the same whether I'm on VPN or not.)
#9
As a script module writer, some modules can get very complex, and it would sometimes be useful to break them up into separate scripts. This would help keep individual files simpler, but also add flexibility for users about what functionality they need and what they don't, and allow the creation of "libraries" to provide features used within multiple script modules, without requiring code duplication.

For example, for the SpeechBubble module, it would be useful to have the code for text formatting/rendering and for formatting GUIs with outlines, corners and backgrounds as separate pieces of functionality in their own scripts, as well as the code that replicates AGS's speech blocking logic (and other missing Wait() functions).

Of course, you can do this already, but it means that there are dependencies between the scripts, and there is no good way to distribute them all together.

Similarly, someone might create a script module that uses e.g. Tween, or some other pre-existing module, but then they have to explain to users that they need the other module, and that it has to be placed higher in the hierarchy, etc.

I think a good way to solve this problem would be if it were possible to save and distribute the module as a (sorted) script folder. When imported, it would create the folder in the script hierarchy. (And to forestall one objection: it would be easy as a module author to use #ifdefs to avoid a case where the same script is imported twice in two folders, e.g. a bundled copy of Tween into a project that already has it.)
#10
We've had paging bugs before where threads get lost between pages on a board, but I don't think I've ever before noticed posts going missing between pages of a thread. However, currently this post (from 25. December at 10:01:51 CET, where I talk about just having seen Glass Onion) does not appear for me either on page 2 or 3 of the thread.
#11
See thread here.

The documentation for this method states:

Quote
Code: ags
Character.ChangeRoomAutoPosition(int room_number, optional int newPosition)

Changes the room that the character is in, and positions him along one of the room edges.

This command simulates the behavior of the old "Go to room" interaction command from AGS 2.72 and previous versions. If newPosition is not specified or is 0, the character will be placed on the opposite side of the new room, if he is within 10 pixels of a room edge in the current room.

Alternatively, you can specify the position where he will get placed in the new room. newPosition can be 1000 for the left edge, 2000 for the right edge, 3000 for the bottom edge and 4000 for the top edge. Then, add on the offset within that edge where you want to place the character, in normal room co-ordinates.

(1) It should be clear from this description that the function cannot work correctly in any game with a room width or height greater than 1000 (because the edge encoding will overflow).

(2) The documentation also leaves undefined how the character will be positioned if it is not within 10 pixels from a room edge.

(3) Khris reports that the current behavior of the function is buggy/not according to spec:

Quote from: Khris on Sun 27/11/2022 20:36:44ChangeRoomAutoPosition is buggy apparently, the Tumbleweed template's 2nd room is twice as wide and Roger ended up halfway between the room's center and edge, suggesting that AGS uses the distance from the center to calculate the new position, not the distance from the edge.

(In other words, it fails to position the character along the edge in the new room.)

If this is a regression and hasn't always behaved this way, it should be fixed for backwards compatibility. I cannot test that right now, but I'll try when I can. (And as a minor point, the documentation should be edited to be gender-neutral. I think "it" should be the preferred pronoun for characters.)

Going forward, I propose that the whole function be deprecated, since its API is fundamentally incompatible with an engine supporting larger resolutions/room sizes. If the functionality is desired in the engine, a new function with an API like the version I wrote in AGS Script could be provided:

Code: ags
Character.ChangeRoomEdge(int room_number, optional RoomEdge edge, optional int edgePosition)

(As in my implementation, I also propose removing the 10 pixel condition, and pick the room edge the character is closest to/furthest outside as the exit edge, no matter the distance.)
#12
See thread.

AGS Script allows you to call functions like String.Format(), Character.Say() and Display() with a variable list of arguments of "arbitrary" types. However, it is not possible to create custom variadic functions in AGS Script (or, at least, there is no way to actually read the argument values). Some way to support this would make the scripting language a lot more powerful and convenient: for example, you could write mathematical functions that could take either ints or floats as arguments (function overloading), create generic functions that could, for example, manipulate arrays of arbitrary types, etc.

Of course, it may be that there are better approaches to achieve those goals, but I thought since it already exists in the engine somehow, this might be relatively easy to implement.
#13
Editor Development / [BUG] Sprite Resolution
Fri 02/12/2022 09:07:02
[AGS Editor v3.6.0.38]

The "Resolution" property for sprites used to allow you to scale up "low-resolution" sprites in "high-resolution" (above 320x240) games to 2x size. This capability is now disabled by default. However, I think there are two problems with the way it currently works.

-First, even when "Allow relative asset resolutions" is disabled, the property is available in the sprite editor and can be modified. This is confusing because changing the value has no actual effect in-game. I think the property should be hidden or made non-editable when the game-wide setting is disabled.
-Second, it used to be possible to bulk-edit this setting by selecting multiple sprites and adjusting the property. Now, the changed value is not applied to all the selected sprites, but only to the first one. I would consider this a regression.

Separately from this, I think it would be nice if the ability to pre-scale sprites was reintroduced in a more straightforward way, e.g. a sprite scaling setting that could be set to 1x, 2x, 3x, 4x.
#14
Sooo... the era of lockdowns appears to be over—regardless of whether the actual pandemic is. We've missed three years of Mittenses; is there any interest in resuming the tradition next year?
#15
Site & Forum Reports / YouTube embeds
Sat 29/10/2022 09:03:46
Just another example of how nobody understands the way embedded YouTube videos is supposed to work. Is it completely impossible to do anything about, so that it will accept a full URL rather than just the ID?
#16
General Discussion / AI, bots and PKD
Fri 28/10/2022 19:14:40
I had a thought that isn't particularly new or original, but that suddenly struck me forcefully.

We've discussed how GPT-3 and other machine learning systems can produce ever more convincing texts (as well as images and voice). And we know that bots are used extensively by spammers and scammers, including to post spam on these forums, and for example on dating apps, because for most of their schemes, the (cost of the) human effort involved is the limiting factor.

It just occurred to me that it's inevitable that as these ML systems become better and better at impersonating a real person, they will be widely adopted by crooks, who will flood every digital channel and forum with deceitful material meant to scam people out of their money (or for other nefarious, monetizable purposes). There will be so much AI-generated bullshit online that it will drown out any genuine human attempts at communication.

If establishing and maintaining a fake identity becomes easy and cheap enough, bad actors can create millions or billions of them, and potentially have them build up credibility over years before breaking cover. There will be no way to trust that someone online isn't a bot set up by criminals: that the friend you've been gaming with for years, the person you've been discussing books or politics with, the aspiring artist or comedian you've been following, isn't just an algorithm waiting for a good opportunity to rip you off.

It reminds me of "Second Variety," a story by Philip K. Dick in which the few surviving humans find themselves lost in a sea of hostile androids impersonating humanity, unable to trust anyone.

Capitalism + lightweight identity + AI = end of human connection

The only solution I can see is that all online accounts and identities would have to be authenticated against some authoritative database, to ensure a real person is behind each account and can be held... accountable. (Of course, some social networks are already trending in that direction. To sign up for an Instagram account these days you might have to stream a live video of yourself holding up your username on a piece of paper.)
#17
I happened to come across an old post of mine, and noticed that the code samples are mangled, with everything appearing on a single line. By trying to edit the post I see that there are linebreaks in the text, but for some reason they are ignored when the post is parsed and displayed.
SMF spam blocked by CleanTalk