My inventory items are not displayed in the default gInventory (1920x1080 game)

Started by qinzha, Tue 25/02/2025 14:30:13

Previous topic - Next topic

qinzha

Hello there,
this is my first game with AGS and I'm having some problems with the gInventory.

I'm using the VerbCoin template and when I started my project, I've changed the game format to 16:9 (1920 x 1080px). Also I'm trying to use the default GUIs and just change their appearance. All the GUI settings seem to be the same as the defaults (except the scaling, background image and position), but for some reason I can't see any items in it (they are already set so the player has them from the start).

The size of the invCustom (298 x 366) is bigger than the size of the items (54 x 54) and I have already copied and pasted the original inventory-code from a new project into the global script just in case. I have not been able to find any solutions yet. Does anyone have any idea what I might have done wrong?

Screenshots:
https://1drv.ms/f/c/02ed179c0667423d/EpOowc7APUBLvpfWL7LllH0BZs8pw4Hzysxq9vW2anosbA?e=pkH5GS

Thank you! :)

Khris

Just to clarify: you cannot see any items in it *in-game*, right?
Because the editor won't show them.

qinzha

Quote from: Khris on Tue 25/02/2025 16:35:00Just to clarify: you cannot see any items in it *in-game*, right?
Because the editor won't show them.

Yes I mean ingame :D I can open the inventory as intended but it is empty, although 3 items should be displayed

Rik_Vargard

Just a stupid question: Did you add
Code: ags
player.AddInventory (iYourItem); 
?

Crimson Wizard

Quote from: Rik_Vargard on Tue 25/02/2025 20:50:05Just a stupid question: Did you add
Code: ags
player.AddInventory (iYourItem); 
?

The topic starter said that
Quote(they are already set so the player has them from the start).

Crimson Wizard

I suppose that it's worth double checking following:
1. Which CharacterID is set on InventoryWindow. It should be either -1 for automatic player character selection, or explicit character matching your player character.
2. InventoryWindow's Visible is true.
3. Inventory Items have appropriate Image set for them.

EDIT: looking at screenshots, all 3 points seem to be correct.
Also at least 1 item have "Player starts with this item" set.

Khris

Everything looks fine; not sure what's happening. If you upload your source files and post the link, we can take a look.

qinzha

Quote from: Khris on Tue 25/02/2025 23:12:45Everything looks fine; not sure what's happening. If you upload your source files and post the link, we can take a look.

Okidoki! Thank you all very much for your help so far! :)
https://we.tl/t-5L8EDpwFi0

Khris

There's a global variable called CurrentCharacter, initially set to 1.

In room_Load of the first room you have
Code: ags
  if (CurrentCharacter == 0)
  {
    cAbby.SetAsPlayer();
    cBarney.FollowCharacter(cAbby);
  }
  else
  {
    cBarney.SetAsPlayer();
    cAbby.FollowCharacter(cBarney);
  }

Which means cBarney is set as player character. cBarney doesn't have any inventory items though, and consequently the inventory GUI is empty.
(I didn't even notice this at first; when I started to debug this I simply put "return;" at the start of room_Load and re-ran the game, and the items appeared just fine.)

Each character has their own inventory, and the invWindow GUI Control is set to display the current player's items, i.e. now the dog's. When you go about fixing this, you should definitely keep the current setting of -1, because if you try to set an item as active that isn't owned by the player, AGS will grind to a halt.
Having multiple inventories is kind of tricky, so you should tell us how you want this to work in your game.

Also, regarding the global variable, you don't really need that. You can do one of these instead:
  if (player == cAbby) ...
  if (player.ID == 1) ...


As for explicitly setting the player in room_Load: AGS always loads/displays the room the current player character is in. I.e. if you call .SetAsPlayer() on a character in another room, AGS switches to that room. So the room_Load code doesn't really make sense; when you create a game where the player can switch the playable character, you typically implement this globally (via a GUI or global keyboard shortcut) and let AGS take care of the room switching. Again, we need to know how you want this to work to give more specific advice.

qinzha

Quote from: Khris on Wed 26/02/2025 11:14:55you should tell us how you want this to work in your game.

Oh damn, I didn't expect each character to have their own inventory. I thought player is player, no matter who the current player is O_O

The plan is that both characters share the same inventory and the player can't switch on their own. After the player has completed certain quests, the character is changed automatically and you play the next passage as Abby.

Did I understand correctly that I don't have to manually check which character is currently the player when changing rooms, because AGS automatically retains this and I only have to set the desired spawn coordinate? And does AGS automatically remember that the non-player character follows the player?

Khris

If the characters are supposed to have a shared inventory, you can transfer all the items, like this:

Code: ags
function TransferInventoryTo(this Character*, Character* other) {
  for (int i = 1; i <= Game.InventoryItemCount; i++) {
    other.InventoryQuantity[i] = this.InventoryQuantity[i];
    this.InventoryQuantity[i] = 0;
  }
  UpdateInventory(); // this unfortunately resets the order of the items to the editor's
}

Now you can call
  cAbby.TransferInventoryTo(cBarney);


AGS has a global pointer called  player  which always points to the player character. I.e. you can look at player.Room or call player.AddInventory(...) at any point. You can set which character the initial player character is in the editor. This also determines which room is loaded at the start of the game (because every character has a starting room and coordinates).

Characters are global entities and do not need to be "activated" after a room change. All you need to do is call player.ChangeRoom(room, x, y); and AGS will a) move the current player character to the new room at the specified coordinates, then unload the current room and load the new one.

