eco2d/code/foundation/src/ents/items.c

131 lines
3.7 KiB
C
Raw Normal View History

#include "ents/items.h"
#include "ents/entity.h"
#include "world/entity_view.h"
2021-08-25 21:36:20 +00:00
#include "world/world.h"
2021-08-30 15:50:05 +00:00
#include "world/blocks.h"
2021-08-25 21:36:20 +00:00
#include "ecs/components.h"
2021-08-25 21:36:20 +00:00
2021-08-30 15:50:05 +00:00
#include "zpl.h"
#include "items_list.c"
2022-09-27 13:55:24 +00:00
void item_cleanup() {
zpl_array_free(items); items = NULL;
}
void item_register(item_desc desc) {
if (!items) {
zpl_array_init(items, zpl_heap());
}
zpl_array_append(items, desc);
}
2021-08-30 15:50:05 +00:00
2021-11-03 18:09:19 +00:00
static inline item_id item_resolve_proxy(item_id id) {
2022-09-27 13:55:24 +00:00
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
2021-11-03 13:34:32 +00:00
item_usage usage = items[id].usage;
if (usage == UKIND_PROXY) {
return item_find(items[id].proxy.id);
}
return id;
}
static inline asset_id item_fix_kind(asset_id id) {
return items[item_find(id)].kind;
}
2021-11-02 10:48:32 +00:00
uint64_t item_spawn(asset_id kind, uint32_t qty) {
2021-08-25 21:36:20 +00:00
ecs_entity_t e = entity_spawn(EKIND_ITEM);
2022-09-12 07:08:22 +00:00
2022-07-31 14:34:47 +00:00
ItemDrop *d = ecs_get_mut(world_ecs(), e, ItemDrop);
2021-08-25 21:36:20 +00:00
*d = (ItemDrop){
2021-11-03 13:34:32 +00:00
.kind = item_fix_kind(kind),
2021-08-25 21:36:20 +00:00
.quantity = qty,
2021-09-09 07:46:22 +00:00
.merger_time = 0,
2021-08-25 21:36:20 +00:00
};
2022-09-12 07:08:22 +00:00
2021-08-25 21:36:20 +00:00
return (uint64_t)e;
}
2021-11-03 18:09:19 +00:00
item_id item_find(asset_id kind) {
2022-09-27 13:55:24 +00:00
for (item_id i=0; i<zpl_array_count(items); i++) {
2021-08-30 15:50:05 +00:00
if (items[i].kind == kind)
2021-11-02 17:58:55 +00:00
return item_resolve_proxy(i);
2021-08-30 15:50:05 +00:00
}
2021-11-02 10:48:32 +00:00
return ASSET_INVALID;
2021-08-30 15:50:05 +00:00
}
2021-11-02 17:58:55 +00:00
void item_use(ecs_world_t *ecs, ItemDrop *it, Position p, uint64_t udata) {
2021-08-30 15:50:05 +00:00
(void)ecs;
2021-11-03 18:09:19 +00:00
uint16_t it_id = item_find(it->kind);
item_desc *desc = &items[it_id];
2021-11-01 17:35:33 +00:00
if (it->quantity <= 0) return;
2021-11-03 18:09:19 +00:00
switch (item_get_usage(it_id)) {
2021-11-02 17:09:54 +00:00
case UKIND_HOLD: /* NOOP */ break;
2021-08-30 15:50:05 +00:00
case UKIND_PLACE:{
world_block_lookup l = world_block_from_realpos(p.x, p.y);
2021-11-03 18:04:34 +00:00
if (l.is_outer && l.bid > 0) {
asset_id item_asset = blocks_get_asset(l.bid);
2021-11-03 18:09:19 +00:00
item_id item_asset_id = item_find(item_asset);
2021-11-03 15:41:42 +00:00
if (item_asset_id == ASSET_INVALID) return;
2022-09-12 07:08:22 +00:00
2021-11-03 16:16:35 +00:00
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
2021-11-03 18:09:19 +00:00
if (item_asset_id == it_id) {
2021-11-03 16:16:35 +00:00
it->quantity++;
2021-11-03 16:17:48 +00:00
} else {
return;
2021-11-03 16:16:35 +00:00
}
}
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
2021-11-03 18:04:34 +00:00
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
return;
}
2021-11-03 15:29:45 +00:00
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
it->quantity--;
2021-08-30 15:50:05 +00:00
}break;
2022-09-12 07:08:22 +00:00
2022-08-09 14:46:23 +00:00
case UKIND_PLACE_ITEM:{
world_block_lookup l = world_block_from_realpos(p.x, p.y);
if (l.is_outer && l.bid > 0) {
return;
}
// NOTE(zaklaus): This is an inner layer block, we can't build over it if it has a collision!
else if (l.bid > 0 && blocks_get_flags(l.bid) & (BLOCK_FLAG_COLLISION|BLOCK_FLAG_ESSENTIAL)) {
return;
}
2022-09-12 07:08:22 +00:00
2022-08-13 06:43:15 +00:00
ecs_entity_t e = entity_spawn_id(desc->place_item.id);
2022-08-09 14:46:23 +00:00
ZPL_ASSERT(world_entity_valid(e));
entity_set_position(e, p.x, p.y);
2022-09-12 07:08:22 +00:00
2022-08-09 14:46:23 +00:00
it->quantity--;
}break;
2022-09-12 07:08:22 +00:00
case UKIND_DELETE:
case UKIND_END_PLACE:
case UKIND_PROXY:
break;
2021-08-30 15:50:05 +00:00
}
}
2021-08-25 21:36:20 +00:00
void item_despawn(uint64_t id) {
entity_despawn(id);
}
2021-11-03 18:09:19 +00:00
uint32_t item_max_quantity(item_id id) {
2022-09-27 13:55:24 +00:00
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
2021-08-30 15:50:05 +00:00
return items[id].max_quantity;
}
2021-11-03 18:09:19 +00:00
item_usage item_get_usage(item_id id) {
2022-09-27 13:55:24 +00:00
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
2021-08-30 15:50:05 +00:00
return items[id].usage;
2021-11-02 17:58:55 +00:00
}
2021-11-03 18:09:19 +00:00
bool item_get_place_directional(item_id id) {
2022-09-27 13:55:24 +00:00
ZPL_ASSERT(id >= 0 && id < zpl_array_count(items));
2021-11-02 17:58:55 +00:00
return items[id].place.directional;
2022-07-31 14:34:47 +00:00
}