lots of changes
parent
b8e3decc96
commit
0be5d87ede
|
@ -4,7 +4,7 @@ game_rulesdef game_rules = (game_rulesdef){
|
|||
.phy_walk_drag = 4.23f,
|
||||
.demo_npc_move_speed = 500,
|
||||
.demo_npc_steer_speed = 300,
|
||||
.furnace_cook_time = 5.0f,
|
||||
.furnace_cook_time = 1.f,
|
||||
.item_pick_radius = 25.0f,
|
||||
.item_merger_radius = 75.0f,
|
||||
.item_attract_radius = 75.0f,
|
||||
|
|
|
@ -49,7 +49,7 @@ ActSpawnChest(void) {
|
|||
|
||||
void
|
||||
ActSpawnBelt(void) {
|
||||
ecs_entity_t e = item_spawn(ASSET_BELT, 999);
|
||||
ecs_entity_t e = item_spawn(ASSET_BELT, 32);
|
||||
ecs_entity_t plr = camera_get().ent_id;
|
||||
|
||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||
|
|
|
@ -12,9 +12,12 @@ ECS_COMPONENT_DECLARE(Classify);
|
|||
ECS_COMPONENT_DECLARE(Vehicle);
|
||||
ECS_COMPONENT_DECLARE(IsInVehicle);
|
||||
ECS_COMPONENT_DECLARE(Item);
|
||||
ECS_COMPONENT_DECLARE(ItemAlreadyEdited);
|
||||
ECS_COMPONENT_DECLARE(Inventory);
|
||||
ECS_COMPONENT_DECLARE(ItemContainer);
|
||||
ECS_COMPONENT_DECLARE(Furnace);
|
||||
ECS_COMPONENT_DECLARE(Fuel);
|
||||
ECS_COMPONENT_DECLARE(Ingredient);
|
||||
ECS_COMPONENT_DECLARE(Device);
|
||||
ECS_COMPONENT_DECLARE(DemoNPC);
|
||||
ECS_COMPONENT_DECLARE(StreamInfo);
|
||||
|
@ -34,9 +37,12 @@ void ComponentsImport(ecs_world_t *ecs) {
|
|||
ECS_COMPONENT_DEFINE(ecs, Vehicle);
|
||||
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
|
||||
ECS_COMPONENT_DEFINE(ecs, Item);
|
||||
ECS_COMPONENT_DEFINE(ecs, ItemAlreadyEdited);
|
||||
ECS_COMPONENT_DEFINE(ecs, Inventory);
|
||||
ECS_COMPONENT_DEFINE(ecs, ItemContainer);
|
||||
ECS_COMPONENT_DEFINE(ecs, Furnace);
|
||||
ECS_COMPONENT_DEFINE(ecs, Fuel);
|
||||
ECS_COMPONENT_DEFINE(ecs, Ingredient);
|
||||
ECS_COMPONENT_DEFINE(ecs, Device);
|
||||
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
|
||||
ECS_COMPONENT_DEFINE(ecs, StreamInfo);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "flecs/flecs.h"
|
||||
#include "gen/assets.h"
|
||||
|
||||
#ifndef ecs_get_mut_if
|
||||
#define ecs_get_mut_if(world, entity, component)\
|
||||
|
@ -100,12 +101,17 @@ typedef struct {
|
|||
uint16_t kind;
|
||||
uint32_t quantity;
|
||||
float merger_time;
|
||||
float durability; // 1.0 - 0.0 (0.0 = broken), we can only ever merge items of the same durability
|
||||
} Item;
|
||||
|
||||
typedef struct {
|
||||
char _unused;
|
||||
} ItemAlreadyEdited;
|
||||
|
||||
typedef struct {
|
||||
// TODO: we now hold a ref to an item, instead of representing an item slot,
|
||||
// so that we can let the item entity keep its own components and also handle merging ops on its own.
|
||||
ecs_entity_t items[ITEMS_CONTAINER_SIZE];
|
||||
ecs_entity_t items[ITEMS_INVENTORY_SIZE];
|
||||
float pickup_time;
|
||||
} Inventory;
|
||||
|
||||
|
@ -114,18 +120,21 @@ typedef struct {
|
|||
} ItemContainer;
|
||||
|
||||
typedef struct {
|
||||
ecs_entity_t processed_item;
|
||||
asset_id processed_item;
|
||||
float cook_time;
|
||||
float burn_time;
|
||||
} Furnace;
|
||||
|
||||
// typedef struct {
|
||||
// float burn_time;
|
||||
// } Fuel;
|
||||
typedef struct {
|
||||
asset_id kind;
|
||||
float burn_time;
|
||||
} Fuel;
|
||||
|
||||
// typedef struct {
|
||||
// asset_id converted_kind;
|
||||
// } FuelTank;
|
||||
typedef struct {
|
||||
asset_id producer;
|
||||
asset_id additional_ingredient; // optional - can specify additional item we need in the container to craft this item
|
||||
asset_id product;
|
||||
} Ingredient;
|
||||
|
||||
typedef struct {
|
||||
uint16_t asset;
|
||||
|
@ -150,9 +159,12 @@ extern ECS_COMPONENT_DECLARE(Classify);
|
|||
extern ECS_COMPONENT_DECLARE(Vehicle);
|
||||
extern ECS_COMPONENT_DECLARE(IsInVehicle);
|
||||
extern ECS_COMPONENT_DECLARE(Item);
|
||||
extern ECS_COMPONENT_DECLARE(ItemAlreadyEdited);
|
||||
extern ECS_COMPONENT_DECLARE(Inventory);
|
||||
extern ECS_COMPONENT_DECLARE(ItemContainer);
|
||||
extern ECS_COMPONENT_DECLARE(Furnace);
|
||||
extern ECS_COMPONENT_DECLARE(Fuel);
|
||||
extern ECS_COMPONENT_DECLARE(Ingredient);
|
||||
extern ECS_COMPONENT_DECLARE(Device);
|
||||
extern ECS_COMPONENT_DECLARE(DemoNPC);
|
||||
extern ECS_COMPONENT_DECLARE(StreamInfo);
|
||||
|
|
|
@ -2,33 +2,42 @@ void FurnaceCook(ecs_iter_t *it) {
|
|||
ItemContainer *storage = ecs_field(it, ItemContainer, 1);
|
||||
Furnace *furnace = ecs_field(it, Furnace, 2);
|
||||
Position *p = ecs_field(it, Position, 3);
|
||||
Device *d = ecs_field(it, Device, 4);
|
||||
|
||||
for (int i = 0; i < it->count; i++) {
|
||||
for (int j = 0; j < ITEMS_CONTAINER_SIZE; j++) {
|
||||
if (storage[i].items[j].kind == ASSET_COAL) {
|
||||
// furnace[i].fuel_level += itemdb_get(storage[i].items[j].uuid, ITEMDB_FUEL_LEVEL);
|
||||
// furnace[i].fuel_level = zpl_clamp(furnace[i].fuel_level + 0.8f, 0.0f, 1.0f);
|
||||
storage[i].items[j].quantity--;
|
||||
if (storage[i].items[j].quantity == 0) {
|
||||
storage[i].items[j] = (ItemSlot){0};
|
||||
ecs_entity_t item_slot_ent = storage[i].items[j];
|
||||
Item *item = item_get_data(item_slot_ent);
|
||||
|
||||
const Fuel *fuel = 0;
|
||||
if ((fuel = ecs_get(it->world, item_slot_ent, Fuel))) {
|
||||
if (fuel->kind == d->asset) {
|
||||
furnace[i].burn_time += fuel->kind;
|
||||
item_despawn(item_slot_ent);
|
||||
storage[i].items[j] = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (furnace[i].fuel_level <= 0.0f) continue;
|
||||
// if (furnace[i].burn_time <= 0.0f) continue; TODO
|
||||
if (furnace[i].cook_time < game_time()) {
|
||||
if (furnace[i].processed_item.kind > 0) {
|
||||
uint64_t e = item_spawn(furnace[i].processed_item.kind, 1);
|
||||
if (furnace[i].processed_item > 0) {
|
||||
uint64_t e = item_spawn(furnace[i].processed_item, 1);
|
||||
entity_set_position(e, p[i].x, p[i].y);
|
||||
furnace[i].processed_item.kind = 0;
|
||||
furnace[i].processed_item = 0;
|
||||
} else {
|
||||
if (storage[i].items[j].kind == ASSET_DEMO_ICEMAKER) {
|
||||
furnace[i].processed_item.kind = ASSET_BELT;
|
||||
storage[i].items[j].quantity--;
|
||||
if (storage[i].items[j].quantity == 0) {
|
||||
storage[i].items[j] = (ItemSlot){0};
|
||||
const Ingredient *ing = 0;
|
||||
if ((ing = ecs_get(it->world, item_slot_ent, Ingredient))) {
|
||||
if (ing->producer == d->asset) {
|
||||
furnace[i].processed_item = ing->product;
|
||||
furnace[i].cook_time = game_time() + game_rules.furnace_cook_time;
|
||||
zpl_printf("e_id %llu, qty: %d\n", item_slot_ent, item->quantity);
|
||||
item->quantity--;
|
||||
if (item->quantity <= 0) {
|
||||
item_despawn(item_slot_ent);
|
||||
storage[i].items[j] = 0;
|
||||
}
|
||||
}
|
||||
furnace[i].cook_time = game_time() + game_rules.furnace_cook_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,14 @@ void PickItem(ecs_iter_t *it) {
|
|||
if (inv[i].pickup_time > game_time()) continue;
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||
bool picked = false;
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
Item *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], Item))) {
|
||||
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
|
||||
Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity);
|
||||
uint64_t ent_id = ents[j];
|
||||
if ((drop = ecs_get_mut_if(it->world, ent_id, Item))) {
|
||||
Position *p2 = ecs_get_mut(it->world, ent_id, Position);
|
||||
Velocity *v2 = ecs_get_mut(it->world, ent_id, Velocity);
|
||||
|
||||
float dx = p2->x - p[i].x;
|
||||
float dy = p2->y - p[i].y;
|
||||
|
@ -21,23 +23,25 @@ void PickItem(ecs_iter_t *it) {
|
|||
if (range <= game_rules.item_pick_radius) {
|
||||
uint16_t drop_id = item_find(drop->kind);
|
||||
for (size_t k = 0; k < ITEMS_INVENTORY_SIZE; k += 1) {
|
||||
ItemSlot *item_slot = &inv[i].items[k];
|
||||
Item *item = item_get_data(item_slot->ent);
|
||||
uint16_t item_id = item_find(item->kind);
|
||||
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)
|
||||
&& (item_slot->ent == 0 || item_slot->ent == ents[j])) {
|
||||
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
|
||||
item_slot->ent = ents[j];
|
||||
item->quantity += picked_count;
|
||||
drop->quantity -= picked_count;
|
||||
item->kind = drop->kind;
|
||||
entity_wake(ents[j]);
|
||||
ecs_entity_t item_slot_ent = inv[i].items[k];
|
||||
Item *item = item_get_data(item_slot_ent);
|
||||
uint16_t item_id = item ? item_find(item->kind) : 0;
|
||||
if (!item || (item_id != ASSET_INVALID && (item->kind == drop->kind && item->durability == drop->durability) && item->quantity < item_max_quantity(drop_id))) {
|
||||
if (item) {
|
||||
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
|
||||
item->quantity += picked_count;
|
||||
drop->quantity -= picked_count;
|
||||
item->kind = drop->kind;
|
||||
|
||||
if (drop->quantity == 0)
|
||||
item_show(ents[j], false);
|
||||
|
||||
item_slot->ent = ents[j];
|
||||
if (drop->quantity == 0)
|
||||
item_despawn(ent_id);
|
||||
} else if (!world_entity_valid(item_slot_ent)) {
|
||||
entity_wake(ent_id);
|
||||
item_show(ent_id, false);
|
||||
inv[i].items[k] = ent_id;
|
||||
}
|
||||
picked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +50,8 @@ void PickItem(ecs_iter_t *it) {
|
|||
v2->y = (p[i].y - p2->y) * game_rules.item_attract_force;
|
||||
}
|
||||
}
|
||||
|
||||
if (picked) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +64,7 @@ void DropItem(ecs_iter_t *it) {
|
|||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].drop) continue;
|
||||
|
||||
ItemSlot *items = inv[i].items;
|
||||
ecs_entity_t *items = inv[i].items;
|
||||
|
||||
if (in[i].storage_action){
|
||||
if (world_entity_valid(in[i].storage_ent)){
|
||||
|
@ -73,8 +79,9 @@ void DropItem(ecs_iter_t *it) {
|
|||
}
|
||||
}
|
||||
|
||||
ItemSlot *item_slot = &items[in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item];
|
||||
Item *item = item_get_data(item_slot->ent);
|
||||
uint8_t slot_id = in[i].storage_action ? in[i].storage_selected_item : in[i].selected_item;
|
||||
ecs_entity_t item_slot_ent = items[slot_id];
|
||||
Item *item = item_get_data(item_slot_ent);
|
||||
|
||||
if (!item || item->quantity <= 0)
|
||||
continue;
|
||||
|
@ -83,72 +90,67 @@ void DropItem(ecs_iter_t *it) {
|
|||
if (in[i].sprint) {
|
||||
dropped_count /= 2;
|
||||
} else if (in[i].ctrl) {
|
||||
dropped_count = dropped_count > 0 ? 1 : 0;
|
||||
dropped_count = item->quantity-1;
|
||||
}
|
||||
|
||||
if (dropped_count == 0)
|
||||
continue;
|
||||
|
||||
ecs_entity_t te = item_slot->ent;
|
||||
item_show(item_slot->ent, true);
|
||||
item->quantity -= dropped_count;
|
||||
item_show(item_slot_ent, true);
|
||||
|
||||
ItemDrop *d = ecs_get_mut(world_ecs(), te, ItemDrop);
|
||||
*d = (ItemDrop){
|
||||
.kind = item->kind,
|
||||
.quantity = dropped_count,
|
||||
.merger_time = game_time() + game_rules.item_drop_merger_time,
|
||||
};
|
||||
Position *ipos = ecs_get_mut(it->world, item_slot_ent, Position);
|
||||
entity_set_position(item_slot_ent, p[i].x, p[i].y);
|
||||
|
||||
Position *ipos = ecs_get_mut(it->world, te, Position);
|
||||
*ipos = p[i];
|
||||
|
||||
Velocity *v = ecs_get_mut(it->world, te, Velocity);
|
||||
Velocity *v = ecs_get_mut(it->world, item_slot_ent, Velocity);
|
||||
v->x = in[i].mx * 800.0f;
|
||||
v->y = in[i].my * 800.0f;
|
||||
|
||||
inv[i].pickup_time = game_time() + game_rules.item_drop_pickup_time;
|
||||
in[i].drop = false;
|
||||
items[slot_id] = 0;
|
||||
|
||||
if (item->quantity == 0) {
|
||||
item->kind = 0;
|
||||
if (item->quantity - dropped_count > 0) {
|
||||
item->quantity -= dropped_count;
|
||||
ecs_entity_t te = item_spawn(item->kind, dropped_count);
|
||||
item_show(te, false);
|
||||
items[slot_id] = te;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MergeItems(ecs_iter_t *it) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
ItemDrop *id = ecs_field(it, ItemDrop, 2);
|
||||
// void MergeItems(ecs_iter_t *it) {
|
||||
// Position *p = ecs_field(it, Position, 1);
|
||||
// ItemDrop *id = ecs_field(it, ItemDrop, 2);
|
||||
|
||||
for (int i = 0; i < it->count; i += 1) {
|
||||
ItemDrop *item = &id[i];
|
||||
// for (int i = 0; i < it->count; i += 1) {
|
||||
// ItemDrop *item = &id[i];
|
||||
|
||||
if (item->merger_time < game_time())
|
||||
continue;
|
||||
// if (item->merger_time < game_time())
|
||||
// continue;
|
||||
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
|
||||
// size_t ents_count;
|
||||
// int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 1);
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
ItemDrop *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||
if (drop->kind != item->kind || (ecs_entity_t)ents[j] == it->entities[i] || drop->quantity == 0 || item->quantity == 0)
|
||||
continue;
|
||||
// for (size_t j = 0; j < ents_count; j++) {
|
||||
// ItemDrop *drop = 0;
|
||||
// if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||
// if (drop->kind != item->kind || (ecs_entity_t)ents[j] == it->entities[i] || drop->quantity == 0 || item->quantity == 0)
|
||||
// continue;
|
||||
|
||||
Position const* p2 = ecs_get(it->world, ents[j], Position);
|
||||
// Position const* p2 = ecs_get(it->world, ents[j], Position);
|
||||
|
||||
float dx = p2->x - (p[i].x);
|
||||
float dy = p2->y - (p[i].y);
|
||||
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
if (range <= game_rules.item_merger_radius) {
|
||||
drop->quantity += item->quantity;
|
||||
item_despawn(it->entities[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// float dx = p2->x - (p[i].x);
|
||||
// float dy = p2->y - (p[i].y);
|
||||
// float range = zpl_sqrt(dx*dx + dy*dy);
|
||||
// if (range <= game_rules.item_merger_radius) {
|
||||
// drop->quantity += item->quantity;
|
||||
// item_despawn(it->entities[i]);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void SwapItems(ecs_iter_t *it) {
|
||||
Input *in = ecs_field(it, Input, 1);
|
||||
|
@ -157,7 +159,7 @@ void SwapItems(ecs_iter_t *it) {
|
|||
for (int i = 0; i < it->count; i++) {
|
||||
if (!in[i].swap) continue;
|
||||
|
||||
ItemDrop *items = inv[i].items;
|
||||
ecs_entity_t *items = inv[i].items;
|
||||
|
||||
if (in[i].storage_action){
|
||||
if (world_entity_valid(in[i].storage_ent)){
|
||||
|
@ -172,40 +174,49 @@ void SwapItems(ecs_iter_t *it) {
|
|||
}
|
||||
}
|
||||
|
||||
ItemDrop *to = 0;
|
||||
ItemDrop *from = 0;
|
||||
ecs_entity_t *from_ent = 0;
|
||||
ecs_entity_t *to_ent = 0;
|
||||
Item *to = 0;
|
||||
Item *from = 0;
|
||||
|
||||
if (in[i].swap_storage){
|
||||
in[i].swap_storage = false;
|
||||
|
||||
if (in[i].storage_action){
|
||||
from = &inv[i].items[in[i].swap_from];
|
||||
to = &items[in[i].swap_to];
|
||||
from_ent = &inv[i].items[in[i].swap_from];
|
||||
to_ent = &items[in[i].swap_to];
|
||||
from = item_get_data(*from_ent);
|
||||
to = item_get_data(*to_ent);
|
||||
}else{
|
||||
if (world_entity_valid(in[i].storage_ent)){
|
||||
ItemContainer *ic = 0;
|
||||
if ((ic = ecs_get_mut_if(it->world, in[i].storage_ent, ItemContainer))){
|
||||
from = &ic->items[in[i].swap_from];
|
||||
from_ent = &ic->items[in[i].swap_from];
|
||||
from = item_get_data(*from_ent);
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
to = &items[in[i].swap_to];
|
||||
to_ent = &items[in[i].swap_to];
|
||||
to = item_get_data(*to_ent);
|
||||
}
|
||||
}else{
|
||||
from = &items[in[i].swap_from];
|
||||
to = &items[in[i].swap_to];
|
||||
from_ent = &items[in[i].swap_from];
|
||||
to_ent = &items[in[i].swap_to];
|
||||
from = item_get_data(*from_ent);
|
||||
to = item_get_data(*to_ent);
|
||||
}
|
||||
|
||||
ZPL_ASSERT(from && to);
|
||||
if (!from) continue;
|
||||
|
||||
uint16_t to_id = item_find(to->kind);
|
||||
uint16_t to_id = to ? item_find(to->kind) : ASSET_EMPTY;
|
||||
asset_id to_kind = to ? to->kind : ASSET_EMPTY;
|
||||
|
||||
if (to == from) {
|
||||
if (to_ent == from_ent) {
|
||||
// NOTE(zaklaus): do nothing
|
||||
} else if (to->kind == from->kind && to->quantity > 0) {
|
||||
} else if (to_kind == from->kind && to->quantity > 0) {
|
||||
uint32_t swapped_count = from->quantity;
|
||||
if (in[i].sprint) {
|
||||
swapped_count /= 2;
|
||||
|
@ -216,24 +227,28 @@ void SwapItems(ecs_iter_t *it) {
|
|||
to->quantity += swapped_count;
|
||||
from->quantity -= swapped_count;
|
||||
|
||||
if (swapped_count == 0) {
|
||||
ItemDrop tmp = *to;
|
||||
*to = *from;
|
||||
*from = tmp;
|
||||
if (from->quantity == 0) {
|
||||
item_despawn(*from_ent);
|
||||
*from_ent = 0;
|
||||
}
|
||||
} else if ((in[i].ctrl || in[i].sprint) && to->quantity == 0 && from->quantity > 0) {
|
||||
} else if ((in[i].ctrl || in[i].sprint) && to == 0 && from->quantity > 0) {
|
||||
// NOTE(zaklaus): item split
|
||||
uint32_t split_count = from->quantity / 2;
|
||||
if (in[i].ctrl) {
|
||||
split_count = 1;
|
||||
}
|
||||
to->quantity = split_count;
|
||||
if (from->quantity - split_count == 0) {
|
||||
continue;
|
||||
}
|
||||
ecs_entity_t te = item_spawn(from->kind, split_count);
|
||||
item_show(te, false);
|
||||
*to_ent = te;
|
||||
|
||||
from->quantity -= split_count;
|
||||
to->kind = from->kind;
|
||||
} else {
|
||||
ItemDrop tmp = *to;
|
||||
*to = *from;
|
||||
*from = tmp;
|
||||
ecs_entity_t tmp = *to_ent;
|
||||
*to_ent = *from_ent;
|
||||
*from_ent = tmp;
|
||||
}
|
||||
|
||||
in[i].swap = false;
|
||||
|
@ -252,12 +267,13 @@ void UseItem(ecs_iter_t *it) {
|
|||
continue;
|
||||
}
|
||||
|
||||
ItemDrop *item = &inv[i].items[in[i].selected_item];
|
||||
ecs_entity_t item_ent = inv[i].items[in[i].selected_item];
|
||||
Item *item = item_get_data(item_ent);
|
||||
uint16_t item_id = 0;
|
||||
item_usage usage = UKIND_DELETE;
|
||||
|
||||
if (!in[i].deletion_mode){
|
||||
item_id = item_find(item->kind);
|
||||
item_id = item ? item_find(item->kind) : ASSET_EMPTY;
|
||||
usage = item_get_usage(item_id);
|
||||
if (!item || item->quantity <= 0) continue;
|
||||
}
|
||||
|
@ -268,7 +284,7 @@ void UseItem(ecs_iter_t *it) {
|
|||
}
|
||||
}
|
||||
else if (in[i].use && usage > UKIND_END_PLACE)
|
||||
item_use(it->world, item, p[i], 0);
|
||||
item_use(it->world, item_ent, item, p[i], 0);
|
||||
else if (in[i].num_placements > 0 && usage < UKIND_END_PLACE) {
|
||||
asset_id ofs = 0;
|
||||
if (item_get_place_directional(item_id) && in[i].num_placements >= 2) {
|
||||
|
@ -289,13 +305,18 @@ void UseItem(ecs_iter_t *it) {
|
|||
|
||||
for (size_t j = 0; j < in[i].num_placements; j++) {
|
||||
Position pos = {.x = in[i].placements_x[j], .y = in[i].placements_y[j]};
|
||||
item_use(it->world, item, pos, ofs);
|
||||
item_use(it->world, item_ent, item, pos, ofs);
|
||||
}
|
||||
|
||||
in[i].num_placements = 0;
|
||||
}
|
||||
|
||||
entity_wake(it->entities[i]);
|
||||
|
||||
if (item->quantity == 0) {
|
||||
item_despawn(item_ent);
|
||||
inv[i].items[in[i].selected_item] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,11 +339,13 @@ void HarvestIntoContainers(ecs_iter_t *it) {
|
|||
// NOTE(zaklaus): find any item
|
||||
size_t ents_count;
|
||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 0);
|
||||
bool picked = false;
|
||||
|
||||
for (size_t j = 0; j < ents_count; j++) {
|
||||
ItemDrop *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||
const Position *p2 = ecs_get(it->world, ents[j], Position);
|
||||
Item *drop = 0;
|
||||
if ((drop = ecs_get_mut_if(it->world, ents[j], Item))) {
|
||||
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
|
||||
uint64_t ent_id = ents[j];
|
||||
|
||||
float dx = p2->x - p[i].x;
|
||||
float dy = p2->y - p[i].y;
|
||||
|
@ -330,23 +353,32 @@ void HarvestIntoContainers(ecs_iter_t *it) {
|
|||
if (range <= game_rules.item_pick_radius) {
|
||||
uint16_t drop_id = item_find(drop->kind);
|
||||
for (size_t k = 0; k < ITEMS_CONTAINER_SIZE; k += 1) {
|
||||
ItemDrop *item = &in->items[k];
|
||||
uint16_t item_id = item_find(item->kind);
|
||||
if (item_id != ASSET_INVALID && (item->quantity == 0 || (item->quantity != 0 && item->kind == drop->kind)) && item->quantity < item_max_quantity(drop_id)) {
|
||||
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
|
||||
item->quantity += picked_count;
|
||||
drop->quantity -= picked_count;
|
||||
item->kind = drop->kind;
|
||||
entity_wake(ents[j]);
|
||||
entity_wake(it->entities[i]);
|
||||
uint64_t item_slot_ent = in[i].items[k];
|
||||
Item *item = item_get_data(item_slot_ent);
|
||||
uint16_t item_id = item ? item_find(item->kind) : 0;
|
||||
if (!item || (item_id != ASSET_INVALID && (item->kind == drop->kind && item->durability == drop->durability) && item->quantity < item_max_quantity(drop_id))) {
|
||||
if (item) {
|
||||
uint32_t picked_count = zpl_max(0, drop->quantity);
|
||||
picked_count = zpl_clamp(picked_count, 0, item_max_quantity(drop_id) - item->quantity);
|
||||
item->quantity += picked_count;
|
||||
drop->quantity -= picked_count;
|
||||
|
||||
if (drop->quantity == 0)
|
||||
item_despawn(ents[j]);
|
||||
if (drop->quantity == 0) {
|
||||
item_despawn(ent_id);
|
||||
}
|
||||
} else if (!world_entity_valid(item_slot_ent)) {
|
||||
entity_wake(ent_id);
|
||||
item_show(ent_id, false);
|
||||
in[i].items[k] = ent_id;
|
||||
}
|
||||
entity_wake(it->entities[i]);
|
||||
picked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (picked) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ void SystemsImport(ecs_world_t *ecs) {
|
|||
ECS_SYSTEM(ecs, UseItem, EcsPostUpdate, components.Input, components.Position, components.Inventory, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, InspectContainers, EcsPostUpdate, components.Input, !components.IsInVehicle);
|
||||
ECS_SYSTEM(ecs, HarvestIntoContainers, EcsPostUpdate, components.ItemContainer, components.Position);
|
||||
ECS_SYSTEM(ecs, FurnaceCook, EcsPostUpdate, components.ItemContainer, components.Furnace, components.Position);
|
||||
ECS_SYSTEM(ecs, FurnaceCook, EcsPostUpdate, components.ItemContainer, components.Furnace, components.Position, components.Device);
|
||||
|
||||
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ static inline asset_id item_fix_kind(asset_id id) {
|
|||
|
||||
void item_show(uint64_t ent, bool show) {
|
||||
Classify *c = ecs_get_mut(world_ecs(), ent, Classify);
|
||||
librg_entity_visibility_global_set(world_tracker(), ent, show ? LIBRG_VISIBLITY_DEFAULT : LIBRG_VISIBLITY_NEVER);
|
||||
c->id = show ? EKIND_ITEM : EKIND_SERVER;
|
||||
}
|
||||
|
||||
|
@ -37,8 +38,25 @@ uint64_t item_spawn(asset_id kind, uint32_t qty) {
|
|||
.kind = item_fix_kind(kind),
|
||||
.quantity = qty,
|
||||
.merger_time = 0,
|
||||
.durability = 1.0f,
|
||||
};
|
||||
|
||||
item_desc *it = &items[item_find(kind)];
|
||||
|
||||
switch (it->attachment) {
|
||||
case UDATA_FUEL: {
|
||||
Fuel *f = ecs_get_mut(world_ecs(), e, Fuel);
|
||||
f->burn_time = it->fuel.burn_time;
|
||||
} break;
|
||||
case UDATA_INGREDIENT: {
|
||||
Ingredient *i = ecs_get_mut(world_ecs(), e, Ingredient);
|
||||
i->producer = it->ingredient.producer;
|
||||
i->product = it->ingredient.product;
|
||||
i->additional_ingredient = it->ingredient.additional_ingredient;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return (uint64_t)e;
|
||||
}
|
||||
|
||||
|
@ -51,15 +69,22 @@ item_id item_find(asset_id kind) {
|
|||
}
|
||||
|
||||
Item *item_get_data(uint64_t ent) {
|
||||
return ecs_get_mut(world_ecs(), ent, Item);
|
||||
if (!world_entity_valid(ent)) return NULL;
|
||||
// if (ecs_get(world_ecs(), ent, ItemAlreadyEdited)) return NULL;
|
||||
// ecs_add(world_ecs(), ent, ItemAlreadyEdited);
|
||||
return ecs_get_mut_if(world_ecs(), ent, Item);
|
||||
}
|
||||
|
||||
void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
|
||||
const Item *item_get_data_const(uint64_t ent) {
|
||||
if (!world_entity_valid(ent)) return NULL;
|
||||
return ecs_get(world_ecs(), ent, Item);
|
||||
}
|
||||
|
||||
void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t udata) {
|
||||
(void)ecs;
|
||||
Item *d = item_get_data(it->ent);
|
||||
uint16_t it_id = d->kind;
|
||||
if (e == 0) return;
|
||||
uint16_t it_id = item_find(it->kind);
|
||||
item_desc *desc = &items[it_id];
|
||||
if (it->ent == 0) return;
|
||||
switch (item_get_usage(it_id)) {
|
||||
case UKIND_HOLD: /* NOOP */ break;
|
||||
case UKIND_PLACE:{
|
||||
|
@ -71,7 +96,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
|
|||
|
||||
// NOTE(zaklaus): If we replace the same item, refund 1 qty and let it replace it
|
||||
if (item_asset_id == it_id) {
|
||||
d->quantity++;
|
||||
it->quantity++;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -81,7 +106,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
|
|||
return;
|
||||
}
|
||||
world_chunk_replace_block(l.chunk_id, l.id, blocks_find(desc->place.kind + (asset_id)udata));
|
||||
d->quantity--;
|
||||
it->quantity--;
|
||||
}break;
|
||||
|
||||
case UKIND_PLACE_ITEM:{
|
||||
|
@ -98,7 +123,7 @@ void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata) {
|
|||
ZPL_ASSERT(world_entity_valid(e));
|
||||
entity_set_position(e, p.x, p.y);
|
||||
|
||||
d->quantity--;
|
||||
it->quantity--;
|
||||
}break;
|
||||
|
||||
|
||||
|
|
|
@ -17,11 +17,17 @@ typedef enum {
|
|||
UKIND_PROXY,
|
||||
} item_usage;
|
||||
|
||||
typedef enum {
|
||||
UDATA_NONE,
|
||||
UDATA_FUEL,
|
||||
UDATA_INGREDIENT,
|
||||
} item_attachment;
|
||||
|
||||
typedef struct {
|
||||
asset_id kind;
|
||||
item_usage usage;
|
||||
item_attachment attachment;
|
||||
uint32_t max_quantity;
|
||||
bool unique;
|
||||
|
||||
// NOTE(zaklaus): usage data
|
||||
union {
|
||||
|
@ -38,6 +44,18 @@ typedef struct {
|
|||
asset_id id;
|
||||
} place_item;
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
float burn_time;
|
||||
} fuel;
|
||||
|
||||
struct {
|
||||
asset_id producer;
|
||||
asset_id product;
|
||||
asset_id additional_ingredient;
|
||||
} ingredient;
|
||||
};
|
||||
} item_desc;
|
||||
|
||||
typedef uint16_t item_id;
|
||||
|
@ -48,15 +66,11 @@ void item_show(uint64_t ent, bool show);
|
|||
uint64_t item_spawn(asset_id kind, uint32_t qty);
|
||||
void item_despawn(uint64_t id);
|
||||
|
||||
// NOTE: item ops
|
||||
void item_pickup(uint64_t ent, uint64_t item);
|
||||
void item_drop(uint64_t ent, uint64_t item);
|
||||
void item_merge(uint64_t item1, uint64_t item2);
|
||||
|
||||
// NOTE(zaklaus): items
|
||||
item_id item_find(asset_id kind);
|
||||
void item_use(ecs_world_t *ecs, ItemSlot *it, Position p, uint64_t udata);
|
||||
void item_use(ecs_world_t *ecs, ecs_entity_t e, Item *it, Position p, uint64_t udata);
|
||||
Item *item_get_data(uint64_t ent);
|
||||
const Item *item_get_data_const(uint64_t ent);
|
||||
|
||||
uint32_t item_max_quantity(item_id id);
|
||||
item_usage item_get_usage(item_id id);
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
static item_desc items[] = {
|
||||
{ .kind = 0, .max_quantity = 0, },
|
||||
ITEM_BLOCK(ASSET_DEMO_ICEMAKER, 64, ASSET_WATER),
|
||||
ITEM_INGREDIENT(ASSET_DEMO_ICEMAKER, 64, ASSET_FURNACE, ASSET_BELT, 0),
|
||||
ITEM_SELF(ASSET_FENCE, 64),
|
||||
ITEM_SELF(ASSET_WOOD, 64),
|
||||
ITEM_FUEL(ASSET_WOOD, 64, 15.0f),
|
||||
ITEM_HOLD(ASSET_TREE, 64),
|
||||
|
||||
ITEM_SELF_DIR(ASSET_BELT, 999),
|
||||
|
|
|
@ -4,13 +4,39 @@
|
|||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_HOLD,\
|
||||
.attachment = UDATA_NONE,\
|
||||
.max_quantity = qty,\
|
||||
}
|
||||
|
||||
#define ITEM_FUEL(asset, qty, fuel_value)\
|
||||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_HOLD,\
|
||||
.attachment = UDATA_FUEL,\
|
||||
.max_quantity = qty,\
|
||||
.fuel = {\
|
||||
.burn_time = fuel_value\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ITEM_INGREDIENT(asset, qty, _producer, _product, _additional)\
|
||||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_HOLD,\
|
||||
.attachment = UDATA_INGREDIENT,\
|
||||
.max_quantity = qty,\
|
||||
.ingredient = {\
|
||||
.producer = _producer,\
|
||||
.product = _product,\
|
||||
.additional_ingredient = _additional,\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ITEM_BLOCK(asset, qty, build_asset)\
|
||||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PLACE,\
|
||||
.attachment = UDATA_NONE,\
|
||||
.max_quantity = qty,\
|
||||
.place = {\
|
||||
.kind = build_asset,\
|
||||
|
@ -21,6 +47,7 @@
|
|||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PLACE,\
|
||||
.attachment = UDATA_NONE,\
|
||||
.max_quantity = qty,\
|
||||
.place = {\
|
||||
.kind = build_asset,\
|
||||
|
@ -32,6 +59,7 @@
|
|||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PROXY,\
|
||||
.attachment = UDATA_NONE,\
|
||||
.proxy = {\
|
||||
.id = proxy_id,\
|
||||
}\
|
||||
|
@ -41,6 +69,7 @@
|
|||
{\
|
||||
.kind = asset,\
|
||||
.usage = UKIND_PLACE_ITEM,\
|
||||
.attachment = UDATA_NONE,\
|
||||
.max_quantity = qty,\
|
||||
.place_item = {\
|
||||
.id = eid\
|
||||
|
|
|
@ -43,7 +43,7 @@ void buildmode_draw(void) {
|
|||
build_is_deletion_mode = !build_is_deletion_mode;
|
||||
}
|
||||
|
||||
ItemDrop *item = &e->items[e->selected_item];
|
||||
Item *item = &e->items[e->selected_item];
|
||||
|
||||
if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) {
|
||||
item_usage usage = 0;
|
||||
|
|
|
@ -4,7 +4,7 @@ typedef struct {
|
|||
|
||||
bool item_is_held;
|
||||
uint8_t held_item_idx;
|
||||
ItemDrop held_item;
|
||||
Item held_item;
|
||||
|
||||
bool is_inside;
|
||||
bool storage_action;
|
||||
|
@ -44,7 +44,7 @@ void inventory_draw_panel(entity_view *e, bool is_player, float sx, float sy){
|
|||
{
|
||||
debug_area_status area = check_mouse_area(x, y, 64, 64);
|
||||
Color color = RAYWHITE;
|
||||
ItemDrop *item = (is_player) ? &e->items[i] : &e->storage_items[i];
|
||||
Item *item = (is_player) ? &e->items[i] : &e->storage_items[i];
|
||||
|
||||
if (area == DAREA_HOVER) {
|
||||
color = YELLOW;
|
||||
|
|
|
@ -64,12 +64,12 @@ typedef struct entity_view {
|
|||
|
||||
// NOTE(zaklaus): inventory
|
||||
uint8_t has_items;
|
||||
ItemDrop items[ITEMS_INVENTORY_SIZE];
|
||||
Item items[ITEMS_INVENTORY_SIZE];
|
||||
uint8_t selected_item;
|
||||
|
||||
// NOTE(zaklaus): storage interface
|
||||
uint8_t has_storage_items;
|
||||
ItemDrop storage_items[ITEMS_CONTAINER_SIZE];
|
||||
Item storage_items[ITEMS_CONTAINER_SIZE];
|
||||
uint8_t storage_selected_item;
|
||||
|
||||
// NOTE(zaklaus): entity picking
|
||||
|
|
|
@ -62,7 +62,7 @@ void predict_receive_update(entity_view *d, entity_view *data) {
|
|||
data->tran_time = d->tran_time;
|
||||
}
|
||||
|
||||
#define ENTITY_DO_LERP_SP 1
|
||||
#define ENTITY_DO_LERP_SP 0
|
||||
|
||||
void lerp_entity_positions(uint64_t key, entity_view *data) {
|
||||
(void)key;
|
||||
|
|
|
@ -56,8 +56,8 @@ entity_view *world_build_entity_view(int64_t e) {
|
|||
view.heading = veh->heading;
|
||||
}
|
||||
|
||||
if (ecs_get(world_ecs(), e, ItemDrop)) {
|
||||
ItemDrop const* dr = ecs_get(world_ecs(), e, ItemDrop);
|
||||
if (ecs_get(world_ecs(), e, Item)) {
|
||||
Item const* dr = ecs_get(world_ecs(), e, Item);
|
||||
view.asset = dr->kind;
|
||||
view.quantity = dr->quantity;
|
||||
}
|
||||
|
@ -74,7 +74,8 @@ entity_view *world_build_entity_view(int64_t e) {
|
|||
view.has_items = true;
|
||||
|
||||
for (int i = 0; i < ITEMS_INVENTORY_SIZE; i += 1) {
|
||||
view.items[i] = inv->items[i];
|
||||
const Item *it = ecs_get(world_ecs(), inv->items[i], Item);
|
||||
view.items[i] = it ? *it : (Item){0};
|
||||
}
|
||||
|
||||
const Input *in = ecs_get(world_ecs(), e, Input);
|
||||
|
@ -89,7 +90,8 @@ entity_view *world_build_entity_view(int64_t e) {
|
|||
view.has_storage_items = true;
|
||||
|
||||
for (int i = 0; i < ITEMS_CONTAINER_SIZE; i += 1) {
|
||||
view.storage_items[i] = ic->items[i];
|
||||
const Item *it = ecs_get(world_ecs(), ic->items[i], Item);
|
||||
view.storage_items[i] = it ? *it : (Item){0};
|
||||
}
|
||||
|
||||
view.storage_selected_item = in->storage_selected_item;
|
||||
|
@ -590,7 +592,6 @@ int64_t *world_chunk_query_entities(int64_t e, size_t *ents_len, int8_t radius)
|
|||
ZPL_ASSERT_NOT_NULL(ents_len);
|
||||
static int64_t ents[UINT16_MAX];
|
||||
*ents_len = UINT16_MAX;
|
||||
librg_entity_radius_set(world.tracker, e, radius);
|
||||
librg_world_query(world.tracker, e, radius, ents, ents_len);
|
||||
return ents;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue