Inventory and Guns

Part of the parenting stuff I posted yesterday was working towards an inventory/weapon system.

To make an entity so you can pick it up you just implement IInventoryEntity like this…

partial class Gun : ModelEntity, IInventoryEntity
{

The way this works is very simple. On the player class we have this function…

public override void StartTouch( Entity other )
{
	if ( IsClient ) return;

	if ( other is IInventoryEntity ient )
	{
		AddToInventory( ient );
	}
}

… which is called when the player bumps into an entity in the world. If it’s a gun, they try to pick it up.

The notion of an inventory is fluid. We should support anything from HLDM buckets and slots to Rust/Minecraft style inventory. So all this stuff exists in addon code… which means you can use it or make your own.

When the player has decided they want to add this item to the inventory, this function on IInventoryEntity is called…

/// <summary>
/// Allow the entity to do what it wants when it's added to the inventory.
/// Default behaviour is to add the target entity as a parent and stop moving.
/// </summary>
void OnAddedToInventory( Entity parentEntity )
{
	Host.AssertServer();

	if ( this is Entity self )
	{
		self.SetParent( parentEntity );
		self.Owner = parentEntity;
		self.MoveType = MoveType.None;
	}
}

The entity can obviously override this to do whatever they want, but this is the default behaviour.

As you can see, it just parents it to the player. That’s now in your inventory. You can obviously just get your children and see which ones implement IInventoryEntity to get a list of your inventory items, but I’ll be adding some nicer stuff for that.

One other thing the player does when an item is added to their inventory is this…

ActiveChild = iiinvent as Entity;

ActiveChild is a networked and predicted var on Entity which we use to store the entity you currently have in your hands.

This means that in the player’s tick we can call this

TickActiveEntity( ActiveChild );

which can calls this…

void TickActiveEntity( Entity ent )
{
	if ( ent == null ) return;

	if ( ent.Parent != this )
	{
		SwitchToNextEntity();
		return;
	}

	if ( ent is IPlayerControllable gun )
	{
		gun.PlayerControl( this );
	}
}

And then PlayerControl can do anything you want. In this case check if attack1 is pressed and shoot a bullet.

This is the start of this system. I don’t love the name IInventoryEntity but I couldn’t think of anything more suitable. It needs to be representative of a gun, a medpack, a tool, food, scrap etc. It’s not necessarily something you can put in your hands, but it’s something that you can put in your inventory.

27 Likes

Why “II”. It confuse

UPD: Ah, ok.

1 Like

A common naming convention for C# is that interfaces are prefixed with I to make it clear what it is at a glance.

2 Likes

Nice. This is the same way I do inventories so making items will be so smooth!

-Who are you?
-I am you, but with pants.

Sweet, can’t wait to see how you approach the hud with panorama.

Please. Please please please. Do not hardcode hold types like Garry’s Mod has it. Allow us to register hold types or animation combos so we can just add and use them easily.

Basically, Garry’s Mod will check hold types against a global table that we can’t add to without overwriting it. Additionally, each hold type is offset from the ACT enumeration instead of directly defined, meaning we can’t mix and match once we DO overwrite it. I know code_gs has plans on changing that, but it hasn’t been pushed yet.

I wanted to get that in while it’s still young so it wouldn’t get to the point of no return.

On topic: This looks great, especially how you create entities. This is basically a simplified version of how the SourceSDK handles entities ( Yeah they’re classes too but you know what I mean ) so I’m excited to see people being able to go through the SDK and understand a lot of the concepts based on what they get here. Good transferable knowledge.

5 Likes

The desire to keep all this in “addon code” is admirable, thanks for prioritizing that :+1:

1 Like

This is excellent. I can think of many gamemodes that could benefit from the ability to customize the system as one might desire, especially gamemodes like TTT or Roleplay where inventory content is constantly changing.

I take it that when you say make our own you mean that we can fully implement our own system without IInventoryEntity classes?

1 Like

IInventoryEntity is just an interface defined in the addon, you can completely change it or remove it if you wanted to. Nothing garry’s made is hard coded.

Good shit. Pleased to see making an entity is so clean even with the jump to C#.

Calling the interface IStoredEntity would look better and tell me the same thing.
If not for it allowing props/ents I would call it IEquipment.

Being able to easily store anything on the player by default and not just weapons is really cool too.

1 Like

StorableEntity rolls off the tongue nicely

3 Likes

My only concern is the behaviour of holding a single item at a time being hardcoded.

I hope that items can be added to the players “body” and we can make our own slots ( left hand, right hand, forehead for headlamp, etc) Even then, that behaviour might be too restrictive compared to something more generic.

It would be amazing to have basic inventories included but I’m not sure how to balance all the possible configurations and keep the inventories hot swappable.

1 Like

It’s not hardcoded, you could technical loop every item in the game and have the player control it in the tick

7 Likes