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

#21
Quote from: brushfe on Tue 27/05/2025 02:11:42Regarding the code, it sounds like Start/EndCutscene are the foundation. Is it safe to say that each cutscene could exist as its own function, and the code within bookended by Start/EndCutscene?
No, because you can change rooms during a cutscene, or have non-blocking events.
What happens at an engine level is that if the player skips a cutscene, AGS basically switches into lightspeed mode where the game runs really really fast, until it hits an EndCutscene() command. So it can be literally anywhere in your code, as long as you make sure it gets hit.
#22
One thing I've noticed:
Code: ags
  i_loop - 8*(i_loop/8) == 2
can be shortened to
Code: ags
  i_loop % 8 == 2

Anyway, it sounds like the game is using the wrong view, a view with too many frames. So you're using the correct loop and frame but a view that has more frames, and in your animation you first see the correct first X frames, then also frames X+1, X+2 which still have sprites in them from a different view.

Your code uses view_to_generate to grab the number of frames but then uses i_view to actually populate it. If these values differ, and they appear to, then the loop might end up putting the wrong number of frames in the view, i.e. less.

Edit:
Scratch that, I just saw that you are saving the generated frames using view_generate.
If I had to debug this I'd probably refactor the code into a bunch of separate functions. Using one massive function and tons of variables makes this a pain to debug.
#23
It's a single layer, so the only way to undo this is to click the undo button. If it's too late for that, I suggest using a paint program instead and importing the mask instead of painting it in the editor.
#24
Hotspots are objects, not in the AGS sense but in terms of programming. References to them are stored in pointers, declaring those requires an asterisk.

Code: ags
int a; // primitive value, initially 0
Hotspot* h; // pointer, initially pointing to null

(JavaScript is weakly typed and therefore doesn't require asterisks, every variable can store all data types.)

Regarding the general feature you're implementing, AGS already has a built-in handler for unhandled events:
https://adventuregamestudio.github.io/ags-manual/Globalfunctions_Event.html#unhandled_event

Unfortunately, there's no way to get the actual hotspot inside this function. One way to fix this is to add some lines above and inside on_mouse_click:
Code: ags
// above
LocationType _lt;
Hotspot* _h;
Object* _o;
Character* _c;

    // inside on_mouse_click / eMouseLeft in a standard template
    int x = mouse.x, y = mouse.y;
    _lt = GetLocationType(x, y);
    if (_lt == eLocationHotspot) _h = Hotspot.GetAtScreenXY(x, y); else _h = null;
    if (_lt == eLocationObject) _o = Object.GetAtScreenXY(x, y); else _o = null;
    if (_lt == eLocationCharacter) _c = Character.GetAtScreenXY(x, y); else _c = null;
    Room.ProcessClick(x, y, mouse.Mode); // this is the existing line

Now put this somewhere below the on_mouse_click function:
Code: ags
function unhandled_event(int what, int type)
{
  if (what == 1) // hotspots
  {
    if (type == 4) // TalkTo was used
    {
      Display("You can't talk to the %s.", _h.Name); // should be save to assume _h isn't null
    }
  }
}


--

You can also skip the somewhat outdated built-in function like this:
Code: ags
function Unhandled_Hotspot(Hotspot* h, CursorMode mode) {
  if (mode == eModeTalkto) Display("You can't talk to the %s.", h.Name);
}

    // on_mouse_click / eMouseLeft
    int x = mouse.x, y = mouse.y;
    if (!IsInteractionAvailable(x, y, mouse.Mode)) {
      int lt = GetLocationType(x, y);
      if (lt == eLocationHotspot) Unhandled_Hotspot(Hotspot.GetAtScreenXY(x, y), mouse.Mode);
    }
    else Room.ProcessClick(x, y, mouse.Mode);
#25
The Tumbleweed template puts the screenshots on the buttons in OptionGui.asc / CustomSave::ShowLoadDialog.
Editing that to achieve the desired look is pretty involved, so since AGS 4 supports rotated buttons, you might want to consider doing that instead.
#26
It's fine, however you can insert the image directly into the post. Right-click the image after uploading it, then click on "Copy Image Link".

Now paste that link in between img tags:
Code: bb
[img]https://i.imgur.com/mTc9pwr.jpeg[/img]

Anyway, are you using a module or template that already does display screenshots of your savegames? Are the screenshots GUI buttons? Or hotspots?
#27
I'm still confused by the idea of putting this *on top of* the text to *soften* it. Don't you mean behind it? Like with a very standard dialog box games have had for decades?
Please post an example screenshot from another game. Anything. Because now we're apparently talking about parchment or something, as opposed to something that "softens" text, whatever that means.
#28
1. create a new script by right-clicking the script node (call it SayRPG or something, up to you)
2. open its main script and move the function there (remove it where you currently have it)
3. open the new script's header and paste this:
Code: ags
import void SayRPG(this Character*, String text);
4. make sure the new script is above the KeyboardMovement script (drag it on top of it)

Still, why is your KeyboardMovement script longer than the original 221 lines, and why are calling this function in there...?
#29
I understand, but I have to point out that my method allows to easily check which room you're entering.

Like:

Code: ags
function on_event(EventType event, int data)
{
  if (event == eEventEnterRoomBeforeFadein) {
    if (data <= 2) return; // do nothing for room 1 and 2
    else if (data == 5 || data == 8) DoJumpScareTransition();
    else DoRandomTransition();
}

Note that I have again used the eEventEnterRoomBeforeFadein event as opposed to eEventLeaveRoom because I imagine the type of transition is primarily determined by the room the characters are entering, not the one they're leaving.
There's also a room event that only triggers when the room is entered for the first time, in case you don't want the jump scare to happen each time the room is visited.

I'm not sure how useful it is to learn bad stuff you'll have to unlearn later, especially in this case where doing it right isn't exactly rocket science :)
Anyway, just wanted to drop the "correct" way for reference.
#30
AGS supports vertical sliders out of the box. Just put a slider on a GUI and set/drag its dimensions so that it's taller than wide.

As for the inv item, something like this should work:

Code: ags
// created and linked to via the character's event table as usual
function cRoger_UseInv(Character *theCharacter, CursorMode mode)
{
  if (player.ActiveInventory == iMagicGearShifter) {
    gGearShifter.Visible = !gGearShifter.Visible; // toggle visibility
  }
  else {
    player.Say("..."); // reaction to other items
  }
}
#31
Just to clarify, you aren't putting that code into every single room's onLeave event, are you?
#32
You're trying to assign a number to a GUI.

You need to use
Code: ags
  gGui4Halo102.X = Speech.TextOverlay.X - 10;

As for using a different speech font for a character, the only way I know of is to change Game.SpeechFont before calling .Say() whenever that character speaks. This can also be solved best with a custom Say function.
#33
Using cCharacter.Say() means you are using character speech (as opposed to displaying text boxes for instance).

Please always post the exact code you tried to use.

This will definitely work:

Code: ags
  // in game_start
  Game.SpeechFont = eFontTheName;

Using a standard GUI to change the appearance of LucasArts style spoken text won't work because AGS moves the text away from any GUIs currently appearing on-screen.

Can you provide a quick illustration that demonstrates how you want this to appear in-game? It's most likely going to require a custom speech function, as in a function you write that is then called by AGS whenever your code uses .Say().
This function will use a graphical overlay or GUI(s) to display the custom speech you want.
#34
Right, the template code doesn't allow to insert a hotspot/object name into the string.

Use the dropdown for VerbGui.asc to navigate to Verbs::Unhandled()

Now replace the top 10 lines or so of the function up to and including "if (ii!=null) type = 4;" with this:

Code: ags
static void Verbs::Unhandled(int door_script) 
{
  InventoryItem*ii = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
  int type=0;
  if (verbsData.location_type == eLocationHotspot)   type = 1;
  if (verbsData.location_type == eLocationCharacter) type = 2;
  if (verbsData.location_type == eLocationObject)    type = 3;
  
  String locationname;
  String usedinvname;

  verbsData.location = verbsData.location_clicked;
  Verbs.RemoveExtension();
  locationname= verbsData.location;

  ShuffleUnhandled();
  for (int en = eVerbGuiUnhandledUse; en <= eVerbGuiUnhandledGive; en += 2) {
    verbsData.unhandled_strings[en] = String.Format(verbsData.unhandled_strings[en], locationname);
  }

  if (ii!=null) type = 4;
#35
This will probably require thinking about room transitions. You can completely customize those if you turn off the built-in ones (i.e. setting them to "Instant" in General Settings -> Visual).

Next, using a global event is the proper way to do this. I'd personally go with eEventEnterRoomBeforeFadein:

Code: ags
void DoRandomTransition()
{
  String videofile = String.Format("transition%d.ogv", Random(2) + 1);
  PlayVideo(videofile, eVideoSkipAnyKeyOrMouse, 10);
}

function on_event(EventType event, int data)
{
  // only do a transition for room 3 and above
  if (event == eEventEnterRoomBeforeFadein && data >= 3) DoRandomTransition();
}
#37
I found FONT.001 in an old SCI template.

https://khris.ddns.net/sierra.wfn

To use it in your game:

1. create a new font (right-click the Fonts node and click on "New Font".
2. save and close the editor
3. open the game's folder and look for the agsfntX.wfn files.
4. replace the last font (agsfnt3.wfn for me) with the properly renamed downloaded font file

2. double-click the font to open it, then click on the "Import over this font" button and pick the downloaded file
3. open the game and enjoy the new font :)

edit:
Thanks CW :-D
#38
Can you give an example of a font that didn't work?
You can also use this: https://khris.ddns.net/agsfont/

Importing a font on its own won't do anything (unless you replaced an existing font). You also need to set the font to be used by GUIs or Display / Speech commands.
#39
I haven't really used FullHD with AGS yet so I can't speak about performance. However the engine is in active development, with an official release of version 4 coming up (a major rewrite afaik).

You can download the latest Alpha here:
https://www.adventuregamestudio.co.uk/forums/ags-engine-editor-releases/ags-4-0-early-alpha-for-public-test/

I'd create a test game with a bunch of moving characters on screen. Calling Debug(4, 1); in game_start will turn on the FPS overlay.
#40
You can use a custom function like this:
Code: ags
// global header
import GiveScoreAreaA(int score);

// global script
int score_area_a;

function GiveScoreAreaA(int score) {
  GiveScore(score);
  score_area_a += score;
  if (score_area_a == 20) {
    // secret bonus code
  }
}

Now call GiveScoreAreaA(5); instead of GiveScore(5); in rooms 1-4.

However if the player always enters area B via room 5, all you really need is a suitable check in room 5:
Code: ags
// room event "first time player enters room"
function room_FirstLoad() {
  if (game.score == 20) {
    // secret bonus code
  }
}
SMF spam blocked by CleanTalk