213 lines
6.3 KiB
C
213 lines
6.3 KiB
C
#include "entity_factory.h"
|
|
|
|
#include "ai_actions.h"
|
|
#include "systems/systems.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, Unit *unit, 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(ECS, e, Position, {
|
|
position.x - size * 0.5f,
|
|
position.y + size * 0.5f,
|
|
});
|
|
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, ®ion);
|
|
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_add_id(ECS, e, Selectable);
|
|
Unit unitComp = {
|
|
.attackElapsed = 0.0f,
|
|
.attackCooldown = 1.0f,
|
|
.minDamage = 1.0f,
|
|
.maxDamage = 2.0f,
|
|
.acceleration = 80.0f,
|
|
.maxSpeed = 15.0f,
|
|
.deceleration = 0.1f,
|
|
.unitType = type
|
|
};
|
|
if (unit) {
|
|
*unit = unitComp;
|
|
} else {
|
|
ecs_set_ptr(ECS, e, Unit, &unitComp);
|
|
}
|
|
ecs_set(ECS, e, ConsumePopCapacity, {1});
|
|
return e;
|
|
}
|
|
|
|
ecs_entity_t entityCreateSoldier(const Position position, Player player, Game *game) {
|
|
Unit unit = {0};
|
|
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_SOLDIER, ANIM_IDLE, &unit, game);
|
|
ecs_set(ECS, e, Health, {
|
|
.startHP = 80.0f,
|
|
.hp = 80.0f,
|
|
.lastChanged = -1000.0f
|
|
});
|
|
unit.minDamage = 5.0f;
|
|
unit.maxDamage = 10.0f;
|
|
unit.attackCooldown = 1.0f;
|
|
ecs_set_ptr(ECS, e, Unit, &unit);
|
|
setAIBehaviour(e, game->BTs.unit, NULL);
|
|
return e;
|
|
}
|
|
ecs_entity_t entityCreateWarrior(const Position position, Player player, Game *game) {
|
|
Unit unit = {0};
|
|
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_WARRIOR, ANIM_IDLE, &unit, game);
|
|
ecs_set(ECS, e, Health, {
|
|
.startHP = 200.0f,
|
|
.hp = 200.0f,
|
|
.lastChanged = -1000.0f
|
|
});
|
|
unit.minDamage = 8.0f;
|
|
unit.maxDamage = 22.0f;
|
|
unit.attackCooldown = 1.8f;
|
|
ecs_set_ptr(ECS, e, Unit, &unit);
|
|
setAIBehaviour(e, game->BTs.unit, NULL);
|
|
return e;
|
|
}
|
|
|
|
ecs_entity_t entityCreateWorker(const Position position, Player player, Game *game) {
|
|
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_WORKER, ANIM_IDLE, NULL, game);
|
|
|
|
ecs_set(ECS, e, Worker, {
|
|
.collectSpeed = 0.8f,
|
|
.depositSpeed = 0.2f,
|
|
.carryCapacity = 5,
|
|
});
|
|
|
|
ecs_set(ECS, e, Health, {
|
|
.startHP = 20.0f,
|
|
.hp = 20.0f,
|
|
.lastChanged = -1000.0f
|
|
});
|
|
|
|
setAIBehaviour(e, game->BTs.unitEvasive, NULL);
|
|
|
|
return e;
|
|
}
|
|
|
|
ecs_entity_t entityCreateSwarmGoblin(const Position position, Player player, Game *game) {
|
|
Unit unit = {0};
|
|
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_GOBLIN, ANIM_IDLE, &unit, game);
|
|
ecs_set(ECS, e, Swarm, {
|
|
.currWaypoint = 0,
|
|
});
|
|
ecs_set(ECS, e, Health, {
|
|
.startHP = 40.0f,
|
|
.hp = 40.0f,
|
|
.lastChanged = -1000.0f
|
|
});
|
|
|
|
unit.minDamage = 5.0f;
|
|
unit.maxDamage = 10.0f;
|
|
unit.attackCooldown = 1.0f;
|
|
unit.maxSpeed = 16.0f;
|
|
ecs_set_ptr(ECS, e, Unit, &unit);
|
|
|
|
return e;
|
|
}
|
|
ecs_entity_t entityCreateSwarmOrc(const Position position, Player player, Game *game) {
|
|
Unit unit = {0};
|
|
ecs_entity_t e = entityCreateBaseUnit(position, 10.0f, player, ENTITY_ORC, ANIM_IDLE, &unit, game);
|
|
ecs_set(ECS, e, Swarm, {
|
|
.currWaypoint = 0,
|
|
});
|
|
ecs_set(ECS, e, Health, {
|
|
.startHP = 80.0f,
|
|
.hp = 80.0f,
|
|
.lastChanged = -1000.0f
|
|
});
|
|
|
|
unit.minDamage = 8.0f;
|
|
unit.maxDamage = 22.0f;
|
|
unit.attackCooldown = 1.8f;
|
|
unit.maxSpeed = 12.0f;
|
|
ecs_set_ptr(ECS, e, Unit, &unit);
|
|
|
|
return e;
|
|
}
|
|
|
|
ecs_entity_t entityCreate(EntityType type, Position position, Player player, Game *game) {
|
|
switch (type) {
|
|
case ENTITY_WORKER:
|
|
return entityCreateWorker(position, player, game);
|
|
case ENTITY_SOLDIER:
|
|
return entityCreateSoldier(position, player, game);
|
|
case ENTITY_WARRIOR:
|
|
return entityCreateWarrior(position, player, game);
|
|
case ENTITY_GOBLIN:
|
|
return entityCreateSwarmGoblin(position, player, game);
|
|
case ENTITY_ORC:
|
|
return entityCreateSwarmOrc(position, player, game);
|
|
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] = 20;
|
|
break;
|
|
case ENTITY_SOLDIER:
|
|
cost[RES_FOOD] = 10;
|
|
cost[RES_GOLD] = 20;
|
|
break;
|
|
case ENTITY_WARRIOR:
|
|
cost[RES_FOOD] = 20;
|
|
cost[RES_GOLD] = 50;
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
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;
|
|
}
|