finished the bulk of game
This commit is contained in:
115
src/enemy.cc
Normal file
115
src/enemy.cc
Normal file
@ -0,0 +1,115 @@
|
||||
#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} {
|
||||
base_hit_rate_reset = {1, 2};
|
||||
}
|
||||
|
||||
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 &&
|
||||
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 (lvl->get_room(tmp) == room_num &&
|
||||
lvl->is_available(tmp) &&
|
||||
distance_sqr(tmp, pc->get_pos()) <
|
||||
distance_sqr(target, pc->get_pos()))
|
||||
target = tmp;
|
||||
}
|
||||
|
||||
pos = target;
|
||||
return {fine, ""};
|
||||
}
|
||||
|
||||
int choices_cnt = 0;
|
||||
position choices[DIRECTION_CNT];
|
||||
|
||||
for (int i = 0; i < DIRECTION_CNT; ++i)
|
||||
if (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 {fine, ""};
|
||||
}
|
||||
|
||||
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 + ". " + abbrev +
|
||||
" is slain by PC. "};
|
||||
|
||||
return {result::hit, "PC deals " +
|
||||
std::to_string(tmp) + " damage to " + abbrev};
|
||||
}
|
||||
|
||||
return {miss, "PC tried to hit " + abbrev + " but missed. "};
|
||||
}
|
||||
|
||||
void enemy_base::dies(level *lvl, character *pc) {
|
||||
auto elist = lvl->get_elist();
|
||||
|
||||
for (size_t i = 0; i < elist.size(); ++i)
|
||||
if (elist[i] == this) {
|
||||
elist.erase(elist.begin() + i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (race == race::rdragon) {
|
||||
return;
|
||||
} else if (race == race::rmerchant) {
|
||||
lvl->add_gold({GOLD_MERCHANT, pos});
|
||||
} else if (race == race::rhuman) {
|
||||
lvl->add_gold({GOLD_NORMAL, pos});
|
||||
auto plist = lvl->get_available_around_all(pos);
|
||||
lvl->add_gold({GOLD_NORMAL,
|
||||
rng->get_rand_in_vector(plist)});
|
||||
}
|
||||
|
||||
((player_base *)pc)->add_gold(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;
|
||||
}
|
Reference in New Issue
Block a user