Fixed up building enemies and items using componentsin the JSON.
This commit is contained in:
parent
9ce4fbd552
commit
222b39c403
13 changed files with 76 additions and 60 deletions
|
@ -4,7 +4,8 @@
|
||||||
"background": [30, 20, 75],
|
"background": [30, 20, 75],
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "Tile", "config": {"chr": "\ua66b"}},
|
{"type": "Tile", "config": {"chr": "\ua66b"}},
|
||||||
{"type": "Combat", "config": {"hp": 200, "damage": 15}}
|
{"type": "Combat", "config": {"hp": 200, "damage": 15}},
|
||||||
|
{"type": "EnemyConfig", "config": {"hearing_distance": 5}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"SNAKE": {
|
"SNAKE": {
|
||||||
|
@ -12,7 +13,8 @@
|
||||||
"background": [30, 20, 75],
|
"background": [30, 20, 75],
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "Tile", "config": {"chr": "\u06b1"}},
|
{"type": "Tile", "config": {"chr": "\u06b1"}},
|
||||||
{"type": "Combat", "config": {"hp": 20, "damage": 15}}
|
{"type": "Combat", "config": {"hp": 20, "damage": 15}},
|
||||||
|
{"type": "EnemyConfig", "config": {"hearing_distance": 6}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"GOBLIN": {
|
"GOBLIN": {
|
||||||
|
@ -21,7 +23,8 @@
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "LightSource", "config": {"strength": 70, "radius": 1.8}},
|
{"type": "LightSource", "config": {"strength": 70, "radius": 1.8}},
|
||||||
{"type": "Tile", "config": {"chr": "\u06bf"}},
|
{"type": "Tile", "config": {"chr": "\u06bf"}},
|
||||||
{"type": "Combat", "config": {"hp": 50, "damage": 35}}
|
{"type": "Combat", "config": {"hp": 50, "damage": 35}},
|
||||||
|
{"type": "EnemyConfig", "config": {"hearing_distance": 4}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"UNICORN": {
|
"UNICORN": {
|
||||||
|
@ -29,7 +32,8 @@
|
||||||
"background": [30, 20, 75],
|
"background": [30, 20, 75],
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "Tile", "config": {"chr": "\u17a5"}},
|
{"type": "Tile", "config": {"chr": "\u17a5"}},
|
||||||
{"type": "Combat", "config": {"hp": 2000, "damage": 5}}
|
{"type": "Combat", "config": {"hp": 100, "damage": 5}},
|
||||||
|
{"type": "EnemyConfig", "config": {"hearing_distance": 3}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"RAT": {
|
"RAT": {
|
||||||
|
@ -37,7 +41,8 @@
|
||||||
"background": [30, 20, 75],
|
"background": [30, 20, 75],
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "Tile", "config": {"chr": "\u08ac"}},
|
{"type": "Tile", "config": {"chr": "\u08ac"}},
|
||||||
{"type": "Combat", "config": {"hp": 10, "damage": 5}}
|
{"type": "Combat", "config": {"hp": 10, "damage": 5}},
|
||||||
|
{"type": "EnemyConfig", "config": {"hearing_distance": 10}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
"inventory_count": 1,
|
"inventory_count": 1,
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "LightSource", "config": {"strength": 70, "radius": 2.0}},
|
{"type": "LightSource", "config": {"strength": 70, "radius": 2.0}},
|
||||||
{"type": "Tile", "config": {"chr": "\u0f08"}},
|
{"type": "Tile", "config": {"chr": "\u0f08"}}
|
||||||
{"type": "Weapon", "config": {"damage": 35}}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"SWORD_RUSTY": {
|
"SWORD_RUSTY": {
|
||||||
|
@ -57,9 +56,8 @@
|
||||||
"description": "A torch on a wall you can't pick up.",
|
"description": "A torch on a wall you can't pick up.",
|
||||||
"inventory_count": 0,
|
"inventory_count": 0,
|
||||||
"components": [
|
"components": [
|
||||||
{"type": "Tile", "config": {"chr": "\u06bf"}},
|
{"type": "Tile", "config": {"chr": "\u077e"}},
|
||||||
{"type": "LightSource", "config": {"strength": 60, "radius": 1.8}}
|
{"type": "LightSource", "config": {"strength": 60, "radius": 1.8}}
|
||||||
],
|
]
|
||||||
"display": "☀"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "dinkyecs.hpp"
|
#include "dinkyecs.hpp"
|
||||||
#include "map.hpp"
|
|
||||||
#include "combat.hpp"
|
#include "combat.hpp"
|
||||||
#include "inventory.hpp"
|
#include "inventory.hpp"
|
||||||
#include <deque>
|
|
||||||
#include "tser.hpp"
|
#include "tser.hpp"
|
||||||
|
#include "config.hpp"
|
||||||
|
|
||||||
namespace components {
|
namespace components {
|
||||||
struct Player {
|
struct Player {
|
||||||
|
@ -41,7 +40,7 @@ namespace components {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EnemyConfig {
|
struct EnemyConfig {
|
||||||
int HEARING_DISTANCE;
|
int hearing_distance = 10;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Debug {
|
struct Debug {
|
||||||
|
@ -52,4 +51,27 @@ namespace components {
|
||||||
struct Weapon {
|
struct Weapon {
|
||||||
int damage = 0;
|
int damage = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void configure(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data) {
|
||||||
|
for(auto &comp : entity_data["components"]) {
|
||||||
|
json& config = comp["config"];
|
||||||
|
|
||||||
|
if(comp["type"] == "Weapon") {
|
||||||
|
world.set<Weapon>(entity, {config["damage"]});
|
||||||
|
} else if(comp["type"] == "LightSource") {
|
||||||
|
world.set<LightSource>(entity, {config["strength"], config["radius"]});
|
||||||
|
} else if(comp["type"] == "Loot") {
|
||||||
|
world.set<Loot>(entity, {config["amount"]});
|
||||||
|
} else if(comp["type"] == "Tile") {
|
||||||
|
world.set<Tile>(entity, {config["chr"]});
|
||||||
|
} else if(comp["type"] == "EnemyConfig") {
|
||||||
|
world.set<EnemyConfig>(entity, {config["hearing_distance"]});
|
||||||
|
} else if(comp["type"] == "Combat") {
|
||||||
|
world.set<Combat>(entity, {config["hp"], config["damage"]});
|
||||||
|
} else {
|
||||||
|
dbc::sentinel(fmt::format("ITEM COMPONENT TYPE MISSING: {}",
|
||||||
|
std::string(comp["type"])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
13
dbc.cpp
13
dbc.cpp
|
@ -2,17 +2,19 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
void dbc::log(const string &message) {
|
void dbc::log(const string &message) {
|
||||||
fmt::print("{}\n", message);
|
std::cerr << message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbc::sentinel(const string &message) {
|
void dbc::sentinel(const string &message) {
|
||||||
string err = fmt::format("[SENTINEL!] {}\n", message);
|
string err = fmt::format("[SENTINEL!] {}", message);
|
||||||
|
dbc::log(err);
|
||||||
throw dbc::SentinelError{err};
|
throw dbc::SentinelError{err};
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbc::pre(const string &message, bool test) {
|
void dbc::pre(const string &message, bool test) {
|
||||||
if(!test) {
|
if(!test) {
|
||||||
string err = fmt::format("[PRE!] {}\n", message);
|
string err = fmt::format("[PRE!] {}", message);
|
||||||
|
dbc::log(err);
|
||||||
throw dbc::PreCondError{err};
|
throw dbc::PreCondError{err};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +25,8 @@ void dbc::pre(const string &message, std::function<bool()> tester) {
|
||||||
|
|
||||||
void dbc::post(const string &message, bool test) {
|
void dbc::post(const string &message, bool test) {
|
||||||
if(!test) {
|
if(!test) {
|
||||||
string err = fmt::format("[POST!] {}\n", message);
|
string err = fmt::format("[POST!] {}", message);
|
||||||
|
dbc::log(err);
|
||||||
throw dbc::PostCondError{err};
|
throw dbc::PostCondError{err};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +38,7 @@ void dbc::post(const string &message, std::function<bool()> tester) {
|
||||||
void dbc::check(bool test, const string &message) {
|
void dbc::check(bool test, const string &message) {
|
||||||
if(!test) {
|
if(!test) {
|
||||||
string err = fmt::format("[CHECK!] {}\n", message);
|
string err = fmt::format("[CHECK!] {}\n", message);
|
||||||
fmt::println("{}", err);
|
dbc::log(err);
|
||||||
throw dbc::CheckError{err};
|
throw dbc::CheckError{err};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
gui.cpp
3
gui.cpp
|
@ -72,8 +72,7 @@ void InventoryUI::update_menu_list(Inventory& inventory) {
|
||||||
$menu_list.clear();
|
$menu_list.clear();
|
||||||
for(size_t i = 0; i < inventory.count(); i++) {
|
for(size_t i = 0; i < inventory.count(); i++) {
|
||||||
auto& item = inventory.get(i);
|
auto& item = inventory.get(i);
|
||||||
$menu_list.push_back(fmt::format("{} {} ({})",
|
$menu_list.push_back(fmt::format("{} ({})",
|
||||||
string(item.data["display"]),
|
|
||||||
string(item.data["name"]),
|
string(item.data["name"]),
|
||||||
item.count));
|
item.count));
|
||||||
|
|
||||||
|
|
22
matrix.hpp
22
matrix.hpp
|
@ -10,8 +10,15 @@ namespace matrix {
|
||||||
using std::vector, std::queue, std::array;
|
using std::vector, std::queue, std::array;
|
||||||
using std::min, std::max, std::floor;
|
using std::min, std::max, std::floor;
|
||||||
|
|
||||||
typedef vector<int> Row;
|
template<typename T>
|
||||||
typedef vector<Row> Matrix;
|
using BaseRow = vector<T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using Base = vector<BaseRow<T>>;
|
||||||
|
|
||||||
|
using Row = vector<int>;
|
||||||
|
using Matrix = vector<Row>;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just a quick thing to reset a matrix to a value.
|
* Just a quick thing to reset a matrix to a value.
|
||||||
|
@ -40,6 +47,17 @@ namespace matrix {
|
||||||
return mat.size();
|
return mat.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline Base<T> make_base(size_t width, size_t height) {
|
||||||
|
Base<T> result(height, BaseRow<T>(width));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matrix make(size_t width, size_t height) {
|
||||||
|
Matrix result(height, Row(width));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline size_t next_x(size_t x, size_t width) {
|
inline size_t next_x(size_t x, size_t width) {
|
||||||
return (x + 1) * ((x + 1) < width);
|
return (x + 1) * ((x + 1) < width);
|
||||||
}
|
}
|
||||||
|
|
5
save.cpp
5
save.cpp
|
@ -92,9 +92,4 @@ void save::load_configs(DinkyECS::World &world) {
|
||||||
world.set_the<GameConfig>({
|
world.set_the<GameConfig>({
|
||||||
game, enemies, items, tiles
|
game, enemies, items, tiles
|
||||||
});
|
});
|
||||||
|
|
||||||
auto enemy = game["enemy"];
|
|
||||||
world.set_the<EnemyConfig>({
|
|
||||||
enemy["HEARING_DISTANCE"]
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
1
save.hpp
1
save.hpp
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "components.hpp"
|
#include "components.hpp"
|
||||||
|
#include "map.hpp"
|
||||||
#include "dinkyecs.hpp"
|
#include "dinkyecs.hpp"
|
||||||
#include "tser.hpp"
|
#include "tser.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
TODAY'S GOAL:
|
TODAY'S GOAL:
|
||||||
|
|
||||||
|
* Goblins will be in the world and not move or are already dead.
|
||||||
* https://pkl-lang.org/
|
* https://pkl-lang.org/
|
||||||
* Check out https://github.com/stephenberry/glaze
|
* Check out https://github.com/stephenberry/glaze
|
||||||
* Things are still in walls because I +1 the x,y if they're colliding.
|
* Things are still in walls because I +1 the x,y if they're colliding.
|
||||||
|
|
|
@ -32,15 +32,17 @@ void System::lighting(DinkyECS::World &world, Map &game_map, LightRender &light,
|
||||||
|
|
||||||
void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {
|
void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {
|
||||||
// TODO: this will be on each enemy not a global thing
|
// TODO: this will be on each enemy not a global thing
|
||||||
const auto &config = world.get_the<EnemyConfig>();
|
|
||||||
const auto &player_position = world.get<Position>(player.entity);
|
const auto &player_position = world.get<Position>(player.entity);
|
||||||
game_map.set_target(player_position.location);
|
game_map.set_target(player_position.location);
|
||||||
game_map.make_paths();
|
game_map.make_paths();
|
||||||
|
|
||||||
world.query<Position, Motion>([&](const auto &ent, auto &position, auto &motion) {
|
world.query<Position, Motion>([&](const auto &ent, auto &position, auto &motion) {
|
||||||
if(ent != player.entity) {
|
if(ent != player.entity) {
|
||||||
|
dbc::check(world.has<EnemyConfig>(ent), "enemy is missing config");
|
||||||
|
const auto &config = world.get<EnemyConfig>(ent);
|
||||||
|
|
||||||
Point out = position.location; // copy
|
Point out = position.location; // copy
|
||||||
if(game_map.distance(out) < config.HEARING_DISTANCE) {
|
if(game_map.distance(out) < config.hearing_distance) {
|
||||||
game_map.neighbors(out);
|
game_map.neighbors(out);
|
||||||
motion = { int(out.x - position.location.x), int(out.y - position.location.y)};
|
motion = { int(out.x - position.location.x), int(out.y - position.location.y)};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,6 @@ TEST_CASE("all components can work in the world", "[components]") {
|
||||||
|
|
||||||
auto tile = world.get<Tile>(ent1);
|
auto tile = world.get<Tile>(ent1);
|
||||||
REQUIRE(tile.chr == "Z");
|
REQUIRE(tile.chr == "Z");
|
||||||
|
|
||||||
auto enemy = world.get<EnemyConfig>(ent1);
|
|
||||||
REQUIRE(enemy.HEARING_DISTANCE == 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("all components can be facts", "[components]") {
|
TEST_CASE("all components can be facts", "[components]") {
|
||||||
|
@ -72,9 +69,6 @@ TEST_CASE("all components can be facts", "[components]") {
|
||||||
|
|
||||||
auto tile = world.get_the<Tile>();
|
auto tile = world.get_the<Tile>();
|
||||||
REQUIRE(tile.chr == "Z");
|
REQUIRE(tile.chr == "Z");
|
||||||
|
|
||||||
auto enemy = world.get_the<EnemyConfig>();
|
|
||||||
REQUIRE(enemy.HEARING_DISTANCE == 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("confirm combat works", "[components]") {
|
TEST_CASE("confirm combat works", "[components]") {
|
||||||
|
|
|
@ -86,7 +86,7 @@ TEST_CASE("thrash matrix iterators", "[matrix]") {
|
||||||
size_t width = Random::uniform<size_t>(1, 100);
|
size_t width = Random::uniform<size_t>(1, 100);
|
||||||
size_t height = Random::uniform<size_t>(1, 100);
|
size_t height = Random::uniform<size_t>(1, 100);
|
||||||
|
|
||||||
Matrix test(width, matrix::Row(height));
|
Matrix test(height, matrix::Row(width));
|
||||||
random_matrix(test);
|
random_matrix(test);
|
||||||
|
|
||||||
// first make a randomized matrix
|
// first make a randomized matrix
|
||||||
|
|
|
@ -168,28 +168,6 @@ void WorldBuilder::generate_map() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void configure_components(DinkyECS::World &world, DinkyECS::Entity entity, json& entity_data) {
|
|
||||||
for(auto &comp : entity_data["components"]) {
|
|
||||||
json& config = comp["config"];
|
|
||||||
|
|
||||||
if(comp["type"] == "Weapon") {
|
|
||||||
world.set<Weapon>(entity, {config["damage"]});
|
|
||||||
} else if(comp["type"] == "LightSource") {
|
|
||||||
world.set<LightSource>(entity, {config["strength"], config["radius"]});
|
|
||||||
} else if(comp["type"] == "Loot") {
|
|
||||||
world.set<Loot>(entity, {config["amount"]});
|
|
||||||
} else if(comp["type"] == "Tile") {
|
|
||||||
world.set<Tile>(entity, {config["chr"]});
|
|
||||||
} else if(comp["type"] == "EnemyConfig") {
|
|
||||||
world.set<EnemyConfig>(entity, {config["hearing_distance"]});
|
|
||||||
} else if(comp["type"] == "Combat") {
|
|
||||||
world.set<Combat>(entity, {config["hp"], config["damage"]});
|
|
||||||
} else {
|
|
||||||
dbc::sentinel(format("ITEM COMPONENT TYPE MISSING: {}",
|
|
||||||
std::string(comp["type"])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string name, int in_room) {
|
DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string name, int in_room) {
|
||||||
auto &config = world.get_the<GameConfig>();
|
auto &config = world.get_the<GameConfig>();
|
||||||
|
@ -203,7 +181,7 @@ DinkyECS::Entity place_item(DinkyECS::World &world, Map &game_map, std::string n
|
||||||
}
|
}
|
||||||
|
|
||||||
if(item_data.contains("components")) {
|
if(item_data.contains("components")) {
|
||||||
configure_components(world, item, item_data);
|
components::configure(world, item, item_data);
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +195,7 @@ DinkyECS::Entity place_combatant(DinkyECS::World &world, Map &game_map, std::str
|
||||||
world.set<Motion>(enemy, {0,0});
|
world.set<Motion>(enemy, {0,0});
|
||||||
|
|
||||||
if(enemy_data.contains("components")) {
|
if(enemy_data.contains("components")) {
|
||||||
configure_components(world, enemy, enemy_data);
|
components::configure(world, enemy, enemy_data);
|
||||||
}
|
}
|
||||||
return enemy;
|
return enemy;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue