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

#221
Hi,

there's AGS Demo Quest, which you can find here: https://github.com/adventuregamestudio/ags-demo-quest

Note that looking at a bunch of code is probably not that useful to a beginner, I'd start with the tutorial in the manual, which can be found here: https://adventuregamestudio.github.io/ags-manual/StartingOff.html
#222
(This answer is regarding game design with respect to save games, not addressing the technical implementation, so feel free to ignore it)

I'm wondering how suitable this approach is in general. Typically, three save slots are used for games that auto-save progress but want to allow up to three people to play simultaneously.
Since that isn't the case here, you're instead limiting the player to three slots instead of the usual hundred or so. Whether this makes sense depends entirely on the game though, i.e. whether it has story-affecting choices and/or dead ends. If yes, the limit of three seems much too small. If no, you don't really need more than one slot.

TL;DR: I can't think of any scenario in which three save slots really make sense (with the exception maybe of knowing in advance that there's going to be some epic part of the game which you want to re-play through again later).
#223
Quote from: Sakspapir on Mon 20/03/2023 23:01:31I'm wondering how reliable the above mentioned function is.

Couldn't you simply try it with a, say, two minute audio file? Schedule something for a specific position near the end and see what happens? That should be quicker than us guessing around, and I'd also guess that if the function isn't perfectly reliable, it's not something that can be fixed in the engine code easily because otherwise it would've been implemented like that already.

Looking for solutions or alternatives only makes sense once it's established that the function isn't reliable.
#224
I don't see any reason why you should deviate from an actual inventory window; sticking to that will make things way easier.

I'd use the 1 column inv window as CW suggested, then use dynamically drawn sprites for the inventory items (and put the image on the left, then a wrapped description next to it).

IIRC there was a relatively recent thread where I did this exact thing, let me try and find it.
#225
You can also use an even shorter way:
Code: ags
  mouse.Visible = mouse.x > 480 && mouse.x < 1101;

However a much better way to solve this is to use  Mouse.SetBounds(); this way the user doesn't suddenly "lose" their mouse.
#226
emini: try sending him a PM maybe :)

Re the code, this:
Code: ags
// Create a Quest
createQuest("Get Ready for Work", "You need to get ready to go to the office. Don't be late!");

// Assign three Tasks to Quest 1
createTask("Get Ready for Work", "Get Dressed");
createTask("Get Ready for Work", "Eat Breakfast");
createTask("Get Ready for Work", "Drink Coffee");
seems pretty redundant, I'd store the quest name in a temporary variable and use that to assign the tasks.
#227
Mostly unrelated, but remember that you should usually use the LockView command before animating.
#228
Afaik overriding built-in inventory click handling is only necessary for handling eMouseLeftInv and eMouseRightInv inside on_mouse_click, but this is about detecting a click on an empty spot of the inv window, which requires on_event code instead.

So the code should work without overriding it.
Can you do some debugging? As in: add Display calls to see which parts run and which ones don't.

Like
Code: ags
  if (event == eEventGUIMouseDown && data == gIconbar.ID) {
    int mx = mouse.x, my = mouse.y;
    bool leftButton = mouse.IsButtonDown(eMouseLeft);
    Display("click on iconbar");
    if (GUIControl.GetAtScreenXY(mx, my) == InventoryWindow1) {
      Display("click on inv window");
      if (InventoryItem.GetAtScreenXY(mx, my) == null) {
        Display("click on empty spot");
        if (leftButton) {
          Display("left button was used");
          cGoby.ActiveInventory = null;
        }
      }
    }
  }

Edit: I tested the above code and it works as it should. The only remaining issue is a cosmetic one: hovering over the top bar with an active inventory item will change the mouse cursor  back to the pointer sprite. Which makes sense for the buttons on the right but not the "place item back into inventory" part.

Btw: I've noticed you've set GUI 7 as text window, but there is no GUI 7, therefore calling Display() causes a crash. Replace the 7 with a 0 in General settings -> Text display to use the default box.
#229
Matti, your code should cause an error / cause unwanted behavior if you right-click on an empty part without an active inventory item. Probably an array out of bounds error since game.inv_activated should be -1(?).

The fact that you never got an error seems to support that your code doesn't run when an empty part of the inv window is clicked (which is how AGS has always behaved, afaik).
#230
You can also write functions for this:
Code: ags
String _message[20];
int _message_count;

void Add(String message) {
  _message[_message_count] = message;
  _message_count++;
}

void Clear() {
  _message_count = 0;
}

void SayRandom(this Character*) {
  if (_message_count == 0) return;
  this.Say(message[Random(_message_count - 1)]);
}

Now you can do:
Code: ags
function region1_WalksOnto()
{
  Clear();
  Add("Nope, I can't stand salty water.");
  Add("I don't want wet feet!");
  Add("Not going to ruin my shoes man...");
  Add("No way, what if there are sharks?");
  Add("Hmmm, I don't think I can swim...");
  player.SayRandom();
}

edit: code fixed
#231
I'm not seeing my code in there?
#232
Detecting a click on an empty part of an InvWindow should work like this:

