Problem with listbox and rooms.

Started by Zrezal, Tue 21/05/2024 17:53:14

Previous topic - Next topic

Zrezal

Hello, good morning.
I am developing an engine to make text adventures. The inventory and the objects that are in each scenario I'm doing with lists and I have the following problem: how could I do so that in each room are the objects that I have not collected, and how could I do the same when I take an object from a room and leave it in another one?
My programming knowledge is limited and I don't know how I can solve this situation.

Translated with DeepL.com (free version)

Khris

This is probably a translation issue but what exactly do you mean by "lists"? Arrays?

One way is to use a struct:

Code: ags
// header
struct RoomData {
  int objectCount[100];
};

// main script
RoomData rd[50]; // 50 rooms

Dropping an object in a room:

Code: ags
  rd[player.Room].objectCount[object_number]++;

Zrezal

No, it is a problem of not having explained myself well: I have created a gui in which I have put a Listbox. In it, I put the objects that are in the scenario, but I do not know how I can do so that if the player takes an object of that particular scenario and when he returns, that the object in question does not appear again; or that if the player leaves that object in any other scenario, that this one appears listed.


Khris

#3
A listbox is a global object, so it has to be filled with the room's objects each time a room is entered.
This means you need a data structure to store the objects. I'd use the engine's inventory items for that, they already have names and IDs.

Next you need a struct array like the one I posted.
rd[2].objectCount[3] = 1 means that room #2 contains one (1) of inventory item #3.

Now you need to fill the listbox:

Code: ags
int invID[20]; // store inv item IDs for listbox items

void UpdateObjectList(int room) {
  lbObjects.Clear(); // empty list box
  for (int i = 1; i <= Game.InventoryItemCount; i++) {
    if (rd[room].objectCount[i] > 0) {
      invID[lbObjects.ItemCount] = i;
      lbObjects.AddItem(inventory[i].Name);
    }
  }
}

function on_event(EventType event, int data) {
  if (event == eEventEnterRoomBeforeFadein) UpdateObjectList(data);
}

When the player selects a listbox item, you can use invID[lbObjects.SelectedIndex] to get the inv item ID.
When the player drops an item, call rd[player.Room].objectCount[invItem.ID]++; then UpdateObjectList();.

Also:
Spoiler
If your programming knowledge is very limited, why do you want to create an engine for text adventures...?
[close]

Snarky

#4
@Khris, I think you need to pass on_event's data (presumably the room number) as a parameter to UpdateObjectList(), where it's used to access into the rd array.

Edit: fixed

Zrezal

Thank you. I will try it and let you know.


I'm doing this for entertainment and to learn something more. If I succeed, great.

Zrezal

Hello again.
Doing it with Struct is impossible for me because it fails everywhere. So I have decided to do it with files.
In them I save as information the objects that are in each room and then I list them in the listbox and it works perfectly when I load the objects so that it shows them in the label where I display the information.
The problem comes at the time of having to modify that file when I want to delete an object, it gives me an error of null referenced pointer.
I do not know what it can be.

Code: ags
  String palabra;
  File *f = File.Open("$DATA$/EObjetos/Cocina.dat", eFileRead);
  int i = 0;
  while (!f.EOF)
  {
    valores[i] = f.ReadInt();
    i++;
    palabra = String.Format("%s", f.ReadRawLineBack());
    if (palabra == objInteract)
    {
      f = File.Open("$DATA$/EObjetos/Cocina.dat", eFileAppend);
      f.WriteRawLine("  ");
    }
  }
  f.Close();

Crimson Wizard

#7
Quote from: Zrezal on Sat 25/05/2024 16:56:10The problem comes at the time of having to modify that file when I want to delete an object, it gives me an error of null referenced pointer.

You cannot write files in $DATA$ location, because that corresponds to the game package.
https://adventuregamestudio.github.io/ags-manual/File.html

If you want to write files, you will have to choose another location:
Quote$DATA$, which allows you to read files that are packaged inside the game package, originally from a directory specified in the General Settings, in the Package custom data folder(s) option, on the Compiler category. Files stored in this way can only be opened in read mode.
$INSTALLDIR$, which allows you to explicitly read files in the game installation directory.
$SAVEGAMEDIR$, which allows you to write/read files in the save game directory.
$APPDATADIR$, which allows you to write/read files to a folder on the system which is accessible by and shared by all users.

Although, I believe that in your case storing this information in variables (using structs or not) is better, because reading and writing files is slower than using variables, and also more prone to problems.

Zrezal

Thank you. The error no longer appears, but it does nothing. It does not run through the file or make any changes.

Code: ags
function writeFile()
{
  String palabra;
  File *f = File.Open("$APPDATADIR$/EObjetos/Cocina.txt", eFileAppend);
  int i = 0;
  while ((!f.EOF))
  {
    valores[i] = f.ReadInt();
    i++;
    palabra = String.Format("%s", f.ReadRawLineBack());
    if (palabra == objInteract)
    {
      f.WriteRawLine("");
      f.Close();
      break;
    }
  }
}

Crimson Wizard

#9
The code above does not make any sense. You open the file in "Append" mode, which means that it's opened for writing at the end of existing file, but then try to read it. Of course nothing will be read.

AGS does not support opening a file in read/write mode, it's only either read or write. If you want to modify existing file after reading it, then you should first read everything from it, then open it again in write mode and overwrite the file with the modified data.

On a side note, this line:
Code: ags
palabra = String.Format("%s", f.ReadRawLineBack());
may be simplified to
Code: ags
palabra = f.ReadRawLineBack();

Crimson Wizard

TBH I'd rather suggest to go back to arrays and structs, and learn how these work, as they may be easier than doing this with a file.

Khris

Quote from: Zrezal on Sat 25/05/2024 16:56:10Doing it with Struct is impossible for me because it fails everywhere.

Show us your code, and we can fix it. This file-based approach is total nonsense, sorry.

SMF spam blocked by CleanTalk