Following works in a similar way; once you tell a character to follow another character they'll keep following them even to new rooms until you call .FollowCharacter(null)

Snarky

The easiest solution is to set InvWindow.CharacterToUse to one of the characters, and write the code to always refer to that character's inventory. Then it won't matter which character is currently set as player, you'll be using the same inventory regardless.

Crimson Wizard

Quote from: Snarky on Wed 26/02/2025 12:30:46The easiest solution is to set InvWindow.CharacterToUse to one of the characters, and write the code to always refer to that character's inventory. Then it won't matter which character is currently set as player, you'll be using the same inventory regardless.

You will see same inventory, but you won't be able to select items in that inventory to ActiveInventory, because character cannot set ActiveInventory to something that they do not own.

Snarky

You could still hardcode what character ActiveInventory is set for, and which character's ActiveInventory events check for, but I suppose it wouldn't update the mouse cursor if that character isn't currently player.

Khris

I guess one workaround is to simply always call Add/LoseInventory on both (all) characters in question.

Another hacky way is to use custom inv click handling and simply add the item to the current player character before setting it as active.

On that note: why does the check exist in the first place? Why does AGS complain if you set a non-owned item as active?

Crimson Wizard

Quote from: Khris on Wed 26/02/2025 13:26:45On that note: why does the check exist in the first place? Why does AGS complain if you set a non-owned item as active?

Because it's illogical if player selects an item that the player character does not have.

Khris

I understand that. I'm asking if there's a technical reason. Because I don't see it.
When you write inv handling code, the usual way is to do this:
Code: ags
  player.ActiveInventory = inventory[game.inv_activated];
So provided that the inv window that was clicked on is showing the player's inventory, this check is redundant for obvious reasons.

player.ActiveInventory is essentially just a random pointer that is typically checked in UseInv handlers.
It is set by the game's creator in their code, not the player. So if the creator wants to make sure that it only points to items actually held by the player character, they can easily implement this (it's not even extra work, it's just how a game works by default anyway).

Let's pretend the engine's setter doesn't check the player's inventory for a second. What is the downside?
Because there is a clear upside: we no longer have to work around the check in case we need to.

Crimson Wizard

There's no technical reason, this is only to make things logically consistent with the default inventory behavior.

qinzha

Quote from: Khris on Wed 26/02/2025 12:26:22If the characters are supposed to have a shared inventory, you can transfer all the items, like this:

Code: ags
function TransferInventoryTo(this Character*, Character* other) {
  for (int i = 1; i <= Game.InventoryItemCount; i++) {
    other.InventoryQuantity[i] = this.InventoryQuantity[i];
    this.InventoryQuantity[i] = 0;
  }
  UpdateInventory(); // this unfortunately resets the order of the items to the editor's
}

Now you can call
  cAbby.TransferInventoryTo(cBarney);



Ok where am I supposed to paste the code? Because if I paste it into the globals script and try to call it in the first room, it gives me the following error:

"room1.asc(12): Error (line 12): '.TransferInventoryTo' is not a public member of 'Character'. Are you sure you spelt it correctly (remember, capital letters are important)?"

Is there a class for characters somewhere, where I need to paste it? Because it sounds a bit like the class doesn't recognize the function yet

Crimson Wizard

Quote from: qinzha on Wed 26/02/2025 16:57:47Ok where am I supposed to paste the code? Because if I paste it into the globals script and try to call it in the first room, it gives me the following error:

How to export global functions to the room scripts:
https://adventuregamestudio.github.io/ags-manual/ImportingFunctionsAndVariables.html

In this case following line has to be added to GlobalScript header:
Code: ags
import function TransferInventoryTo(this Character*, Character* other);

SMF spam blocked by CleanTalk