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

#281
Yes, this is the correct way to solve this. The important part is that you can assign footstep sounds to your view's frames.

One caveat is that region events are not triggered during blocking walks; this is a general issue with regions that can be solved like this:

Code: ags
function region1_WalksOnto(Region *theRegion)
{
  player.ChangeView(VHOLOGRAM);
}

function region1_WalksOff(Region *theRegion)
{
  player.ChangeView(VROGER_WALK);
}

Region* prevRegion;

void repeatedly_execute_always() {
  Region* currRegion = Region.GetAtRoomXY(player.x, player.y);
  if (currRegion != prevRegion) {
    if (currRegion == region[1]) region1_WalksOnto(currRegion);
    if (prevRegion == region[1]) region1_WalksOff(currRegion);
  }
  prevRegion = currRegion;
}

This keeps cropping up from time to time, so maybe AGS4 could provide the option to always trigger region events?
#282
True, if you want the spell counters to tick down exactly from when they're cast, you need to go back to a higher frame resolution. You can in theory pick any amount of frames, like 5. It should be a divider of 40 though, so the conversion to seconds doesn't have rounding issues.

Memory is reserved whenever a new variable is declared. A single AGS int is probably a 32 bit signed integer, which means a gigabyte of RAM can hold 268.435.456 ints.
Changing an int takes up a (tiny, tiny, tiny) bit of processing time but doesn't use additional memory; it just changes the bits that were already reserved at declaration time.
It's like a massive blackboard where you wipe away a number and replace it with a different one, no additional space is needed.
#283
In general this is how you have to do it, yes.

There is room for optimization though: instead of setting the label each frame it's enough to update it each second:

Code: ags
function cd_countdown(int i) {
  //this function aims at displaying the cooldown of a spell once you've played it. (When you cast the spell,it sets Spell[i].cd to a positive value, which triggers the following codes)

  if (Spell[i].cd > 0) {
    Spell[i].cd--;
    gSpellbar.Controls[i].AsLabel.Text = String.Format("%d", Spell[i].cd + 1); //a label from the gui that appears on top,
  } else {
    Spell[i].cd = -1;
    gSpellbar.Controls[i].AsLabel.Visible = false;
  }
}

int frame_count;

function repeatedly_execute() {

  frame_count++;

  if (frame_count == GetGameSpeed()) {
    frame_count = 0;
    // the following runs once per second
    for (int j = 0; j < 10; j++) {
      cd_countdown(j);
    }
  }

}

Also, this is not really a waste of memory, especially since all variables are already declared. No new memory is reserved here, let alone each frame.
#284
@Snarky leaving aside AGS's quirks, I'm reading the OP as "if I use < instead of <= my code breaks" and given there's no further explanation I don't really know which problem to address in the first place.
#285
Not sure what your point is here? Or question?

If you skip over the last item and you have two inv items in your game, then the second item is not added if you skip over it, yes.

< and <= are two different things that make code behave differently.

When you loop over an array which is zero based, you typically do:
Code: ags
  for (int i = 0; i < length_of_array; i++)
edit: for an array of size 5, this runs the code inside the loop 5 times, with i being 0, 1, 2, 3 and 4.

In the case of the inventory items array, which for some weird reason is one based, you need to start at 1 instead of 0 and consequently count up until length, not length - 1, therefore:
Code: ags
  for (int i = 1; i <= Game.InventoryItemCount; i++)
edit: for an inventory count of 5, this runs the code inside the loop 5 times, with i being 1, 2, 3, 4 and 5.
#286
That template is very old and I'm not sure how much use it'll be.

Typing a paragraph of text is possible but requires some programming. It's easier if the user cannot move the cursor i.e. just backspace typos.
Adjusting the font size is also possible if you draw the text to a dynamic sprite but requires importing a font a various sizes beforehand.

GUI labels support line breaks, so you need code that listens to keypresses and appends the character to a label.
This can be handled with a flag or GUI visibility check indicating to on_key_press that the label is currently visible and any keypress should be directed there.

Like this:

Code: ags
function handleParser(eKeyCode k) {
  lblParser.Text = String.Format("%s%c", lblParser.Text, k); // not a full solution
}

function on_key_press(eKeyCode k) {

  if (gParser.Visible) {
    handleParser(k);  
    return;
  }

  // existing key handling here
}
#287
Just to put it online somewhere, mega.nz offers 50GB for free and you'll get 17GB with a gmail account, 5GB with a Microsoft one.

You can also try upping the compression level a bit to get under the 2GB threshold.
#288
Add a new script module, then put this as the header:

Code: ags
struct Draggable {
  import static void Activate(Label* label);
};

and this in the main script:
Code: ags
Label* labels[100];
int label_count;

static void Draggable::Activate(Label* label) {
  labels[label_count] = label;
  label_count++;
}

GUI* theGUI;
bool dragging;
int ox, oy;

