Files
PixelDefense/game/entity_factory.c
2024-02-05 10:11:54 +01:00

140 lines
4.4 KiB
C

#include "entity_factory.h"
#include "ai_actions.h"
ecs_entity_t entityCreateEmpty() {
ecs_entity_t e = ecs_new_id(ECS);
ecs_add_id(ECS, e, GameEntity);
return e;
}
ecs_entity_t entityCreateBaseUnit(const Position position, f32 size, Player player,
EntityType type, AnimType startAnim, Game *game) {
BzTileset *tileset = &game->tileset;
BzTileID tileID = getEntityTile(type);
TextureRegion region = {
tileset->tiles,
getTextureRect(tileID)
};
HitBox hitbox = getEntityHitBoxRec(tileID);
ecs_entity_t e = entityCreateEmpty();
ecs_set_ptr(ECS, e, Position, &position);
f32 scl = size / region.rec.width;
ecs_set(ECS, e, Size, {region.rec.width * scl, region.rec.height * scl});
hitbox.x *= scl;
hitbox.y *= scl;
hitbox.width *= scl;
hitbox.height *= scl;
ecs_set_ptr(ECS, e, HitBox, &hitbox);
BzSpatialGridID spatialID = bzSpatialGridInsert(game->entityGrid, &e,
position.x + hitbox.x, position.y + hitbox.y,
hitbox.width, hitbox.height);
ecs_set(ECS, e, SpatialGridID, { spatialID });
ecs_set(ECS, e, Rotation, { 0.0f });
ecs_set(ECS, e, Orientation, {0.0f});
ecs_set(ECS, e, Velocity, {});
ecs_set(ECS, e, Steering, {});
ecs_set(ECS, e, Owner, {player});
ecs_set_ptr(ECS, e, TextureRegion, &region);
if (startAnim != ANIM_NONE) {
ecs_set(ECS, e, Animation, {
.entityType = type,
.animType = startAnim,
.sequence = entityGetAnimationSequence(type, startAnim),
.tileset = tileset,
.curFrame = 0,
.elapsed = 0.0f,
});
}
ecs_set(ECS, e, BzBTState, {
.root = NULL,
.nodeStatePool = game->pools.btNodeState
});
ecs_set(ECS, e, AIBlackboard, {.entity = e});
ecs_add_id(ECS, e, Selectable);
ecs_set(ECS, e, Unit, {
.acceleration = 80.0f,
.maxSpeed = 15.0f,
.deceleration = 0.1f,
.unitType = type
});
ecs_set(ECS, e, ConsumePopCapacity, {1});
return e;
}
ecs_entity_t entityCreateSoldier(const Position position, Player player, Game *game) {
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_SOLDIER, ANIM_IDLE, game);
return e;
}
ecs_entity_t entityCreateWorker(const Position position, Player player, Game *game) {
BzTileset *tileset = &game->tileset;
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_WORKER, ANIM_IDLE, game);
ecs_set(ECS, e, Worker, {
.collectSpeed = 0.8f,
.depositSpeed = 0.2f,
.carryCapacity = 5,
});
ecs_entity_t right = entityCreateEmpty();
Arms arms = {.primary = right};
ecs_set_ptr(ECS, e, Arms, &arms);
ecs_set(ECS, right, Arm, {.offset = 45.0f, 4.5f});
ecs_set(ECS, right, Rotation, { 0.0f });
TextureRegion daggerRegion = {
tileset->tiles,
bzTilesetGetTileRegion(tileset, getItemTile(ITEM_AXE))
};
ecs_set_ptr(ECS, right, TextureRegion, &daggerRegion);
return e;
}
ecs_entity_t entityHire(EntityType type, Position position, Player player, Game *game) {
PlayerResources *playerRes = &game->playerResources[player];
i32 res[RES_COUNT] = {0, };
getEntityCost(type, res);
switch (type) {
case ENTITY_WORKER:
entityCreateWorker(position, player, game);
playerRes->food -= res[RES_FOOD];
playerRes->wood -= res[RES_WOOD];
playerRes->gold -= res[RES_GOLD];
default:
return 0;
}
}
void getEntityCost(EntityType type, i32 cost[RES_COUNT]) {
for (i32 i = 0; i < RES_COUNT; i++) {
cost[i] = 0;
}
switch (type) {
case ENTITY_WORKER:
cost[RES_FOOD] = 50;
break;
case ENTITY_SOLDIER:
cost[RES_FOOD] = 50;
cost[RES_GOLD] = 50;
break;
case ENTITY_WARRIOR:
cost[RES_FOOD] = 200;
cost[RES_GOLD] = 100;
break;
}
}
bool canAffordEntity(EntityType type, PlayerResources res) {
i32 needed[RES_COUNT] = {0, };
getEntityCost(type, needed);
if (needed[RES_WOOD] > res.wood) return false;
if (needed[RES_FOOD] > res.food) return false;
if (needed[RES_GOLD] > res.gold) return false;
return true;
}