105 lines
3.4 KiB
C++
105 lines
3.4 KiB
C++
#include "enemy.h"
|
|
|
|
#include "constants.h"
|
|
#include "player.h"
|
|
#include "level.h"
|
|
|
|
enemy_base::enemy_base(RNG *rng, const feature enabled_features,
|
|
const enum race &nrace, const position &pos,
|
|
const int gen_room_num, std::string abbrev):
|
|
character{rng, enabled_features, nrace, pos},
|
|
room_num{gen_room_num}, abbrev{abbrev} {}
|
|
|
|
int enemy_base::get_room_num() const {
|
|
return room_num;
|
|
}
|
|
|
|
long_result enemy_base::act(level *lvl, character *pc, bool hostile) {
|
|
if (is_adjacent(pos, pc->get_pos()) && hostile)
|
|
return attack(pc);
|
|
|
|
if (enabled_features & FEATURE_ENEMIES_CHASE && hostile &&
|
|
distance_sqr(pos, pc->get_pos()) <= DIST_THRESHOLD_SQR) {
|
|
position tmp;
|
|
position target = {BIG_NUMBER, BIG_NUMBER};
|
|
|
|
for (int i = 0; i < DIRECTION_CNT; ++i) {
|
|
tmp = pos + MOVE[i];
|
|
|
|
if (((enabled_features & FEATURE_DOORS) ? true
|
|
: lvl->get_room(tmp) == room_num) &&
|
|
lvl->is_available(tmp) &&
|
|
distance_sqr(tmp, pc->get_pos()) <
|
|
distance_sqr(target, pc->get_pos()))
|
|
target = tmp;
|
|
}
|
|
|
|
if (target.x != BIG_NUMBER)
|
|
pos = target;
|
|
|
|
return {NOTHING, ""};
|
|
}
|
|
|
|
int choices_cnt = 0;
|
|
position choices[DIRECTION_CNT];
|
|
|
|
for (int i = 0; i < DIRECTION_CNT; ++i)
|
|
if (((enabled_features & FEATURE_DOORS) ?
|
|
true : lvl->get_room(pos + MOVE[i]) == room_num ) &&
|
|
lvl->is_available(pos + MOVE[i])) {
|
|
choices[choices_cnt] = pos + MOVE[i];
|
|
++choices_cnt;
|
|
}
|
|
|
|
if (choices_cnt)
|
|
pos = choices[rng->rand_under(choices_cnt)];
|
|
|
|
return {NOTHING, ""};
|
|
}
|
|
|
|
long_result enemy_base::attack(character *ch) {
|
|
return ch->get_hit(this, ATK, base_hit_rate);
|
|
}
|
|
|
|
std::string enemy_base::get_abbrev() const {
|
|
return abbrev;
|
|
}
|
|
|
|
long_result enemy_base::get_hit(character *ch, const int tATK,
|
|
const fraction &hit_rate) {
|
|
if (rng->trial(hit_rate)) {
|
|
int tmp = calc_dmg(tATK, DEF);
|
|
tmp = tmp > HP ? HP : tmp;
|
|
HP -= tmp;
|
|
|
|
if (HP == 0)
|
|
return {result::HIT,
|
|
"PC deals " + std::to_string(tmp) +
|
|
" damage to " + abbrev + " (" +
|
|
std::to_string(HP) + " HP). " +
|
|
abbrev + " is slain by PC. "};
|
|
|
|
return {result::HIT, "PC deals " +
|
|
std::to_string(tmp) + " damage to " + abbrev + " (" +
|
|
std::to_string(HP) + " HP). "};
|
|
}
|
|
|
|
return {MISS, "PC tried to hit " + abbrev + " but missed. "};
|
|
}
|
|
|
|
int enemy_base::dies(level *lvl) {
|
|
return rand_gold_drop(rng);
|
|
}
|
|
|
|
enemy_base *get_enemy_at(const position &pos, const enemy_list &elist) {
|
|
for (auto e : elist)
|
|
if (e->get_pos() == pos)
|
|
return e;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void enemy_base::print(output *out) {
|
|
out->print_char(pos, CHAR_REP[race], COLOR_PAIR(COLOR_RED));
|
|
}
|