Discordo levemente de todos e digo que a abordagem relacional é razoável aqui. O interessante aqui é que os itens podem ter várias funções. A questão principal será que o mapeamento entre esse layout relacional e um layout OO no código não parecerá "natural", mas acho que no lado do banco de dados várias funções podem ser expressas de maneira limpa (sem codificações ou redundância estranhas, apenas se juntam) .
A primeira coisa a decidir é quanto dos dados é específico do item e quanto é compartilhado por todos os itens de um determinado tipo.
Aqui está o que eu faria se todos os dados fossem específicos do item:
// ITEMS table: attributes common to all items
item_id | name | owner | location | sprite_id | ...
1 | Light Saber | 14 (Tchalvek) | 381 (Tchalvek house) | 5663 | ...
// WEAPONS table: attributes for items that are weapons
item_id | damage | damage_type | durability | ...
1 | 5 | sharp | 13 | ...
// LIGHTING table: attributes for items that serve as lights
item_id | radius | brightness | duration | ...
1 | 3 meters | 50 | 8 hours | ...
Nesse design, cada item está na tabela Itens, juntamente com os atributos que todos (ou a maioria) dos itens possuem. Cada função adicional que um item pode desempenhar é uma tabela separada.
Se você quiser usá-lo como arma, procure na tabela de Armas. Se estiver lá, é utilizável como arma. Se não estiver lá, não poderá ser usado como arma. A existência do registro informa se é uma arma. E se estiver lá, todos os seus atributos específicos de arma serão armazenados lá. Como esses atributos são armazenados diretamente em vez de em algum formato codificado, você poderá realizar consultas / filtros com eles. (Por exemplo, para a página de métricas do seu jogo, você pode agregar jogadores por tipo de dano da arma e poderá fazer isso com algumas junções e um tipo de dano por grupo.)
Um item pode ter várias funções e existir em mais de uma tabela específica de função (neste exemplo, arma e iluminação).
Se for apenas um valor booleano como "isso é suportável", eu o colocaria na tabela Items. Pode valer a pena armazenar em cache "isto é uma arma" etc. etc. para que você não precise fazer uma pesquisa nas armas e em outras tabelas de funções. No entanto, ele adiciona redundância, portanto, você deve ter cuidado para mantê-lo sincronizado.
A recomendação de Ari de ter uma tabela adicional por tipo também pode ser usada com essa abordagem se alguns dados não variarem por item. Por exemplo, se o dano da arma não variar por item, mas os papéis ainda variarem por item, você pode levar em consideração os atributos da arma compartilhada em uma tabela:
// WEAPONS table: attributes for items that are weapons
item_id | durability | weapon_type
1 | 13 | light_saber
// WEAPONTYPES table: attributes for classes of weapons
weapon_type_id | damage | damage_type
light_saber | 5 | energy
Outra abordagem seria se os papéis desempenhados pelos itens não variarem por item, mas apenas por tipo de item. Nesse caso, você colocaria o item_type na tabela Items e poderá armazenar as propriedades como "é uma arma" e "é suportável" e "é uma luz" em uma tabela ItemTypes. Neste exemplo, também faço os nomes dos itens não variarem por item:
// ITEMS table: attributes per item
item_id | item_type | owner | location
1 | light_saber | 14 (Tchalvek) | 381 (Tchalvek house)
// ITEMTYPES table: attributes shared by all items of a type
item_type | name | sprite_id | is_holdable | is_weapon | is_light
light_saber | Light Saber | 5663 | true | true | true
// WEAPONTYPES table: attributes for item types that are also weapons
item_type | damage | damage_type
light_saber | 5 | energy
É provável que os tipos de item e tipo de arma não sejam alterados durante o jogo; portanto, você pode carregar essas tabelas na memória apenas uma vez e procurar esses atributos em uma tabela de hash em vez de em uma associação ao banco de dados.