Created a combat system to start with and also added a 'HEARING' mechanic where enemies can hear you from a certain distance before moving to you.
This commit is contained in:
parent
753bc70b77
commit
9102bdc8ad
9 changed files with 70 additions and 24 deletions
14
combat.cpp
Normal file
14
combat.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "combat.hpp"
|
||||
#include "rand.hpp"
|
||||
|
||||
int Combat::fight(Combat &target) {
|
||||
int attack = Random::uniform<int>(0,1);
|
||||
int my_dmg = 0;
|
||||
|
||||
if(attack) {
|
||||
my_dmg = Random::uniform<int>(1, damage);
|
||||
target.hp -= my_dmg;
|
||||
}
|
||||
|
||||
return my_dmg;
|
||||
}
|
11
combat.hpp
Normal file
11
combat.hpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "components.hpp"
|
||||
|
||||
struct Combat {
|
||||
int hp;
|
||||
int damage;
|
||||
bool dead;
|
||||
|
||||
int fight(Combat &target);
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "dinkyecs.hpp"
|
||||
#include "map.hpp"
|
||||
#include "combat.hpp"
|
||||
#include <deque>
|
||||
|
||||
namespace Components {
|
||||
|
@ -17,11 +18,6 @@ namespace Components {
|
|||
int dy;
|
||||
};
|
||||
|
||||
struct Combat {
|
||||
int hp;
|
||||
int damage;
|
||||
};
|
||||
|
||||
struct Treasure {
|
||||
int amount;
|
||||
};
|
||||
|
|
1
gui.cpp
1
gui.cpp
|
@ -164,6 +164,7 @@ void GUI::run_systems() {
|
|||
System::enemy_pathing($world, $game_map, player);
|
||||
System::motion($world, $game_map);
|
||||
System::combat($world, player);
|
||||
System::death($world);
|
||||
}
|
||||
|
||||
void GUI::resize_map(int new_size) {
|
||||
|
|
1
map.hpp
1
map.hpp
|
@ -57,6 +57,7 @@ public:
|
|||
int limit() { return $limit; }
|
||||
size_t width() { return $walls[0].size(); }
|
||||
size_t height() { return $walls.size(); }
|
||||
int distance(Point to) { return $paths[to.y][to.x]; }
|
||||
Room &room(size_t at) {
|
||||
return $rooms[at];
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ roguish = executable('roguish', [
|
|||
'gui.cpp',
|
||||
'rand.cpp',
|
||||
'collider.cpp',
|
||||
'combat.cpp',
|
||||
'systems.cpp',
|
||||
],
|
||||
dependencies: dependencies)
|
||||
|
|
|
@ -10,7 +10,9 @@ TODO:
|
|||
* Write a test that generates a ton of maps then confirms there's a path from one room to every other room?
|
||||
* Lua integration?
|
||||
|
||||
* Combat system and simple loot system.
|
||||
* BUG: If map is < 90 zome out crashes.
|
||||
|
||||
* Simple loot system.
|
||||
* Actually render FTXUI ansi output instead of the gui.cpp hack.
|
||||
* Remove entity from world, _or_ mark them dead, switch their icon, and make them an entity the player walks over?
|
||||
* Bring back sounds, check out SoLoud.
|
||||
|
|
53
systems.cpp
53
systems.cpp
|
@ -10,6 +10,8 @@ using namespace fmt;
|
|||
|
||||
using namespace Components;
|
||||
|
||||
#define HEARING_DISTANCE 8
|
||||
|
||||
void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {
|
||||
const auto &player_position = world.component<Position>(player.entity);
|
||||
game_map.set_target(player_position.location);
|
||||
|
@ -17,10 +19,12 @@ void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player
|
|||
|
||||
world.system<Position, Motion>([&](const auto &ent, auto &position, auto &motion) {
|
||||
if(ent != player.entity) {
|
||||
Point out = position.location;
|
||||
Point out = position.location; // copy
|
||||
if(game_map.distance(out) < HEARING_DISTANCE) {
|
||||
game_map.neighbors(out, false);
|
||||
motion = { int(out.x - position.location.x), int(out.y - position.location.y)};
|
||||
}
|
||||
}
|
||||
});
|
||||
game_map.clear_target(player_position.location);
|
||||
}
|
||||
|
@ -64,6 +68,22 @@ void System::motion(DinkyECS::World &world, Map &game_map) {
|
|||
});
|
||||
}
|
||||
|
||||
void System::death(DinkyECS::World &world) {
|
||||
auto &collider = world.get<spatial_map>();
|
||||
|
||||
world.system<Position, Combat>([&](const auto &ent, auto &position, auto &combat) {
|
||||
// bring out yer dead
|
||||
if(combat.hp <= 0 && !combat.dead) {
|
||||
combat.dead = true;
|
||||
// take them out of collision map
|
||||
collider.remove(position.location);
|
||||
|
||||
// remove their motion so they're dead
|
||||
world.remove<Motion>(ent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void System::combat(DinkyECS::World &world, Player &player) {
|
||||
auto& collider = world.get<spatial_map>();
|
||||
|
@ -77,25 +97,24 @@ void System::combat(DinkyECS::World &world, Player &player) {
|
|||
if(found) {
|
||||
for(auto entity : nearby) {
|
||||
auto& enemy_combat = world.component<Combat>(entity);
|
||||
int player_dmg = Random::uniform<int>(1, enemy_combat.damage);
|
||||
enemy_combat.hp -= player_dmg;
|
||||
log.log(format("YOU HIT {} damage! Enemy has {} HP left.",
|
||||
player_dmg, enemy_combat.hp));
|
||||
int player_dmg = player_combat.fight(enemy_combat);
|
||||
|
||||
if(enemy_combat.hp <= 0) {
|
||||
log.log("--- ENEMY DEAD!---");
|
||||
auto enemy_position = world.component<Position>(entity);
|
||||
collider.remove(enemy_position.location);
|
||||
world.remove<Motion>(entity);
|
||||
if(player_dmg > 0) {
|
||||
log.log(format("You HIT for {} damage, HP left {}.", player_dmg, enemy_combat.hp));
|
||||
} else {
|
||||
int attack = Random::uniform<int>(0,1);
|
||||
if(attack) {
|
||||
int dmg = Random::uniform<int>(1, enemy_combat.damage);
|
||||
player_combat.hp -= dmg;
|
||||
log.log(format("HIT! You took {} damage.", dmg));
|
||||
} else {
|
||||
log.log("You dodged! Run!");
|
||||
log.log("You missed! They're quick!");
|
||||
}
|
||||
|
||||
if(enemy_combat.hp > 0) {
|
||||
int enemy_dmg = enemy_combat.fight(player_combat);
|
||||
|
||||
if(enemy_dmg > 0) {
|
||||
log.log(format("Enemy HIT YOU for {} damage.", enemy_dmg));
|
||||
} else {
|
||||
log.log("Enemy MISSED, you dodged it.");
|
||||
}
|
||||
} else {
|
||||
log.log("ENEMY DEAD! YOU WIN!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using namespace Components;
|
|||
namespace System {
|
||||
void motion(DinkyECS::World &world, Map &game_map);
|
||||
void combat(DinkyECS::World &world, Player &player);
|
||||
void death(DinkyECS::World &world);
|
||||
void enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player);
|
||||
void draw_map(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, size_t view_x, size_t view_y);
|
||||
void draw_entities(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue