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

#241
Since this is a new question, unrelated to your previous one, I have split it into a new thread.

Do you mean that instead of having the option to manually save the game in multiple slots, there should only be a single savegame, and that the game should autosave its state, and that the next time the game starts after quitting, it should automatically continue from that save, so that players never have to (and can't) manually save/restore?

You kind of just have to... do it.

-Remove the code that lets players bring up the save and load menus
-Pick a savegame slot that will be your autosave
-Make sure to save to this slot at suitable times, e.g. when the player enters a room, when a conversation ends, and of course, when quitting
-From the main game menu, have a "continue" option that loads the savegame

That's the basic idea. Then you can add some polish (e.g. to make sure that when you load, you don't bring up the "quit?" menu straight away just because that was your last autosave).
#242
And I.

Wordle 592 2/6*

🟩🟨⬜⬜⬜
🟩🟩🟩🟩🟩
#243
All right, glad you got it to work!
#244
Typically this problem is caused by not setting the item dimension properties for the inventory, so that the actual "clickable" part of the items is only a small corner of the sprite.

Another possibility is that a different, invisible GUI is covering up your inventory GUI.

A third possibility is an AGS bug that was discovered today, if you are calling SayBackground() from repeatedly_execute() (or any of that family of functions).
#245
Quote from: Ali on Sun 29/01/2023 00:02:28I really enjoyed the 1975 film adaptation, called Death at an Old Mansion in English. The title is particularly enjoyable, because that's the premise of every whodunit.

Nice! Maybe I'll try to find it, if only to check out the scruffy bohemian stammering detective.

The book explains that a "honjin" in olden times was a family mansion used as a place for the nobility to stay during official travelâ€"i.e. a very exclusive innâ€"and that families running this kind of establishment were a privileged class, a kind of gentry. So "Old Mansion" is a pretty literal translation into English.

… Although weirdly enough, (at least in the book) the deaths do not in fact take place in a former honjin, the family in question having sold theirs several generations ago and moved to a new homeâ€"though they still jealously guard their status as an historical honjin family.

Quote from: Ali on Sun 29/01/2023 00:02:28It's a little plodding, but I suspect that the solution is one of those explanations that are more plausible when you see it happening. That said, the whole concept of a locked room mystery is somewhat different in a country where walls can be made of paper.

Yeah, I can imagine that the solution would play better when you can see it. The written explanation is ludicrously complex and hard both to visualize and believe.

Spoiler
And I don't know if it's meant to be self-deprecating or what, but early on in the book, the detective criticizes just this kind of locked-room solution, saying he finds it disappointing and is "totally unimpressed" by it.
[close]
#246
I watched Park Chan-Wook's Decision to Leave this week.


It's more of a psychological thriller (with strong echoes of Vertigo and Basic Instinct) than a whodunnit, but there are some fun investigative twists, and I enjoyed it. The combination of very stylized noir and quirky comedy reminded me a little of the Coen brothers.

I've also checked out the first couple of episodes of Rian Johnson's Poker Face, the Columbo-esque "inverted mystery" series with Natasha Lyonne. I'm not entirely sold yet: her gimmick is that she can immediately tell when someone is lying, and since she's not a detective who has to provide any evidence for her conclusions, it renders the investigations pretty trivial, so far. I've heard the next two episodes are better, so I'll give it another chance.

And I recently read Seishi Yokomizo's The Honjin Murders (1946), a classic Japanese locked-room mystery recently available in English. I found it more interesting for its portrayal of Japanese society before and after WWII (the main narrative takes place in 1937, with a frame story set right after the war) than for the mystery itself, which is convoluted and strained.
#247
Annoying...

Wordle 585 6/6*

⬜⬜🟨⬜🟩
🟨⬜⬜⬜🟩
⬜🟩⬜⬜🟩
🟩🟩⬜⬜🟩
🟩🟩⬜⬜🟩
🟩🟩🟩🟩🟩
#248
Quote from: boosterterrik on Tue 24/01/2023 14:02:11The documentation for AGS is both very extensive and well-written in places, while being aggravatingly sparse in others.

I think it's mainly that AGS itself is too complex and too inconsistent, with too many features interacting. That's because it's been gradually added to over 25 years, and there probably hasn't been enough streamlining and clearing away of old, unnecessary stuff.

That said, if you report things missing in the manual, it can be updated without much difficulty.

Quote from: boosterterrik on Tue 24/01/2023 14:02:11I feel like I need a long weekend with the manual

Yeah, I think anyone serious about AGS should read through the manual front-to-back at least once. It's not that long. And in older version (up to AGS 3.3) you could browse through all the script APIs in the TOC menu on the left.
#249
In cases like this, I would first check that it works in the simpler case where you use a blocking animation to interrupt the idle animation. That way we can be more confident that there isn't some other part of the code messing things up.

