CleverRaven/Cataclysm-DDA — pull request #8007 by BevapDin (2014-06-18 17:36:51+00:00)
Title: Add deafness check as separate function

Did you know: a new character starts with 300 move points (or more)?

Every time you open the Stats screen in the character creation, `Creature::reset_stats` is called and that function adds some move points to the moves counter of the creature. That means a free turn for you. It's called another time from `game::start_game`. Another free turn. Together with the initial 100 move points (constructor of `Creature`) you have 300 move points at the beginning.

Test for this: make new character, open the Stats tab several times (move to the next tab and back). Start the game. Debug a wrist watch to display the time. Starting time is 8:00:06, move around and look at the time, it will not change for some moves and later change normally on each move.

When the first turn is really finished (`moves <= 0`), the function `game::do_turn` ends and adds the deafening effect. This leads to #6916 - the message actually appears at the end of the *first* turn, but that turn is longer than usual and allows you to make several movements.

I fixed this by explicitly settings `player::moves` to 0 right in front of the last `u.reset` call (which calls `Creature::reset_stats`) in `game::start_game`. This prevents that exploit.

I also added an explicit `player::is_deaf` function. It simply wraps both deafness sources: by disease and by worn item. This makes the character start out deaf without the code at the end of `game::do_turn` and without the "You're deaf" message at the start. It thereby fixes #6916.

It also fixes #7005. The current implementation would prolong the deaf disease when the player wears deafening gear. This means the deafness from a flashbang would not wear off while the ear plugs are worn, as each turn the duration of the disease is decreased naturally, but increased because of the worn item. This leads to an effectively unchanged duration of the disease.

----

The same trouble with move points happens at the end of `game::load`. You continue your game with a free turn (because `u.reset` is called there). If you save and reload again, another free turn.

The simple fix is to set `u.moves` to 0 before calling `u.reset()` in `game::start_game` (done here) and in `game::load_game`. But `game::load_game` should not override the moves you have still left from when you saved the game (might be anything above 0).

Actually this is an even bigger problem in `game::load_game`. It seems to be necessarily to call `u.reset()` as apparently not all members of the Creature class are stored in the save. (Why not?)

I added a simple fix that keeps the moves points across the reset call, so you won't get any free moves anymore (the world time still goes on (#7430), but you're synced to the monsters - reset is not called on monsters after loading).

----

Questions:

1. Why can one still "sense" footsteps when deaf? Is this a bug or intended?
2. Should all the members of the Creature class be stored in saves? There is also some overlapping code/data between player/monster as they both inherit from Creature. (Most obvious `moves`, `pain`, `effects`). The game should store all members of Creature.
3. `Creature::reset` calls `reset_bonuses` (sets all bonuses to 0) and `reset_stats`. `reset_stats` is a bit problematic as it invokes long-term changes like adding to the move points, increasing hunger/power for bio_metabolics, ...
But is also makes temporary changes by setting up the stat bonuses (from traits/bionics). So it should not be called directly after loading a game.

There should be a separate `player::on_each_turn` function (better name needed). This function should contain those long-term changes like from bio_metabolics, but also the whole block that increases hunger/thirst/... that is currently in `game::do_turn`. This function would be called exactly once a turn.

The reset function can than be called after loading or before starting the game. This way even repeatedly loading and saving won't change the player data.