void on_event(EventType event, int data) {
  
  int mx = mouse.x, my = mouse.y;
  
  if (event == eEventGUIMouseDown) {
    GUIControl* gc = GUIControl.GetAtScreenXY(mx, my);
    if (gc) {
      Label* lbl = gc.AsLabel;
      for (int i = 0; i < label_count; i++) {
        if (labels[i] == lbl) {
          theGUI = lbl.OwningGUI;
          dragging = true;
          ox = mx - theGUI.X;
          oy = my - theGUI.Y;
        }
      }
    }
  }
  if (event == eEventGUIMouseUp) {
    if (dragging) dragging = false;
  }
  
}

void repeatedly_execute_always() {
  if (dragging) {
    theGUI.X = mouse.x - ox;
    theGUI.Y = mouse.y - oy;
  }
}

Now put a label at the top of the GUI (this acts as handle) and call
Code: ags
  Draggable.Activate(lblDragMe);
passing the label in a suitable place like game_start or the first room's room_Load.
#289
Quote from: Jordanowen42 on Sat 29/06/2024 06:28:33I downloaded it and it only has an option to convert to .ogg not .ogv

The option is called "Video - Theora and Vorbis (OGG)" and creates a video file. .ogg doesn't mean it's just audio.
You can simply rename it after the conversion, if you want the extension to be .ogv.
#290
You can also use VLC to convert video; it has a good and simple GUI for that.
(It also seems to use the same library as ffmpeg, so the result will be just as good.)

https://www.videolan.org/
#291
Look at 0:07 and compare that to 0:23.
It's very visibly a different position.

I assume 340, 140 is where the player is at 0:23, so the question is why they don't reach that coordinate the first time around.
#292
Well, the entire thing depends on
Code: ags
if (Verbs.MovePlayer(340, 140)) {
so if that fails, (edited for clarity:) the player walks towards these coordinates but then can't reach them and they stop and nothing happens.

The question is, why does it fail from one side and not the other? And does the function itself have a bug?
Make sure that 340, 140 is part of the walkable area and also not blocked by the NPC's solidity rectangle.
#293
Having button images change upon hovering is a) not what OP is looking for here afaik b) built-in

You need something like this:

Code: ags
  // inside repeatedly_execute

  // default value is name of hotspot / object / character under cursor
  String ln = Game.GetLocationName(mouse.x, mouse.y);

  GUIControl* gc = GUIControl.GetAtScreenXY(mouse.x, mouse.y);
  // if mouse is over button, change text to button description
  if (gc == btnScissors) ln = "scissors";
  if (gc == btnThread) ln = "thread";
  ...

  // set label text
  lblDescription.Text = ln;
#294
Like this:

Code: ags
function cLupo_AnyClick() {
    if (Verbs.MovePlayer(340, 140)) {
        Display("Move player finished");
        player.FaceDirection(eDirectionRight);
        // WALK TO
        if (Verbs.UsedAction(eGA_WalkTo)) {
            Display("action is walk");
            Verbs.GoTo();
        }
        // GIVE TO (characters only)
        else if (Verbs.UsedAction(eGA_GiveTo)) {
            Display("action is give");
            if (player.ActiveInventory == iObject) {
                player.LoseInventory(iObject);
                player.Say("do you want this?");
                cLupo.Say("WOW! YES. I want it");
            } else if (player.ActiveInventory != iObject) {
                player.Say("do you want this?");
                cLupo.Say("No");
            }
        }
    }
}
#295
Try adding Display() commands to see exactly what is happening.

You can also try removing the eGA_WalkTo branch since your moving the player to the character manually anyway.
#296
GUIs are global objects so you can access them from inside a room script no problem.

Just put
Code: ags
  gBasket.Visible = true;
in your interaction function.

Hotspot hovering means you need to add GUI buttons to the code that displays them. Which template / module are you using?



Side note: to upload screen shots, first check the global on_key_press function for an existing F12 line. Some templates have this built-in. Press F12 during the game (when the interface isn't blocked) and AGS saves a screenshot to the save game folder. Usually C:\Windows\Users\[Username]\Saved Games\[Name of Game]

Next, upload this image to a host that supports hotlinking. After the upload, right-click the image and select "copy image location" or similar.

Finally, paste the url into your post and surround it with tags:
Code: bb
[img width=640]https://i.ibb.co/x7PzjGp/IMG-6064.jpg[/img]

#297
Yeah, it's the same for me. Chrome is showing me an HTTP 503 error.
#298
I don't have time to debug this right now, just wanted to point out something:

Code: ags
  Lblinfo.Text = String.Format("%s", skill[u].Description);

can be written as

Code: ags
  Lblinfo.Text = skill[u].Description;
#299
I'd use a custom say function to handle the coordinates. Like this:

Code: ags
function DSay(this Character*, String message) {
  int x = 483;
  int y = 225;
  if (this != player) { x = 454; y = 74; }
  this.SayAt(x, y, 100, message);
}
#300
You cannot use built-in inventory items for this. You need an array of strings instead:

Code: ags
String inv_item[100]; // array
int inv_count;  // count size

// add new string to array
function AddItem(String name) {
  if (inv_count == 100) { Display("Inv item limit reached!"); return; }
  inv_item[inv_count] = name;
  inv_count++;
}
SMF spam blocked by CleanTalk