basic ai demo
parent
4fd2856a25
commit
1c68c73028
|
@ -24,6 +24,7 @@ add_library(eco2d-foundation STATIC
|
||||||
src/models/prefabs/splitter.c
|
src/models/prefabs/splitter.c
|
||||||
src/models/prefabs/craftbench.c
|
src/models/prefabs/craftbench.c
|
||||||
src/models/prefabs/assembler.c
|
src/models/prefabs/assembler.c
|
||||||
|
src/models/prefabs/creature.c
|
||||||
|
|
||||||
src/pkt/packet.c
|
src/pkt/packet.c
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "models/items.h"
|
#include "models/items.h"
|
||||||
#include "net/network.h"
|
#include "net/network.h"
|
||||||
|
|
||||||
|
#include "models/entity.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
ActExitGame(void) {
|
ActExitGame(void) {
|
||||||
game_request_close();
|
game_request_close();
|
||||||
|
@ -230,8 +232,7 @@ ActSpawnDemoNPCs(void) {
|
||||||
if (zpl_array_count(demo_npcs) >= 100000) return;
|
if (zpl_array_count(demo_npcs) >= 100000) return;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 1000; i++) {
|
for (uint32_t i = 0; i < 1000; i++) {
|
||||||
uint64_t e = entity_spawn(EKIND_DEMO_NPC);
|
uint64_t e = entity_spawn_id(ASSET_CREATURE);
|
||||||
ecs_add(world_ecs(), e, DemoNPC);
|
|
||||||
Position *pos = ecs_get_mut(world_ecs(), e, Position);
|
Position *pos = ecs_get_mut(world_ecs(), e, Position);
|
||||||
pos->x=(float)(rand() % world_dim());
|
pos->x=(float)(rand() % world_dim());
|
||||||
pos->y=(float)(rand() % world_dim());
|
pos->y=(float)(rand() % world_dim());
|
||||||
|
|
|
@ -28,6 +28,8 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
|
||||||
case ASSET_SCREWS: return LoadTexEco("screws");
|
case ASSET_SCREWS: return LoadTexEco("screws");
|
||||||
case ASSET_LOG: return LoadTexEco("log");
|
case ASSET_LOG: return LoadTexEco("log");
|
||||||
case ASSET_PLANK: return LoadTexEco("plank");
|
case ASSET_PLANK: return LoadTexEco("plank");
|
||||||
|
case ASSET_CREATURE: return GenColorEco(YELLOW);
|
||||||
|
case ASSET_CREATURE_FOOD: return GenColorEco(GREEN);
|
||||||
|
|
||||||
// NOTE(zaklaus): blocks
|
// NOTE(zaklaus): blocks
|
||||||
case ASSET_FENCE: return LoadTexEco("fence");
|
case ASSET_FENCE: return LoadTexEco("fence");
|
||||||
|
|
|
@ -2,7 +2,49 @@
|
||||||
|
|
||||||
#define ASSET_INVALID 0xFF
|
#define ASSET_INVALID 0xFF
|
||||||
|
|
||||||
#include "assets_ids.lst"
|
#define _ASSETS\
|
||||||
|
X(ASSET_EMPTY)\
|
||||||
|
X(ASSET_BLANK)\
|
||||||
|
X(ASSET_BLOCK_FRAME)\
|
||||||
|
X(ASSET_BUILDMODE_HIGHLIGHT)\
|
||||||
|
X(ASSET_PLAYER)\
|
||||||
|
X(ASSET_THING)\
|
||||||
|
X(ASSET_CREATURE)\
|
||||||
|
X(ASSET_CREATURE_FOOD)\
|
||||||
|
X(ASSET_CHEST)\
|
||||||
|
X(ASSET_SPLITTER)\
|
||||||
|
X(ASSET_ASSEMBLER)\
|
||||||
|
X(ASSET_FURNACE)\
|
||||||
|
X(ASSET_CRAFTBENCH)\
|
||||||
|
X(ASSET_BLUEPRINT_BEGIN)\
|
||||||
|
X(ASSET_BLUEPRINT)\
|
||||||
|
X(ASSET_BLUEPRINT_DEMO_HOUSE)\
|
||||||
|
X(ASSET_BLUEPRINT_END)\
|
||||||
|
X(ASSET_FENCE)\
|
||||||
|
X(ASSET_DEV)\
|
||||||
|
X(ASSET_GROUND)\
|
||||||
|
X(ASSET_DIRT)\
|
||||||
|
X(ASSET_WATER)\
|
||||||
|
X(ASSET_LAVA)\
|
||||||
|
X(ASSET_WALL)\
|
||||||
|
X(ASSET_HILL)\
|
||||||
|
X(ASSET_HILL_SNOW)\
|
||||||
|
X(ASSET_HOLE)\
|
||||||
|
X(ASSET_WOOD)\
|
||||||
|
X(ASSET_TREE)\
|
||||||
|
X(ASSET_COAL)\
|
||||||
|
X(ASSET_IRON_ORE)\
|
||||||
|
X(ASSET_IRON_INGOT)\
|
||||||
|
X(ASSET_IRON_PLATES)\
|
||||||
|
X(ASSET_SCREWS)\
|
||||||
|
X(ASSET_LOG)\
|
||||||
|
X(ASSET_PLANK)\
|
||||||
|
X(ASSET_TEST_TALL)\
|
||||||
|
X(ASSET_BELT)\
|
||||||
|
X(ASSET_BELT_LEFT)\
|
||||||
|
X(ASSET_BELT_RIGHT)\
|
||||||
|
X(ASSET_BELT_UP)\
|
||||||
|
X(ASSET_BELT_DOWN)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define X(idx) idx,
|
#define X(idx) idx,
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
#define _ASSETS\
|
|
||||||
X(ASSET_EMPTY)\
|
|
||||||
X(ASSET_BLANK)\
|
|
||||||
X(ASSET_BLOCK_FRAME)\
|
|
||||||
X(ASSET_BUILDMODE_HIGHLIGHT)\
|
|
||||||
X(ASSET_PLAYER)\
|
|
||||||
X(ASSET_THING)\
|
|
||||||
X(ASSET_CHEST)\
|
|
||||||
X(ASSET_SPLITTER)\
|
|
||||||
X(ASSET_ASSEMBLER)\
|
|
||||||
X(ASSET_FURNACE)\
|
|
||||||
X(ASSET_CRAFTBENCH)\
|
|
||||||
X(ASSET_BLUEPRINT_BEGIN)\
|
|
||||||
X(ASSET_BLUEPRINT)\
|
|
||||||
X(ASSET_BLUEPRINT_DEMO_HOUSE)\
|
|
||||||
X(ASSET_BLUEPRINT_END)\
|
|
||||||
X(ASSET_FENCE)\
|
|
||||||
X(ASSET_DEV)\
|
|
||||||
X(ASSET_GROUND)\
|
|
||||||
X(ASSET_DIRT)\
|
|
||||||
X(ASSET_WATER)\
|
|
||||||
X(ASSET_LAVA)\
|
|
||||||
X(ASSET_WALL)\
|
|
||||||
X(ASSET_HILL)\
|
|
||||||
X(ASSET_HILL_SNOW)\
|
|
||||||
X(ASSET_HOLE)\
|
|
||||||
X(ASSET_WOOD)\
|
|
||||||
X(ASSET_TREE)\
|
|
||||||
X(ASSET_COAL)\
|
|
||||||
X(ASSET_IRON_ORE)\
|
|
||||||
X(ASSET_IRON_INGOT)\
|
|
||||||
X(ASSET_IRON_PLATES)\
|
|
||||||
X(ASSET_SCREWS)\
|
|
||||||
X(ASSET_LOG)\
|
|
||||||
X(ASSET_PLANK)\
|
|
||||||
X(ASSET_TEST_TALL)\
|
|
||||||
X(ASSET_BELT)\
|
|
||||||
X(ASSET_BELT_LEFT)\
|
|
||||||
X(ASSET_BELT_RIGHT)\
|
|
||||||
X(ASSET_BELT_UP)\
|
|
||||||
X(ASSET_BELT_DOWN)
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ static asset assets[] = {
|
||||||
ASSET_TEX(ASSET_LOG),
|
ASSET_TEX(ASSET_LOG),
|
||||||
ASSET_TEX(ASSET_PLANK),
|
ASSET_TEX(ASSET_PLANK),
|
||||||
ASSET_TEX(ASSET_CHEST),
|
ASSET_TEX(ASSET_CHEST),
|
||||||
|
ASSET_TEX(ASSET_CREATURE),
|
||||||
|
ASSET_TEX(ASSET_CREATURE_FOOD),
|
||||||
ASSET_TEX(ASSET_FURNACE),
|
ASSET_TEX(ASSET_FURNACE),
|
||||||
ASSET_TEX(ASSET_SPLITTER),
|
ASSET_TEX(ASSET_SPLITTER),
|
||||||
ASSET_TEX(ASSET_ASSEMBLER),
|
ASSET_TEX(ASSET_ASSEMBLER),
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "models/prefabs/craftbench.h"
|
#include "models/prefabs/craftbench.h"
|
||||||
#include "models/prefabs/splitter.h"
|
#include "models/prefabs/splitter.h"
|
||||||
#include "models/prefabs/assembler.h"
|
#include "models/prefabs/assembler.h"
|
||||||
|
#include "models/prefabs/creature.h"
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
asset_id id;
|
asset_id id;
|
||||||
|
@ -17,6 +18,7 @@ static struct {
|
||||||
{ .id = ASSET_SPLITTER, .proc = splitter_spawn },
|
{ .id = ASSET_SPLITTER, .proc = splitter_spawn },
|
||||||
{ .id = ASSET_ASSEMBLER, .proc = assembler_spawn },
|
{ .id = ASSET_ASSEMBLER, .proc = assembler_spawn },
|
||||||
{ .id = ASSET_BLUEPRINT, .proc_udata = blueprint_spawn_udata },
|
{ .id = ASSET_BLUEPRINT, .proc_udata = blueprint_spawn_udata },
|
||||||
|
{ .id = ASSET_CREATURE, .proc = creature_spawn },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_ENTITY_SPAWNDEFS ((sizeof(entity_spawnlist))/(sizeof(entity_spawnlist[0])))
|
#define MAX_ENTITY_SPAWNDEFS ((sizeof(entity_spawnlist))/(sizeof(entity_spawnlist[0])))
|
||||||
|
|
|
@ -28,6 +28,7 @@ static item_desc items[] = {
|
||||||
ITEM_ENT(ASSET_FURNACE, 32, ASSET_FURNACE),
|
ITEM_ENT(ASSET_FURNACE, 32, ASSET_FURNACE),
|
||||||
ITEM_ENT(ASSET_SPLITTER, 32, ASSET_SPLITTER),
|
ITEM_ENT(ASSET_SPLITTER, 32, ASSET_SPLITTER),
|
||||||
ITEM_ENT(ASSET_ASSEMBLER, 32, ASSET_ASSEMBLER),
|
ITEM_ENT(ASSET_ASSEMBLER, 32, ASSET_ASSEMBLER),
|
||||||
|
ITEM_ENT(ASSET_CREATURE, 32, ASSET_CREATURE),
|
||||||
|
|
||||||
ITEM_HOLD(ASSET_IRON_ORE, 64),
|
ITEM_HOLD(ASSET_IRON_ORE, 64),
|
||||||
ITEM_HOLD(ASSET_IRON_INGOT, 64),
|
ITEM_HOLD(ASSET_IRON_INGOT, 64),
|
||||||
|
@ -35,4 +36,5 @@ static item_desc items[] = {
|
||||||
ITEM_HOLD(ASSET_SCREWS, 64),
|
ITEM_HOLD(ASSET_SCREWS, 64),
|
||||||
ITEM_HOLD(ASSET_LOG, 64),
|
ITEM_HOLD(ASSET_LOG, 64),
|
||||||
ITEM_HOLD(ASSET_PLANK, 64),
|
ITEM_HOLD(ASSET_PLANK, 64),
|
||||||
|
ITEM_HOLD(ASSET_CREATURE_FOOD, 1),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,51 +1,15 @@
|
||||||
#include "models/components.h"
|
#include "models/components.h"
|
||||||
|
|
||||||
ECS_COMPONENT_DECLARE(Vector2D);
|
|
||||||
ECS_COMPONENT_DECLARE(Position);
|
|
||||||
ECS_COMPONENT_DECLARE(Velocity);
|
#define X(comp) ECS_COMPONENT_DECLARE(comp);
|
||||||
ECS_COMPONENT_DECLARE(Chunk);
|
_COMPS
|
||||||
ECS_COMPONENT_DECLARE(Drawable);
|
#undef X
|
||||||
ECS_COMPONENT_DECLARE(Input);
|
|
||||||
ECS_COMPONENT_DECLARE(ClientInfo);
|
|
||||||
ECS_COMPONENT_DECLARE(Health);
|
|
||||||
ECS_COMPONENT_DECLARE(Classify);
|
|
||||||
ECS_COMPONENT_DECLARE(Vehicle);
|
|
||||||
ECS_COMPONENT_DECLARE(IsInVehicle);
|
|
||||||
ECS_COMPONENT_DECLARE(Item);
|
|
||||||
ECS_COMPONENT_DECLARE(BlockHarvest);
|
|
||||||
ECS_COMPONENT_DECLARE(Inventory);
|
|
||||||
ECS_COMPONENT_DECLARE(ItemContainer);
|
|
||||||
ECS_COMPONENT_DECLARE(Producer);
|
|
||||||
ECS_COMPONENT_DECLARE(EnergySource);
|
|
||||||
ECS_COMPONENT_DECLARE(ItemRouter);
|
|
||||||
ECS_COMPONENT_DECLARE(Device);
|
|
||||||
ECS_COMPONENT_DECLARE(Blueprint);
|
|
||||||
ECS_COMPONENT_DECLARE(DemoNPC);
|
|
||||||
ECS_COMPONENT_DECLARE(StreamInfo);
|
|
||||||
|
|
||||||
void ComponentsImport(ecs_world_t *ecs) {
|
void ComponentsImport(ecs_world_t *ecs) {
|
||||||
ECS_MODULE(ecs, Components);
|
ECS_MODULE(ecs, Components);
|
||||||
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Vector2D);
|
#define X(comp) ECS_COMPONENT_DEFINE(ecs, comp);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Position);
|
_COMPS
|
||||||
ECS_COMPONENT_DEFINE(ecs, Velocity);
|
#undef X
|
||||||
ECS_COMPONENT_DEFINE(ecs, Chunk);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Drawable);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Input);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, ClientInfo);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Health);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Classify);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Vehicle);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, IsInVehicle);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Item);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, BlockHarvest);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Inventory);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, ItemContainer);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Producer);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, EnergySource);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, ItemRouter);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Device);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Blueprint);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, DemoNPC);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, StreamInfo);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,27 +185,44 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {char _unused;} DemoNPC;
|
typedef struct {char _unused;} DemoNPC;
|
||||||
|
|
||||||
extern ECS_COMPONENT_DECLARE(Vector2D);
|
typedef struct {
|
||||||
extern ECS_COMPONENT_DECLARE(Position);
|
int16_t hunger_satisfied;
|
||||||
extern ECS_COMPONENT_DECLARE(Velocity);
|
int16_t mating_satisfied;
|
||||||
extern ECS_COMPONENT_DECLARE(Chunk);
|
int16_t life_remaining;
|
||||||
extern ECS_COMPONENT_DECLARE(Drawable);
|
} Creature;
|
||||||
extern ECS_COMPONENT_DECLARE(Input);
|
|
||||||
extern ECS_COMPONENT_DECLARE(ClientInfo);
|
typedef struct { char _unused; } SeeksFood;
|
||||||
extern ECS_COMPONENT_DECLARE(Health);
|
typedef struct { char _unused; } SeeksCompanion;
|
||||||
extern ECS_COMPONENT_DECLARE(Classify);
|
|
||||||
extern ECS_COMPONENT_DECLARE(Vehicle);
|
#define _COMPS\
|
||||||
extern ECS_COMPONENT_DECLARE(IsInVehicle);
|
X(Vector2D)\
|
||||||
extern ECS_COMPONENT_DECLARE(Item);
|
X(Position)\
|
||||||
extern ECS_COMPONENT_DECLARE(BlockHarvest);
|
X(Velocity)\
|
||||||
extern ECS_COMPONENT_DECLARE(Inventory);
|
X(Chunk)\
|
||||||
extern ECS_COMPONENT_DECLARE(ItemContainer);
|
X(Drawable)\
|
||||||
extern ECS_COMPONENT_DECLARE(Producer);
|
X(Input)\
|
||||||
extern ECS_COMPONENT_DECLARE(EnergySource);
|
X(ClientInfo)\
|
||||||
extern ECS_COMPONENT_DECLARE(ItemRouter);
|
X(Health)\
|
||||||
extern ECS_COMPONENT_DECLARE(Device);
|
X(Classify)\
|
||||||
extern ECS_COMPONENT_DECLARE(Blueprint);
|
X(Vehicle)\
|
||||||
extern ECS_COMPONENT_DECLARE(DemoNPC);
|
X(IsInVehicle)\
|
||||||
extern ECS_COMPONENT_DECLARE(StreamInfo);
|
X(Item)\
|
||||||
|
X(BlockHarvest)\
|
||||||
|
X(Inventory)\
|
||||||
|
X(ItemContainer)\
|
||||||
|
X(Producer)\
|
||||||
|
X(EnergySource)\
|
||||||
|
X(ItemRouter)\
|
||||||
|
X(Device)\
|
||||||
|
X(Blueprint)\
|
||||||
|
X(DemoNPC)\
|
||||||
|
X(Creature)\
|
||||||
|
X(SeeksFood)\
|
||||||
|
X(SeeksCompanion)\
|
||||||
|
X(StreamInfo)
|
||||||
|
|
||||||
|
#define X(comp) extern ECS_COMPONENT_DECLARE(comp);
|
||||||
|
_COMPS
|
||||||
|
#undef X
|
||||||
|
|
||||||
void ComponentsImport(ecs_world_t *ecs);
|
void ComponentsImport(ecs_world_t *ecs);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "creature.h"
|
||||||
|
#include "world/world.h"
|
||||||
|
|
||||||
|
#include "models/entity.h"
|
||||||
|
#include "world/entity_view.h"
|
||||||
|
#include "models/components.h"
|
||||||
|
|
||||||
|
uint64_t creature_spawn(void) {
|
||||||
|
ecs_entity_t e = entity_spawn(EKIND_DEMO_NPC);
|
||||||
|
|
||||||
|
Creature *c = ecs_get_mut_ex(world_ecs(), e, Creature);
|
||||||
|
c->hunger_satisfied = 0;
|
||||||
|
c->mating_satisfied = rand() % 1800;
|
||||||
|
c->life_remaining = 500 + rand() % 5200;
|
||||||
|
|
||||||
|
return (uint64_t)e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void creature_despawn(uint64_t ent_id) {
|
||||||
|
entity_despawn(ent_id);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "platform/system.h"
|
||||||
|
|
||||||
|
uint64_t creature_spawn(void);
|
||||||
|
void creature_despawn(uint64_t id);
|
|
@ -10,3 +10,164 @@ void DemoNPCMoveAround(ecs_iter_t *it) {
|
||||||
entity_wake(it->entities[i]);
|
entity_wake(it->entities[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define CREATURE_FOOD_SATISFY_FOR 200
|
||||||
|
#define CREATURE_MATING_SATISFY_FOR 300
|
||||||
|
#define CREATURE_INTERACT_RANGE 5625.0f
|
||||||
|
#define CREATURE_SEEK_FOOD_MOVEMENT_SPEED 0.98f
|
||||||
|
#define CREATURE_SEEK_MATE_MOVEMENT_SPEED 0.357f
|
||||||
|
#define CREATURE_SEEK_ROAM_MOVEMENT_SPEED 50.0f // *dt
|
||||||
|
|
||||||
|
void CreatureCheckNeeds(ecs_iter_t *it) {
|
||||||
|
Creature *c = ecs_field(it, Creature, 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
// check hunger
|
||||||
|
if (c[i].hunger_satisfied < 1) {
|
||||||
|
ecs_add(it->world, it->entities[i], SeeksFood);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check mating
|
||||||
|
if (c[i].mating_satisfied < 1) {
|
||||||
|
ecs_add(it->world, it->entities[i], SeeksCompanion);
|
||||||
|
}
|
||||||
|
|
||||||
|
// die of an old age
|
||||||
|
if (c[i].life_remaining < 1) {
|
||||||
|
entity_despawn(it->entities[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tick down needs
|
||||||
|
TICK_VAR(c[i].hunger_satisfied);
|
||||||
|
TICK_VAR(c[i].mating_satisfied);
|
||||||
|
TICK_VAR(c[i].life_remaining);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureSeekFood(ecs_iter_t *it) {
|
||||||
|
Creature *c = ecs_field(it, Creature, 1);
|
||||||
|
Position *p = ecs_field(it, Position, 2);
|
||||||
|
Velocity *v = ecs_field(it, Velocity, 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
size_t ents_count;
|
||||||
|
uint64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||||
|
|
||||||
|
float closest_ent_dist = ZPL_F32_MAX;
|
||||||
|
uint64_t closest_ent = 0;
|
||||||
|
Position *p2 = 0;
|
||||||
|
|
||||||
|
// find the closest item of kind ASSET_CREATURE_FOOD
|
||||||
|
for (size_t j = 0; j < ents_count; j++) {
|
||||||
|
Item *drop = 0;
|
||||||
|
uint64_t ent_id = ents[j];
|
||||||
|
if ((drop = ecs_get_mut_if_ex(it->world, ent_id, Item))) {
|
||||||
|
if (drop->kind != ASSET_CREATURE_FOOD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p2 = ecs_get_mut_ex(it->world, ent_id, Position);
|
||||||
|
float dx = p2->x - p[i].x;
|
||||||
|
float dy = p2->y - p[i].y;
|
||||||
|
float range = (dx*dx + dy*dy);
|
||||||
|
|
||||||
|
// item is close enough, eat it!
|
||||||
|
if (range < CREATURE_INTERACT_RANGE) {
|
||||||
|
drop->quantity--;
|
||||||
|
|
||||||
|
if (drop->quantity == 0)
|
||||||
|
item_despawn(ent_id);
|
||||||
|
|
||||||
|
c[i].hunger_satisfied = CREATURE_FOOD_SATISFY_FOR;
|
||||||
|
ecs_remove(it->world, it->entities[i], SeeksFood);
|
||||||
|
}
|
||||||
|
else if (range < closest_ent_dist)
|
||||||
|
closest_ent = ent_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// drift towards the item
|
||||||
|
if (closest_ent) {
|
||||||
|
float dx = p2->x - p[i].x;
|
||||||
|
float dy = p2->y - p[i].y;
|
||||||
|
float r = 1; //zpl_sqrt(dx*dx + dy*dy);
|
||||||
|
v[i].x = (dx/r) * CREATURE_SEEK_MATE_MOVEMENT_SPEED;
|
||||||
|
v[i].y = (dy/r) * CREATURE_SEEK_MATE_MOVEMENT_SPEED;
|
||||||
|
} else {
|
||||||
|
// die if no food is left
|
||||||
|
entity_despawn(it->entities[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureSeekCompanion(ecs_iter_t *it) {
|
||||||
|
Creature *c = ecs_field(it, Creature, 1);
|
||||||
|
Position *p = ecs_field(it, Position, 2);
|
||||||
|
Velocity *v = ecs_field(it, Velocity, 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
size_t ents_count;
|
||||||
|
uint64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||||
|
|
||||||
|
float closest_ent_dist = ZPL_F32_MAX;
|
||||||
|
uint64_t closest_ent = 0;
|
||||||
|
Position *p2 = 0;
|
||||||
|
|
||||||
|
// find the closest entity that also seeks a companion
|
||||||
|
for (size_t j = 0; j < ents_count; j++) {
|
||||||
|
uint64_t ent_id = ents[j];
|
||||||
|
if (ent_id != it->entities[i] && ecs_get_if(it->world, ent_id, SeeksCompanion)) {
|
||||||
|
p2 = ecs_get_mut_ex(it->world, ent_id, Position);
|
||||||
|
float dx = p2->x - p[i].x;
|
||||||
|
float dy = p2->y - p[i].y;
|
||||||
|
float range = (dx*dx + dy*dy);
|
||||||
|
|
||||||
|
// creature is close enough, mate them!
|
||||||
|
if (range < CREATURE_INTERACT_RANGE) {
|
||||||
|
// remove the need
|
||||||
|
c[i].mating_satisfied = CREATURE_MATING_SATISFY_FOR;
|
||||||
|
ecs_remove(it->world, it->entities[i], SeeksCompanion);
|
||||||
|
ecs_remove(it->world, ent_id, SeeksCompanion);
|
||||||
|
|
||||||
|
// spawn a new creature
|
||||||
|
uint64_t ch = entity_spawn_id(ASSET_CREATURE);
|
||||||
|
entity_set_position(ch, p[i].x, p[i].y);
|
||||||
|
}
|
||||||
|
else if (range < closest_ent_dist)
|
||||||
|
closest_ent = ent_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// drift towards the creature
|
||||||
|
if (closest_ent) {
|
||||||
|
float dx = p2->x - p[i].x;
|
||||||
|
float dy = p2->y - p[i].y;
|
||||||
|
float r = 1; //zpl_sqrt(dx*dx + dy*dy);
|
||||||
|
v[i].x = (dx/r) * CREATURE_SEEK_MATE_MOVEMENT_SPEED;
|
||||||
|
v[i].y = (dy/r) * CREATURE_SEEK_MATE_MOVEMENT_SPEED;
|
||||||
|
entity_wake(it->entities[i]);
|
||||||
|
} else {
|
||||||
|
// no companion is found, let's try again later.
|
||||||
|
c[i].mating_satisfied = CREATURE_MATING_SATISFY_FOR;
|
||||||
|
ecs_remove(it->world, it->entities[i], SeeksCompanion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureRoamAround(ecs_iter_t *it) {
|
||||||
|
Velocity *v = ecs_field(it, Velocity, 1);
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
float d = zpl_quake_rsqrt(v[i].x*v[i].x + v[i].y*v[i].y);
|
||||||
|
if (zpl_abs(v[i].x) < 0.1f)
|
||||||
|
v[i].x = (float)(rand() % 5);
|
||||||
|
if (zpl_abs(v[i].y) < 0.1f)
|
||||||
|
v[i].y = (float)(rand() % 5);
|
||||||
|
v[i].x += (v[i].x*d*CREATURE_SEEK_ROAM_MOVEMENT_SPEED*safe_dt(it) + zpl_cos(zpl_to_radians((float)(rand()%360)))*game_rules.demo_npc_steer_speed*safe_dt(it));
|
||||||
|
v[i].y += (v[i].y*d*CREATURE_SEEK_ROAM_MOVEMENT_SPEED*safe_dt(it) + zpl_sin(zpl_to_radians((float)(rand()%360)))*game_rules.demo_npc_steer_speed*safe_dt(it));
|
||||||
|
|
||||||
|
entity_wake(it->entities[i]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ void ProduceItems(ecs_iter_t *it) {
|
||||||
entity_wake(it->entities[i]);
|
entity_wake(it->entities[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
producer[i].process_ticks_left = zpl_max(producer[i].process_ticks_left-1, 0) ;
|
TICK_VAR(producer[i].process_ticks_left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -271,6 +271,11 @@ void SystemsImport(ecs_world_t *ecs) {
|
||||||
ECS_SYSTEM_TICKED_EX(ecs, PushItemsOnNodes, EcsPostUpdate, 20, components.ItemContainer, components.Position, components.Device, components.ItemRouter);
|
ECS_SYSTEM_TICKED_EX(ecs, PushItemsOnNodes, EcsPostUpdate, 20, components.ItemContainer, components.Position, components.Device, components.ItemRouter);
|
||||||
ECS_SYSTEM_TICKED(ecs, BuildBlueprints, EcsPostUpdate, components.Blueprint, components.Device, components.Position);
|
ECS_SYSTEM_TICKED(ecs, BuildBlueprints, EcsPostUpdate, components.Blueprint, components.Device, components.Position);
|
||||||
|
|
||||||
|
ECS_SYSTEM_TICKED(ecs, CreatureCheckNeeds, EcsPostUpdate, components.Creature);
|
||||||
|
ECS_SYSTEM_TICKED(ecs, CreatureSeekFood, EcsPostUpdate, components.Creature, components.Position, components.Velocity, components.SeeksFood, !components.SeeksCompanion);
|
||||||
|
ECS_SYSTEM_TICKED(ecs, CreatureSeekCompanion, EcsPostUpdate, components.Creature, components.Position, components.Velocity, components.SeeksCompanion, !components.SeeksFood);
|
||||||
|
ECS_SYSTEM(ecs, CreatureRoamAround, EcsPostUpdate, components.Velocity, components.Creature, !components.SeeksFood, !components.SeeksCompanion);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
|
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
||||||
|
|
|
@ -5,4 +5,6 @@ static inline float safe_dt(ecs_iter_t *it) {
|
||||||
return zpl_min(it->delta_time, 0.03334f);
|
return zpl_min(it->delta_time, 0.03334f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TICK_VAR(var) (var) = zpl_max((var)-1, 0)
|
||||||
|
|
||||||
void SystemsImport(ecs_world_t *ecs);
|
void SystemsImport(ecs_world_t *ecs);
|
||||||
|
|
|
@ -144,6 +144,15 @@ int32_t worldgen_build(world_data *wld) {
|
||||||
entity_set_position(e, dest->x, dest->y);
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<RAND_RANGE(3852, 5964); i++) {
|
||||||
|
uint64_t e = item_spawn(ASSET_CREATURE_FOOD, 1);
|
||||||
|
|
||||||
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return WORLD_ERROR_NONE;
|
return WORLD_ERROR_NONE;
|
||||||
|
|
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