Code: ags
MouseButton button;

function on_event(EventType event, int data) {
  
  if ((event == eEventGUIMouseDown || eEventGUIMouseUp) && data == gInventoryBar.ID) {
    if (event == eEventGUIMouseDown) {
      for (int i = eMouseLeft; i <= eMouseMiddle; i++) if (Mouse.IsButtonDown(i)) button = i;
    }

    if (event == eEventGUIMouseUp && button == eMouseLeft) {
      int mx = mouse.x, my = mouse.y;
      GUIControl *gc = GUIControl.GetAtScreenXY(mx, my);
      if (gc == null) return;
      InvWindow* iw = gc.AsInvWindow;
      if (iw == null) return;
      InventoryItem* ii = InventoryItem.GetAtScreenXY(mx, my);
      if (ii == null) {
        // player clicked on empty part of inv window
        player.ActiveInventory = null;
      }
    }
  }
}
#233


1. right-click the image and click "copy image location" to get the URL
2. put the image in your post like this:
Code: bbcode
[img width=300]https://i.imgur.com/lpeCi9x.png[/img]

Also note that you can auto-generate the button images using scripting; there's no need to manually create 26 images :)
#234
"i.e." is an expression meaning "in other words", it was not part of the code obviously  :-D

And eModeSomeMode was a fictional generic mode illustrating you were supposed to use the mode from the Room Click command.

Anyway, using an inventory item with a hotspot works fine for me (I guess that's what you meant?) but one should probably insert a ClaimEvent() at certain places into do_room_action to prevent the click from also triggering the GotThere code.

For instance if you have an active inventory item, the mouse is over a hotspot and you right-click, what's supposed to happen? Should that always deselect the inv item, then do nothing further? Or still trigger a look at?
#235
I managed to find a solution for this that so far, seems to work:

1. Move TwoClickHandler above the GotThere module in the script tree (drag and drop the former on the latter)

2. Open the GotThere script and change the first line (31) of on_mouse_click to
Code: ags
  if (button == eMouseLeft || button == eMouseRight) {

3. Open the TwoClickHandler script and find the do_room_action function's first and main if block. In there, whenever it says Room.ProcessClick(mouse.x, mouse.y, eModeSomeMode);, replace that with just setting the mode instead, i.e. mouse.Mode = eModeSomeMode; (should be lines 126, 131 and 139).

4. Assign a cursor image to the interact and look cursors.


What happens is the BASS code now only changes the mode according to the type of click, but the actual click is now processed by GotThere. I haven't tested it thoroughly though.
#236
The problem with the BASS template is that it doesn't rely on cursor modes, it calls the correct interaction based on what was clicked and the button that was used.
My module was built for the Sierra template, i.e. is completely based on cursor modes. It should be relatively simply to re-write for the BASS interface. Or to amend the BASS code to use the actual cursor modes.
#237
You need to actually link your button to the function: open the button's events pane (thunderbolt icon) and paste btnConfirmSave_OnClick into the 2nd column.

(Debe vincular su botón a la función: abra el panel de eventos del botón (icono de rayo) y pegue btnConfirmSave_OnClick en la segunda columna.)
#238
Yeah, I did the same test and noticed that the BASS template uses the walk-to cursor for everything for some reason. The mode used doesn't matter for the BASS code but the GotThere module relies on a proper cursor mode being used.
The solution is to simply run mouse.Mode = eModeInteract; in game_start.
#239
I rewrote the module to make it easier to use; since I kept updating the Google Drive file which to my knowledge retains the share link, you've probably ended up with the latest version but outdated instructions.

Here's the latest thread:
https://www.adventuregamestudio.co.uk/forums/beginners-technical-questions/graphicalfunctional-questions-for-cmi-style-guiinventorymenus/msg636639852/#msg636639852

In short you need:
Code: ags
  if (WalkFace(123, 45, eDirectionLeft)) {
    // what happens when the player reachers those coordinates goes in here
  }

eri0o: the module doesn't just check for a character's position, it also runs the interaction as soon as they arrive at the target coordinates.
#240
Calling the text property "book-one" doesn't make much sense, it should be something like "label" or "dynamic name".

Anyway, assuming that you're using the default "@OVERHOTSPOT@" as the label text, you need to set it manually in repeatedly_execute:

Code: ags
  int lt = GetLocationType(mouse.x, mouse.y);
  String labelText = Game.GetLocationName(mouse.x, mouse.y), dynName;
  if (lt == eLocationHotspot) {
    Hotspot *h = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
    dynName = h.GetTextProperty("label");
  }
  if (lt == eLocationObject) {
    Object *o = Object.GetAtScreenXY(mouse.x, mouse.y);
    dynName = o.GetTextProperty("label");
  }
  if (lt == eLocationCharacter) {
    Character *c = Character.GetAtScreenXY(mouse.x, mouse.y);
    dynName = c.GetTextProperty("label");
  }
  if (dynName.Length > 0) labelText = dynName;
  lblStatusBar.Text = labelText;

Also, line 2 from your snippet is completely pointless.
SMF spam blocked by CleanTalk