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 - Snarky

#61
You could still hardcode what character ActiveInventory is set for, and which character's ActiveInventory events check for, but I suppose it wouldn't update the mouse cursor if that character isn't currently player.
#62
The easiest solution is to set InvWindow.CharacterToUse to one of the characters, and write the code to always refer to that character's inventory. Then it won't matter which character is currently set as player, you'll be using the same inventory regardless.
#63
I think making COLOR_TRANSPARENT clear the part it is drawing on is probably OK. If you're constructing the color value manually it might mean you have to add a separate check to make sure you're not inadvertently wiping out part of the sprite, but that's easy to add, and people who are calculating color values probably have a good idea of what they're doing.

As for adding another API to overwrite without blending, I don't think I've ever experienced a need for it, but maybe it might come in useful. I suggest DrawingSurface.Clear...() (ClearCircle, ClearLine, ClearRectangle, ClearTriangle, ClearPixel, and possibly ClearString), to work consistently with the existing DrawingSurface.Clear().
#64
There isn't a lot of comfort I can offer other than sending best wishes and hopes. Things are fucked.
#65
You could take a look at the Clipboard plugin, which also has to do the conversion to and from AGS strings. (Though note that it has not been updated to support Unicode strings.)

https://github.com/messengerbag/Clipboard

The important bits are:

Code: C
const char *ourScriptHeader =
"#define CLIPBOARD_PLUGIN\r\n"
"#define CLIPBOARD_PLUGIN_VERSION 0.04\r\n"
"/// Methods to access the Windows clipboard (via AGS Clipboard Plugin)\r\n"
"builtin struct Clipboard {\r\n"
"  /// Paste a String from the clipboard. Returns null if not available\r\n"
"  import static String PasteText ();\r\n"
"  /// Copy a String to the clipboard. Returns true if successful\r\n"
"  import static bool CopyText (String copyString);\r\n"
"};\r\n";

const char* Clipboard_PasteText(void) {
	HGLOBAL   hglb;
	LPTSTR    lptstr;
	const char* pasteString = nullptr;

	if (!IsClipboardFormatAvailable(CF_TEXT))
		return nullptr;
	if (!OpenClipboard(engine->GetWindowHandle()))
		return nullptr;

	hglb = GetClipboardData(CF_TEXT);
	if (hglb != nullptr)
	{
		lptstr = reinterpret_cast<LPTSTR>(GlobalLock(hglb));
		if (lptstr != nullptr)
		{
			pasteString = engine->CreateScriptString(lptstr);
			GlobalUnlock(hglb);
		}
	}
	CloseClipboard();

	return pasteString;
}

void AGS_EngineStartup(IAGSEngine *lpEngine) {
	engine = lpEngine;

	// Make sure it's got the version with the features we need
	if (engine->version < 3) {
		engine->AbortGame("Engine interface is too old, need newer version of AGS.");
	}

	engine->RegisterScriptFunction("Clipboard::PasteText", Clipboard_PasteText);
	engine->RegisterScriptFunction("Clipboard::CopyText^1", Clipboard_CopyText);
}

