[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Adonthell-devel] Finally, inventories!
From: |
Kai Sterker |
Subject: |
[Adonthell-devel] Finally, inventories! |
Date: |
Sun, 9 Feb 2003 17:43:26 +0100 |
As often is the case, I'm writing this mail 'cause it helps me to think
things through properly :). OTOH, if you have concerns with some of the
stuff that will follow, or better ideas, please let me know!
So lets start with the basic design: 2 classes are involved with the
inventory.
A "slot" is the inventory's basic unit. Basically, inventories are just
a list of slots. But as a slot is more than a container for a single
item, it needs to be a full featured class. So what does a slot contain?
Either nothing, a single item, a stack of identical items, or multiple
stacks of roughly identical items. Examples would be a suit of chain
mail, 100 coins or 5 torches in different state of usage.
Since a slot will not contain 100 coin items, but rather one coin item
and the count 100, items should never delete themselves. Instead they
should tell their slot to remove one unit. Therefore, items need to know
the slot they are kept in.
Some care has to be taken that items cannot be easily 'cloned' or
otherwise multiplied.
The "slot" class has at least the following attributes and methods:
- item_base* Item [private]
The item(s) kept in this slot. It may be a single, immutable item
in which case it is a mere pointer to the global instance of that
item. Or it is an instance (or linked list of instances) of a
mutable item.
Only (roughly) equal items may be kept in the same slot. To compare
items for equality, their name is used.
- u_int16 Count [private]
The number of items in the slot. If it contains immutable items,
then the number is a mere refcount. If it contains mutable items,
it tells the number of instances that are in the stack.
- string Id [private]
This can be used in cases where slots shouldn't be interchangeable.
That way we can use an inventory to store the items a character
wears by naming the slots accordingly. Setting this value is optional.
But its very useful for retrieving slots (and thus the items they may
contain) from an inventory without having a pointer to the slot.
- inventory * Inventory [private]
The inventory the slot belongs to. This is required so that the
slot can inform its inventory of changes that the inventory is
not aware of. (For example if an item is used up and tells the slot
to delete itself). The inventory in turn can notify others of the
change. (The GUI for example).
- unsigned int count () [public]
Returns the number of items in a slot. Can also be used to check
whether a given slot is empty.
This method is mainly of interest for a GUI that wants to display
the number of items in a slot.
- item_base * get_item () [public]
Returns a pointer to the (first) item in the slot. Again this is
mainly useful for inventories to access things like the item's icon or
description.
- bool add_item (item_base * item, int & count) [public]
Adds an item to the slot. The slot needs to be either empty, or has to
contain items of roughly the same kind. The items have to be stackable
of course. If they are stackable, as many items as fit are added to
the slot. If not all fit, the count parameter will contain the number
of remaining items. The method will return true if all items fitted,
false otherwise.
Some sanity checking can be implemented here as well. If the item in
question comes from another inventory, it's 'slot' member won't be
NULL. Therefore, we can automatically remove as many items from the
old slot as are added to the new one. That means, when moving an item
from one inventory to another, it needs not be explicitly removed.
That also means, that if a stack of item does not fit entirely into
the new inventory, no further action has to be taken, as the part of
the stack that cannot be transferred will remain in the old inventory.
Of course, in cases where this is not the desired behaviour (for
example if one has paid for these items in a shop), the remaining
items should be placed somewhere where the player can get them (e.g on
the ground) instead of remaining in the shopkeepers inventory.
- bool remove_item (item_base * item, const int & count = 1) [public]
Remove the given item from the slot. Removes up to 'count' items.
Returns false if 'count' greater than items in the slot. If 'count'
is -1, then all items will be removed, no matter how many there are.
That's the method an item should call if it is used up and wants to
delete itself.
The item instance needs to be passed to the slot, so we can remove
the right mutable item in case there is more than one. In case of
immutable item it wouldn't be needed.
Okay, those are the most basic methods of a slot. More might be needed
later on, but for a first implementation those should suffice.
On to the actual inventory:
- vector<slot*> Slots [private]
The slots an inventory contains. Inventories can have different
numbers of slots, and they can even grow if required.
- vector of 'listeners' [private]
Not exactly sure how that will be implemented, but I am pretty certain
that we might want to attach callbacks that are invoked when certain
'inventory events' occur. Such events could be adding or removing a
certain item, or some sort of item transition.
They can be used to update an inventory gui as required, but also for
gameplay stuff.
There'd be some methods for registering/unregistering those listeners.
Have to check whether the generic event system is suitable for this
purpose.
- bool Autogrow [private]
Whether the inventory may grow on inserting items. Might be useful for
a keyring, for example, or 'inventories' of maps or shops.
- void add_slot (const string & id) [public]
Add a slot with the given id. Mainly useful for setting up special
inventories from python. Otherwise, a special constructor should
create an inventory with a given number of (anonymous) slots.
- slot * get_slot (const string & id) [public]
Retrieve the named slot from the inventory. For example
get_slot ("Left Ring") or something similar. Apart from items the
character wears this could be also used to access other 'special'
slots, like a quiver or a slot associated with a certain action
button.
- bool add_item (item_base *item, u_int16 & count) [public]
Similar to slot::add_item. Will search for a slot that contains
matching items and add them to the stack, if stackable. Otherwise
will look for an empty slot to add the item to.
I think we do not need an explicit remove_item method. If items are
always moved between slots/inventories, removal will happen
automatically. The same is true when items are simply used up.
Should the need arise, such method could be added however.
- query methods [public]
We'd need a couple of methods to query an inventory for certain
items, or properties (like total weight or size). Items could be
queried by instance, by name or by category.
Query methods returning items should return one item at a time
or NULL if no item of that type remains. This means a bit more code to
write, if for example we want to remove all items of a kind, but OTOH
it allows equal treatment of mutable and immutable items.
- action methods [public]
As I said in the mail about item actions, to allow simple combination
of stacks of items, item actions should be executed via the inventory
(if desired). The methods should be written such that items may come
from different inventories (i.e work on slot level). When
manipulating/using items via the inventory GUI, those methods would be
called. On other occassions the item actions may be called directly.
Okay, that should be it for now. I am quite happy with everything, so I
will go about coding the stuff to see where problems remain that I
haven't covered. If you have suggestions or ideas, please fire away!
Kai
- [Adonthell-devel] Finally, inventories!,
Kai Sterker <=