Skip to content

Commit

Permalink
Make monster::dead private and add is_dead function.
Browse files Browse the repository at this point in the history
monster::die is now called exactly once, further calls are ignored.
monster::dead is only set to true in that function.
*all* effects of a dying monster are handled in monster::die.

Added a function to class game to increase the kill counter.

game::cleanup_dead now only removes the monster object from the creature tracker, nothing more.

ranged.cpp: use monster::pos(), which already returns a point.

Note on the removal of the is-dead check: game::mon_at / Creature_tracker::mon_at never return the index of a dead monster, so returned index is always for a living monster, so the check is not required.
game::zombie() / Creature_tracker::find still return a dead monster.

The correction of game::last_target is now in game::remove_zombie so it is always corrected (remove_zombie is called from other code as well, not just from game::cleanup_dead).
  • Loading branch information
BevapDin committed Jul 26, 2014
1 parent 1f1778f commit e745478
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 73 deletions.
4 changes: 1 addition & 3 deletions src/cata_tiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,15 +1083,13 @@ bool cata_tiles::draw_entity(int x, int y)
bool entity_here = false;
// check for monster (most common)
if (!entity_here && g->mon_at(x, y) >= 0) {
monster m = g->zombie(g->mon_at(x, y));
if (!m.dead) {
monster &m = g->zombie(g->mon_at(x, y));
ent_name = m.type->id;
ent_category = C_MONSTER;
if(!(m.type->species.empty())) {
ent_subcategory = *(m.type->species.begin());
}
entity_here = true;
}
}
// check for NPC (next most common)
if (!entity_here && g->npc_at(x, y) >= 0) {
Expand Down
8 changes: 4 additions & 4 deletions src/creature_tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ int Creature_tracker::mon_at(point coords) const
std::map<point, int>::const_iterator iter = _old_monsters_by_location.find(coords);
if (iter != _old_monsters_by_location.end()) {
const int critter_id = iter->second;
if (!_old_monsters_list[critter_id]->dead) {
if (!_old_monsters_list[critter_id]->is_dead()) {
return critter_id;
}
}
Expand All @@ -38,7 +38,7 @@ int Creature_tracker::dead_mon_at(point coords) const
std::map<point, int>::const_iterator iter = _old_monsters_by_location.find(coords);
if (iter != _old_monsters_by_location.end()) {
const int critter_id = iter->second;
if (_old_monsters_list[critter_id]->dead) {
if (_old_monsters_list[critter_id]->is_dead()) {
return critter_id;
}
}
Expand Down Expand Up @@ -71,9 +71,9 @@ bool Creature_tracker::update_pos(const monster &critter, const int new_x_pos, c
bool success = false;
const int dead_critter_id = dead_mon_at(point(critter.posx(), critter.posy()));
const int live_critter_id = mon_at(point(critter.posx(), critter.posy()));
const int critter_id = critter.dead ? dead_critter_id : live_critter_id;
const int critter_id = critter.is_dead() ? dead_critter_id : live_critter_id;
const int new_critter_id = mon_at(new_x_pos, new_y_pos);
if (new_critter_id >= 0 && !_old_monsters_list[new_critter_id]->dead) {
if (new_critter_id >= 0 && !_old_monsters_list[new_critter_id]->is_dead()) {
debugmsg("update_zombie_pos: new location %d,%d already has zombie %d",
new_x_pos, new_y_pos, new_critter_id);
} else if (critter_id >= 0) {
Expand Down
75 changes: 37 additions & 38 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,11 @@ int game::kill_count(std::string mon)
return 0;
}

void game::increase_kill_count(const std::string &mtype_id)
{
kills[mtype_id]++;
}

mission *game::find_mission(int id)
{
for (std::vector<mission>::iterator it = active_missions.begin();
Expand Down Expand Up @@ -4724,7 +4729,9 @@ void game::debug()

case 19: {
for (size_t i = 0; i < num_zombies(); i++) {
zombie(i).dead = true;
// Use the normal death functions, useful for testing death
// and for getting a corpse.
zombie(i).die( nullptr );
}
cleanup_dead();
}
Expand Down Expand Up @@ -6212,29 +6219,15 @@ int game::mon_info(WINDOW *w)

void game::cleanup_dead()
{
for (int i = 0; i < num_zombies(); i++) {
for( int i = 0; i < num_zombies(); ) {
monster &critter = critter_tracker.find(i);
if (critter.dead || critter.hp <= 0) {
if( critter.is_dead() ) {
dbg(D_INFO) << string_format("cleanup_dead: critter[%d] %d,%d dead:%c hp:%d %s",
i, critter.posx(), critter.posy(), (critter.dead ? '1' : '0'),
i, critter.posx(), critter.posy(), (critter.is_dead() ? '1' : '0'),
critter.hp, critter.name().c_str());
Creature *killer = critter.get_killer();
if (killer != NULL && killer->is_player() && // killed by player and
(critter.has_flag(MF_GUILT) || // has guilt flag or
(u.has_trait("PACIFIST") && critter.has_flag(MF_HUMAN)))) { // pacifist player && humanoid
mdeath tmpdeath;
tmpdeath.guilt(&critter);
}
if( killer != NULL && killer->is_player() ) {
kills[critter.type->id]++;
}
remove_zombie(i);
if (last_target == i) {
last_target = -1;
} else if (last_target > i) {
last_target--;
}
i--;
remove_zombie( i );
} else {
i++;
}
}

Expand Down Expand Up @@ -6268,7 +6261,7 @@ void game::monmove()

for (int i = 0; i < num_zombies(); i++) {
monster *critter = &critter_tracker.find(i);
while (!critter->dead && !critter->can_move_to(critter->posx(), critter->posy())) {
while (!critter->is_dead() && !critter->can_move_to(critter->posx(), critter->posy())) {
// If we can't move to our current position, assign us to a new one
if (debugmon) {
dbg(D_ERROR) << "game:monmove: " << critter->name().c_str()
Expand All @@ -6291,29 +6284,27 @@ void game::monmove()
}
}
if (!okay) {
critter->dead = true;
// die of "natural" cause (overpopulation is natural)
critter->die( nullptr );
}
}

if (!critter->dead) {
if (!critter->is_dead()) {
critter->process_turn();
critter->reset();
critter->hurt( 0 ); // trigger dying on low hp
}

m.mon_in_field(critter->posx(), critter->posy(), critter);
// might have killed the critter and spawned more monsters
critter = &critter_tracker.find(i);

while (critter->moves > 0 && !critter->dead) {
while (critter->moves > 0 && !critter->is_dead()) {
critter->made_footstep = false;
critter->plan(friendlies); // Formulate a path to follow
critter->move(); // Move one square, possibly hit u
critter->process_triggers();
m.mon_in_field(critter->posx(), critter->posy(), critter);
}

if (!critter->dead) {
if (!critter->is_dead()) {
if (u.has_active_bionic("bio_alarm") && u.power_level >= 1 &&
rl_dist(u.posx, u.posy, critter->posx(), critter->posy()) <= 5) {
u.power_level--;
Expand Down Expand Up @@ -6342,7 +6333,10 @@ void game::monmove()
cur_om->zg.push_back(mongroup(MonsterGroupManager::Monster2Group((critter->type->id)),
levx, levy, levz, 1, 1));
}
critter->dead = true;
// Remove the zombie, but don't let it "die", it still exists, just
// not in the reality bubble.
remove_zombie( i );
i--;
}
}
}
Expand Down Expand Up @@ -6864,14 +6858,14 @@ void game::knockback(std::vector<point> &traj, int force, int stun, int dam_mult
break;
}
targ->setpos(traj[i]);
if (m.has_flag("LIQUID", targ->posx(), targ->posy()) && !targ->can_drown() && !targ->dead) {
if (m.has_flag("LIQUID", targ->posx(), targ->posy()) && !targ->can_drown() && !targ->is_dead()) {
targ->die( nullptr );
if (u_see(targ)) {
add_msg(_("The %s drowns!"), targ->name().c_str());
}
}
if (!m.has_flag("LIQUID", targ->posx(), targ->posy()) && targ->has_flag(MF_AQUATIC) &&
!targ->dead) {
!targ->is_dead()) {
targ->die( nullptr );
if (u_see(targ)) {
add_msg(_("The %s flops around and dies!"), targ->name().c_str());
Expand Down Expand Up @@ -7248,7 +7242,7 @@ void game::emp_blast(int x, int y)
add_msg(_("The EMP blast fries the %s!"), critter.name().c_str());
int dam = dice(10, 10);
critter.hurt( dam );
if( !critter.dead && one_in( 6 ) ) {
if( !critter.is_dead() && one_in( 6 ) ) {
critter.make_friendly();
}
}
Expand Down Expand Up @@ -7333,6 +7327,11 @@ bool game::update_zombie_pos(const monster &critter, const int newx, const int n

void game::remove_zombie(const int idx)
{
if( last_target == idx && !last_target_was_npc ) {
last_target = -1;
} else if( last_target > idx && !last_target_was_npc ) {
last_target--;
}
critter_tracker.remove(idx);
}

Expand Down Expand Up @@ -7984,7 +7983,7 @@ bool game::forced_gate_closing(int x, int y, ter_id door_type, int bash_dmg)
// if the npc was really big?
}
const int cindex = mon_at(x, y);
if (cindex != -1 && !zombie(cindex).dead) {
if (cindex != -1) {
if (bash_dmg <= 0) {
return false;
}
Expand All @@ -7997,13 +7996,13 @@ bool game::forced_gate_closing(int x, int y, ter_id door_type, int bash_dmg)
} else {
critter.hurt( bash_dmg );
}
if( !critter.dead && critter.type->size >= MS_HUGE ) {
if( !critter.is_dead() && critter.type->size >= MS_HUGE ) {
// big critters simply prevent the gate from closing
// TODO: perhaps damage/destroy the gate
// if the critter was really big?
return false;
}
if( !critter.dead ) {
if( !critter.is_dead() ) {
// Still alive? Move the critter away so the door can close
knockback(kbx, kby, x, y, std::max(1, bash_dmg / 10), -1, 1);
if (mon_at(x, y) != -1) {
Expand Down Expand Up @@ -12365,7 +12364,7 @@ bool game::plmove(int dx, int dy)
if (critter.is_hallucination()) {
critter.die( &g->u );
}
draw_hit_mon(x, y, critter, critter.dead);
draw_hit_mon(x, y, critter, critter.is_dead());
return false;
} else {
displace = true;
Expand Down Expand Up @@ -13283,7 +13282,7 @@ void game::fling_player_or_monster(player *p, monster *zz, const int &dir, float
dname = critter.name();
dam2 = flvel / 3 + rng(0, flvel * 1 / 3);
critter.hurt( dam2 );
if( !critter.dead ) {
if( !critter.is_dead() ) {
thru = false;
}
if (is_player) {
Expand Down
2 changes: 2 additions & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ class game
npc *find_npc(int id);
void load_npcs(); //Make any nearby NPCs from the overmap active.
int kill_count(std::string mon); // Return the number of kills of a given mon_id
// Register one kill of a monster of type mtype_id by the player.
void increase_kill_count(const std::string &mtype_id);
mission *find_mission(int id); // Mission with UID=id; NULL if non-existant
mission_type *find_mission_type(int id); // Same, but returns its type
bool mission_complete(int id, int npc_id); // True if we made it
Expand Down
2 changes: 1 addition & 1 deletion src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8103,7 +8103,7 @@ int iuse::robotcontrol(player *p, item *it, bool)
p->add_msg_if_player(_("The %s short circuits as you attempt to reprogram it!"),
z->name().c_str());
z->hurt( rng( 1, 10 ), 0, p ); //damage it a little
if( z->dead ) {
if( z->is_dead() ) {
p->practice("computer", 10);
return it->type->charges_to_use(); //dont do the other effects if the robot died
}
Expand Down
4 changes: 2 additions & 2 deletions src/monmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void monster::move()

//Hallucinations have a chance of disappearing each turn
if (is_hallucination() && one_in(25)) {
dead = true;
die( nullptr );
return;
}

Expand Down Expand Up @@ -729,7 +729,7 @@ int monster::attack_at(int x, int y) {

// Special case: Target is hallucination
if(mon.is_hallucination()) {
mon.dead = true;
mon.die( nullptr );

// We haven't actually attacked anything, i.e. we can still do things.
// Hallucinations(obviously) shouldn't affect the way real monsters act.
Expand Down
49 changes: 30 additions & 19 deletions src/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ void monster::melee_attack(Creature &target, bool, matec_id) {

if (is_hallucination()) {
if(one_in(7)) {
dead = true;
die( nullptr );
}
return;
}
Expand Down Expand Up @@ -1190,35 +1190,41 @@ void monster::explode()
}

void monster::die(Creature* nkiller) {
if( dead ) {
// We are already dead, don't die again, note that monster::dead is
// *only* set to true in this function!
return;
}
dead = true;
if( nkiller != NULL && !nkiller->is_fake() ) {
killer = nkiller;
}
if( hp < -( type->size < MS_MEDIUM ? 1.5 : 3 ) * type->hp ) {
explode(); // Explode them if it was big overkill
}
if (!dead) {
dead = true;
}
if (!no_extra_death_drops) {
drop_items_on_death();
}
// TODO:
/*
if (killer == &g->u) {
if (!is_hallucination()) {
g->kills[type->id]++; // Increment our kill counter
// TODO: should actually be class Character
player *ch = dynamic_cast<player*>( get_killer() );
if( !is_hallucination() && ch != nullptr ) {
if( has_flag( MF_GUILT ) || ( ch->has_trait( "PACIFIST" ) && has_flag( MF_HUMAN ) ) ) {
// has guilt flag or player is pacifist && monster is humanoid
mdeath tmpdeath;
tmpdeath.guilt( this );
}
// TODO: add a kill counter to npcs?
if( ch->is_player() ) {
g->increase_kill_count( type->id );
}
if( type->difficulty >= 30 ) {
ch->add_memorial_log( pgettext( "memorial_male", "Killed a %s." ),
pgettext( "memorial_female", "Killed a %s." ),
name().c_str() );
}
}
*/
for (std::vector<item>::iterator it = inv.begin();
it != inv.end(); ++it) {
g->m.add_item_or_charges(posx(), posy(), *it);
}
if (type->difficulty >= 30 && get_killer() != NULL && get_killer()->is_player()) {
g->u.add_memorial_log(
pgettext("memorial_male", "Killed a %s."),
pgettext("memorial_female", "Killed a %s."),
name().c_str());
for( const auto &it : inv ) {
g->m.add_item_or_charges( posx(), posy(), it );
}

// If we're a queen, make nearby groups of our type start to die out
Expand Down Expand Up @@ -1491,3 +1497,8 @@ void monster::add_msg_player_or_npc(game_message_type type, const char *, const
}
va_end(ap);
}

bool monster::is_dead() const
{
return dead || const_cast<monster*>(this)->is_dead_state();
}
3 changes: 2 additions & 1 deletion src/monster.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ class monster : public Creature, public JsonSerializer, public JsonDeserializer
int mission_id; // If we're related to a mission
mtype *type;
bool no_extra_death_drops; // if true, don't spawn loot items as part of death
bool dead;
bool is_dead() const;
bool made_footstep;
std::string unique_name; // If we're unique
bool hallucination;
Expand Down Expand Up @@ -298,6 +298,7 @@ class monster : public Creature, public JsonSerializer, public JsonDeserializer
private:
std::vector <point> plans;
int _posx, _posy;
bool dead;
};

#endif
Loading

0 comments on commit e745478

Please sign in to comment.