So I start by confirming that it works with this code (where the animations are called V_IDLE and V_INTERRUPT, respectively—it's better to name the views than to just refer to them by number):

Code: ags
function room_AfterFadeIn()
{
  cLeBlanc.SetIdleView(V_IDLE, 1);
  SetTimer(1, GetGameSpeed()*12);
}

function room_RepExec()
{
  if(IsTimerExpired(1))
  {
    cLeBlanc.LockView(V_INTERRUPT);
    cLeBlanc.Animate(0, 4, eOnce, eBlock);
    cLeBlanc.UnlockView();
    SetTimer(1, GetGameSpeed()*12);
  }
}

And yup, that works.

Given that it works in principle, we now need to make it work with a non-blocking animation. In that case, we have to hold off on doing the UnlockView() and SetTimer() until the animation has finished. How do we do that? Well, let's try to keep checking in room_RepExec() to see if the animation has stopped:

Code: ags
function room_RepExec()
{
  if(IsTimerExpired(1))
  {
    cLeBlanc.LockView(V_INTERRUPT);
    cLeBlanc.Animate(0, 4, eOnce, eNoBlock);
  }
  else if(!cLeBlanc.Animating)
  {
    cLeBlanc.UnlockView();
    SetTimer(1, GetGameSpeed()*12);
  }
}

What happens when we run this? We see immediately that the idle animation stops playing altogether: something has gone wrong. With a little consideration, we should see that this new "else if(!cLeBlanc.Animating)" test will be true before the idle animation starts playing, so we keep calling UnlockView() over and over each game loop. Apparently this resets the idle counter, so the idle animation never triggers. (Edit: And it also keeps resetting the timer, so that it will never time out and trigger the interrupt animation. So we're left with... nothing happening.)

(And actually, there's an undocumented quirk in AGS here: Character.Animating will be false even when the idle animation is playing; it "doesn't count." I believe it's only animations specifically triggered by Character.Animate() that set Character.Animating true, though I'm not sure about Talking and Walking animations.)

How can we fix that? Simple: by making sure we only run this chunk of code when the view is set to V_INTERRUPT, because that must mean it has just finished playing the V_INTERRUPT animation specifically (as long as V_INTERRUPT != any of the other views used by cLeBlanc, such as the NormalView, IdleView, SpeechView if used, etc.):

Code: ags
function room_RepExec()
{
  if(IsTimerExpired(1))
  {
    cLeBlanc.LockView(V_INTERRUPT);
    cLeBlanc.Animate(0, 4, eOnce, eNoBlock);
  }
  else if(cLeBlanc.View == V_INTERRUPT && !cLeBlanc.Animating)
  {
    cLeBlanc.UnlockView();
    SetTimer(1, GetGameSpeed()*12);
  }
}

And now it works.
#250
In the top version, this code never runs at all:

Code: ags
 if (IsTimerExpired(1)){
  cLeblanc.LockView(12);
  cLeblanc.Animate(0, 4, eOnce, eNoBlock);
  cLeblanc.UnlockView();
  cLeblanc.SetIdleView(13, 3);
  }

Because at the time the function runs, the timer is not expired, so the test is false. Therefore the view 12 animation is not played, and the idle view is not set, which is why that never plays.

I think your original code was close to correct; I'd just lose the else clause and simply set the idle view once, in room_AfterFadeIn(). I don't believe you need to set it again after the animation ends, and you certainly don't need to set it every game loop; that is presumably why it wouldn't play, because the timeout got reset each time you set it. (If you want the View 12 animation to play repeatedly, though, with the idle animation in between, you need to set the timer again once it has expired.)

Quote from: boosterterrik on Mon 23/01/2023 17:49:09My core question is: should I be using timers set in the global script instead of the Room script for this sort of thing?

No, there's no reason to do that. You can do it just as well in the Room script, and AFAICT from the snippets posted, that is where it belongs.
#251
BTW, the way you're doing the timer is rather more complicated than necessary.

1. Rather than keeping two separate code branches just to add a 0 when the seconds-counter is in single digits, you can use the automatic 0-padding formatting style:

Code: ags
// This will always display sec with two digits
TimerText = String.Format("%d:%02d", min, sec);

2. It would be a lot easier to not keep track of the minutes and seconds separately, but only the actual remaining time, and just convert it into minute and second parts for display:

Code: ags
int totalSec;

function room_load()
{
  int totalSec = 2*60 + 15;
  // ...
}

function repeatedly_execute_always()
{
  // ...
  // Divide by 60 to give the number of minutes,
  // take the remainder to give just seconds within the minute
  TimerText = String.Format("%d:%02d", totalSec/60, totalSec % 60);
}

Then you don't need all the logic for when the minute changes; you only need to test whether the total countdown has reached the end.

3. If you're already keeping manual countdown variables, you don't really need timers at all. At most a single timer to give you a "tick" per second, just for convenience.

So taken all together, the timer code can be simplified to:

Code: ags
// room script file

int totalSec;

function room_Load()
{
  totalSec = 1*60 + 30;
  SetTimer(1, GetGameSpeed());  // set "seconds tick" Timer
}

function repeatedly_execute_always()
{
  // This runs once every second while timeout displayed
  if (IsTimerExpired(1))
  {
    if (totalSec > 0)
      cTimer.SayBackground("%d:02d", totalSec/60, totalSec%60);
    else
      cTimer.SayBackground("0:00");
    if (totalSec == 0)
      DisplayAtY(10, "Crap, what is... Feels like I'm falling.");

    totalSec--; // Count down our timer
    // How long we keep re-displaying 0:00 after the timeout has ended
    // (the time for DisplayAtY to time out comes on top of this)
    if (totalSec > -5)
      SetTimer(1, GetGameSpeed());
  }
}
#252
Your first issue could have to do with the General Setting "When player interface is disabled, GUIs should...", if that differs between your test game and real game. Try making sure that it is set to "display normally."

Your second issue, if I understand it correctly (it should display a label over your inventory), might have to do with the z-order of the GUIs. Check that gInvLabel.ZOrder is set to a higher value than that of the inventory GUI itself, or it will be displayed behind it.
#253
I would say it does not matter what the rule for sorting between things with the same z-order is, since as already mentioned it is arbitrary. There is no "right" or "expected" way to sort them, and it's not even important that the sorting is predictable. The only "problem" we might want to solve is flickering (i.e. that the sorting is not stable). So any hard-coded ordering between different types, for example, is fine.

As for overlays, they are always explicitly created with a given z-order, right? In that case, I don't think it's even much of a priority to ensure stable sorting at all: just let the game maker be responsible for ensuring that two of them don't have the same z-order.

To put it succinctly: the way for a game maker to control the order of drawing between different things is the z-order. If two things are given the same z-order, it's up to the engine to decide, based on whatever it likes.
#254
Quote from: Crimson Wizard on Thu 19/01/2023 09:28:47Whether this has to be changed or not is arguable, but "fixing" this may only be done if the mentioned problem is resolved; and definitely not in 3.6.0, because we're done making significant changes in it.

Since the draw order really is undefined when two things have the same z-order value (by definition), any ordering will be inherently arbitrary. Though I suppose there is a good argument to be made that it would be better to keep it stable (sorting by ID?) to avoid flickering—especially for characters, since that's the most common case where the player can directly affect the z-order, thereby making it hard for a game maker to ensure that two of them don't have the same value.
#255
The Rumpus Room / Re: *Guess the Movie Title*
Thu 19/01/2023 07:03:13
(Hey @Mandle, your turn.)
#256
Quote from: boosterterrik on Thu 19/01/2023 01:35:27On a side note though, as I am brand new to this, how are you getting blocks of code into the forum to look like that?

Tip: to see how to get a certain effect in a forum post, just try quoting a post that does it. In this case, it's:

[code=ags][/code]
#257
Quote from: boosterterrik on Wed 18/01/2023 20:43:32The other issue is that I am doing this for work, am not a coder, but am the only one willing to learn. Feels like half my time these days is spent reading documentation and trying to wrap my head around concepts that are likely simplistic to those with more experience.

BTW, a job that forces reluctant employees to write AGS code? That sounds cruel and very unusual.
#258
Quote from: boosterterrik on Wed 18/01/2023 20:43:32I have checked every instance within the documentation of idle animations, and I have found no places to make changes to how quickly idle animations trigger. There's the frame-delay on idle animation, but that won't make characters not stand completely still for ~15 sec between idle animations (one character, for instance, is holding a lit cigarette).

It's not the most intuitive API, but Character.SetIdleView() has a delay parameter that allows you to set the time of inactivity before idle animations are triggered.

If you want to have a variety of "idle" animations triggering without any discernible patterns, one way is to use a timer with a random delay, and then pick an animation at random from a selection of animations. You can also combine this with a continuous "rest" animation (whether that's breathing, fidgeting, swaying, or what-have-you) that runs at all other times.

But this is a more "programmer-y" way of approaching the issue. Certainly, just creating a very long animation loop should also work. Did you have a chance to do the test I suggested to see whether it's the particular animation loop that causes the crash, or the combination of all the animations?
#259
The first thing I would try is to comment out the first five characters, to check whether there's something wrong with this particluar animation, or if it's something about the total number of (very long) simultaneous animations (which could be an AGS limitation, perhaps something to do with having to load all of them into memory).

Edit: I would also be curious about whether this approach is actually necessary. What do you mean "idle animations are triggered too slowly"? You can set how quickly they trigger. Also, do the animations really need to be so long? Are you for example adding the same frame multiple times to add a delay, or something like that?
#260
Yeah, I was also chary of going with it, on grounds of it being too rare. If I hadn't already eliminated the last letter, I would sooner have guessed

Spoiler
CHARY (cautious, hesitant, reluctant, suspicious (laugh) )
[close]
... which itself is not a particularly common word.
SMF spam blocked by CleanTalk