This adds this header to AGS, and hooks up the methods (I've omitted Clipboard.CopyText) to the corresponding plugin functions:

Code: ags
#define CLIPBOARD_PLUGIN
#define CLIPBOARD_PLUGIN_VERSION 0.04
/// Methods to access the Windows clipboard (via AGS Clipboard Plugin)
builtin struct Clipboard {
  /// Paste a String from the clipboard. Returns null if not available
  import static String PasteText ();
  /// Copy a String to the clipboard. Returns true if successful
  import static bool CopyText (String copyString);
};
#66
My impression is that there are still enough people using versions older than 3.6 that it's worth supporting at least 3.5.x as long as it doesn't require any major changes to the code. (A typical example of a trivial change would be the change from System.Viewport to Camera.)

But it's probably even more important to be forward-compatible, so definitely make sure to test it with the newest 3.x RC and also if possible with AGS 4.0.
#67
It's a crying shame; he was only 59. Cancer, reportedly.

He spent years in a kind of early semi-retirement from the games and music industries in Madagascar (I think he worked with gems or something), and then when the rights to the Dune soundtrack finally reverted to him last year he began remixing, rerecording and re-releasing his old music and even started composing again. He talked about putting out an album of new music, his first in decades.
#68
It depends.

Ideally you want it to work with all versions of AGS. It's possible to use #ifdef version checks to adapt to differences between versions.

In practice, worrying about anything below 3.3 is a waste of time, and anything below 3.5 is probably pretty niche. But if you can, why not?

But sometimes the code depends on a feature introduced in a certain AGS version, and in that case it makes sense to make that the lowest supported version. Or if some major part has changed, perhaps it is better to release separate versions of the module for different AGS versions.

I would recommend writing the module for the AGS version you use, and then once it is done, try to test it with the lowest AGS version you're looking to support, as well as the latest RC. Then make any fixes as necessary.
#69
I will not visit the US under its current regime. I would be OK with Canada.
#70
Quote from: Kara Jo Kalinowski on Tue 11/02/2025 19:18:58Yes, I did, and it worked. Your solution wouldn't work - both horizontal and vertical walk speed need to change to the same amounts depending on which direction you are facing since you don't walk in purely straight lines i.e. you will still be moving left or right sometimes even when facing down. (I was thinking the same as you at first and it doesn't work.)

Ah, I see your point. You're assuming that the x_speed and y_speed are equal in the first place? So if they are different, you would need something like:

Code: ags
function repeatedly_execute_always() 
{
    if (player.Moving) {
    switch (player.Loop) {
      case 0: //Down
      case 3: //Up
      player.AnimationSpeed = 1;
      player.SetWalkSpeed(2, 1);
      break;
      case 1: //Left
      case 2: //Right
      player.AnimationSpeed = 4;
      player.SetWalkSpeed(4, 2);
    }
  }
}

(I find it surprising that changing the AnimationSpeed (i.e. frame delay) from 1 to 4 only requires a doubling of the walk speed to remain consistent, but the logic of the frame delays always makes my head spin. I think it's that the base value is 1 loop per frame, and the delay is added to that, so that AnimationSpeed = 1 actually means it changes frame every 2 loops, and AnimationSpeed = 4 means every 5 loops—40% of the speed—but I'm not 100% sure.)
#71
Quote from: Kara Jo Kalinowski on Tue 11/02/2025 06:39:17
Code: ags
function repeatedly_execute_always() 
{
    if (player.Moving) {
    switch (player.Loop) {
      case 0: //Down
      case 3: //Up
      player.AnimationSpeed = 1;
      player.SetWalkSpeed(2, 2);
      break;
      case 1: //Left
      case 2: //Right
      player.AnimationSpeed = 4;
      player.SetWalkSpeed(4, 4);
    }
  }
}

As the arguments to SetWalkSpeed are x_speed and y_speed (which is actually the x-distance and y-distance; they have been misnamed since forever), you don't need to change them depending on whether you're moving vertically or horizontally. You can simply leave them as player.SetWalkSpeed(4,2) (or just turn off UniformMovementSpeed and set them to those values in the IDE character editor), and it will use 4 when moving horizontally and 2 when moving vertically.

What I don't have any idea of is how the distance is calculated when moving diagonally, especially if you have different x and y speeds.

Also, the manual entry for SetWalkSpeed claims: "This function CANNOT be called while the character is moving, so you must stop him first." Have you tested it to see that that's not correct?
#72
Quote from: Danvzare on Mon 10/02/2025 17:15:48A quick and dirty solution would be to set movementLinkedToAnimation to false, therefore unlinking your walking animation from the speed the character walks at.

This doesn't actually solve the fundamental problem FortressCaulfield is having: to have the animation of one pace (the animation loop) take the same amount of time whichever direction the character is walking, even though the animations don't have the same number of frames.

There are actually a lot of AGS games that suffer from this. It's especially noticeable if they have footstep sounds linked to the animation, where the rhythm changes every time the character changes direction.

Quote from: FortressCaulfield on Mon 10/02/2025 20:03:28Even putting the loops aside doesn't the char.animationspeed setting affect ALL of a char's animation?

Yes, I believe so, but you would only be changing it when the character is walking, so that doesn't really matter. But I don't know exactly what happens if you start changing Character.AnimationSpeed while the character is walking. Some experimentation would be needed.
#73
If you double the number of frames in the animation, you have to cut the animation delay in half keep the time of the animation the same, and then cut the movement distance (called "movement speed" in AGS) in half in order to keep the same walking speed.

I don't think it's possible to have different animation delays for the different loops, without the kind of custom function you talk about (and even then it is not trivial).

One possible workaround is to add each frame twice to the up/down animations. If you have movement linked to animation speed, this may introduce some gliding. If this is noticeable, you would have to modify at least the legs in the in-between frames.
#74
Quote from: FortressCaulfield on Mon 10/02/2025 11:38:59what I was really hoping for was being able to change the y align

For Characters you can use Character.z for the Y-offset. The "Scale Character sprite offsets" CW mentions should make it work when you scale it.

For Objects, you have to calculate the scaled offset yourself. That having been done, making it work with Tweens is pretty easy: Instead of TweenPosition you would use a custom Tween for both the X and Y, and each loop you add the offset to the values and set the position to the results. (Though personally I think if you're already doing this manually it's usually easier to just do the movement calculation yourself rather than tweening it.)

Object.Move won't work, but you can pretty easily script your own Move function for moving in straight lines. For moving along walkable area paths I would use a Character rather than an Object.
#75
The Rumpus Room / Re: What grinds my gears!
Mon 03/02/2025 22:50:55
When I floss, the dental floss often used to fray, and I would get fibers stuck between my teeth. Finally I found a brand where the floss wasn't made like thread, but instead a continuous strip of plastic that wouldn't fray.

I just bought a new roll of the same brand. They've changed it to the thread type.  >:(
#76
@Crimson Wizard, I can't see the image you linked. It might only be visible if you have a GitHub account and are logged in.
#77
Quote from: AGA on Wed 29/01/2025 19:09:23And @Privateer Puddin' and @Snarky also seem to be flexible?

I'm a maybe at this point. I'll be starting a new job, and I haven't figured out exactly what my vacation situation will be. Any time outside July could be difficult.

Also, whether or not the US is at war with Denmark by this summer, my enthusiasm for visiting the country is low.
#78
@Khris, the game is 16-bit, so it can't use alpha-transparent sprites.
#79
I would like to at some point, but I have no immediate plans to do so.
#80
King's Quest II+, Quest for Glory II VGA and Heroine's Quest are examples of Sierra-style AGS games with arcade sequences.
SMF spam blocked by CleanTalk