forked from CleverRaven/Cataclysm-DDA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
creature.h
475 lines (397 loc) · 20.1 KB
/
creature.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
#ifndef CREATURE_H
#define CREATURE_H
#include "damage.h"
#include "pldata.h"
#include "skill.h"
#include "bionics.h"
#include "json.h"
#include "effect.h"
#include "bodypart.h"
#include "mtype.h"
#include "output.h"
#include <stdlib.h>
#include <string>
#include <unordered_map>
class game;
class JsonObject;
class JsonOut;
class Creature
{
public:
virtual ~Creature();
virtual std::string disp_name(bool possessive = false) const = 0; // displayname for Creature
virtual std::string skin_name() const = 0; // name of outer layer, e.g. "armor plates"
virtual bool is_player() const
{
return false;
}
virtual bool is_npc () const
{
return false;
}
virtual bool is_monster() const
{
return false;
}
// Fake is used to mark non-real creatures used temporarally,
// such as fake NPCs that fire weapons to simulate turrets.
virtual bool is_fake () const;
virtual void set_fake (const bool fake_value);
virtual void normalize(); // recreate the Creature from scratch
virtual void process_turn(); // handles long-term non-idempotent updates to creature state (e.g. moves += speed, bionics hunger costs)
virtual void reset(); // handle both reset steps. Call this function instead of reset_stats/bonuses
virtual void reset_bonuses(); // reset the value of all bonus fields to 0
virtual void reset_stats(); // prepare the Creature for the next turn. Should be idempotent
virtual void die(Creature *killer) = 0;
virtual int hit_roll() const = 0;
virtual int dodge_roll() = 0;
/**
* Simplified attitude towards any creature:
* hostile - hate, want to kill, etc.
* friendly - avoid harming it, maybe even help.
* neutral - anything between.
*/
enum Attitude {
A_HOSTILE,
A_NEUTRAL,
A_FRIENDLY,
};
/**
* Attitude (of this creature) towards another creature. This might not be symmetric.
*/
virtual Attitude attitude_to( const Creature &other ) const = 0;
// tests for visibility
bool sees(const Creature &critter, int range_min, int range_max, int &t) const;
bool sees(int cx, int cy, int range_min, int range_max, int &t) const;
/**
* For fake-players (turrets, mounted turrets) this functions
* chooses a target. This is for creatures that are friendly towards
* the player and therefor choose a target that is hostile
* to the player.
* @param pos Position of the fake-player
* @param range The maximal range to look for monsters, anything
* outside of that range is ignored.
* @param boo_hoo The number of targets that have been skipped
* because the player is in the way.
* @param area The area of effect of the projectile aimed.
*/
Creature *auto_find_hostile_target( int range, int &boo_hoo, int area = 0);
// makes a single melee attack, with the currently equipped weapon
virtual void melee_attack(Creature &t, bool allow_special,
matec_id technique) = 0; // Returns a damage
// fires a projectile at target point from source point, with total_dispersion
// dispersion. returns the rolled dispersion of the shot.
virtual double projectile_attack(const projectile &proj, int sourcex, int sourcey,
int targetx, int targety, double total_dispersion);
// overloaded version, assume it comes from this Creature's position
virtual double projectile_attack(const projectile &proj, int targetx, int targety,
double total_dispersion);
/*
// instantly deals damage at the target point
virtual int smite_attack(game* g, projectile &proj, int targetx, int targety,
std::set<std::string>& proj_effects);
*/
// handles dodges and misses, allowing triggering of martial arts counter
virtual void dodge_hit(Creature *source, int hit_spread) = 0;
// handles blocking of damage instance. mutates &dam
virtual bool block_hit(Creature *source, body_part &bp_hit,
damage_instance &dam) = 0;
// handles armor absorption (including clothing damage etc)
// of damage instance. mutates &dam
virtual void absorb_hit(body_part bp, damage_instance &dam) = 0;
// TODO: this is just a shim so knockbacks work
virtual void knock_back_from(int posx, int posy) = 0;
// begins a melee attack against the creature
// returns hit - dodge (>=0 = hit, <0 = miss)
virtual int deal_melee_attack(Creature *source, int hitroll);
// completes a melee attack against the creature
// dealt_dam is overwritten with the values of the damage dealt
virtual void deal_melee_hit(Creature *source, int hit_spread, bool crit,
const damage_instance &d, dealt_damage_instance &dealt_dam);
// makes a ranged projectile attack against the creature
// dodgeable determines if the dodge stat applies or not, dodge is
// reduced for ranged attacks
virtual int deal_projectile_attack(Creature *source, double missed_by,
const projectile &proj, dealt_damage_instance &dealt_dam);
// deals the damage via an attack. Allows armor mitigation etc.
// Most sources of external damage should use deal_damage
// Mutates the damage_instance& object passed in to reflect the
// post-mitigation object
virtual dealt_damage_instance deal_damage(Creature *source, body_part bp,
const damage_instance &d);
// for each damage type, how much gets through and how much pain do we
// accrue? mutates damage and pain
virtual void deal_damage_handle_type(const damage_unit &du,
body_part bp, int &damage, int &pain);
// directly decrements the damage. ONLY handles damage, doesn't
// increase pain, apply effects, etc
virtual void apply_damage(Creature *source, body_part bp, int amount) = 0;
virtual bool digging() const; // MF_DIGS or MF_CAN_DIG and diggable terrain
virtual bool is_on_ground() const = 0;
virtual bool is_underwater() const = 0;
virtual bool is_warm() const; // is this creature warm, for IR vision, heat drain, etc
virtual bool has_weapon() const = 0;
virtual bool is_hallucination() const = 0;
// returns true if health is zero or otherwise should be dead
virtual bool is_dead_state() const = 0;
// xpos and ypos, because posx/posy are used as public variables in
// player.cpp and therefore referenced everywhere
virtual int xpos() const = 0;
virtual int ypos() const = 0;
virtual point pos() const = 0;
struct compare_by_dist_to_point {
point center;
// Compare the two creatures a and b by their distance to a fixed center point.
// The nearer creature is considered smaller and sorted first.
bool operator()( const Creature *a, const Creature *b ) const;
};
/** Processes move stopping effects. Returns false if movement is stopped. */
virtual bool move_effects();
/** Handles effect application effects. */
virtual void add_eff_effects(effect e, bool reduced);
/** Adds or modifies an effect. If intensity is given it will set the effect intensity
to the given value, or as close as max_intensity values permit. */
virtual void add_effect(efftype_id eff_id, int dur, body_part bp = num_bp, bool permanent = false,
int intensity = 0);
/** Gives chance to save via environmental resist, returns false if resistance was successful. */
bool add_env_effect(efftype_id eff_id, body_part vector, int strength, int dur,
body_part bp = num_bp, bool permanent = false, int intensity = 1);
/** Removes a listed effect, adding the removal memorial log if needed. bp = num_bp means to remove
* all effects of a given type, targeted or untargeted. Returns true if anything was removed. */
bool remove_effect(efftype_id eff_id, body_part bp = num_bp);
/** Remove all effects. */
void clear_effects();
/** Check if creature has the matching effect. bp = num_bp means to check if the Creature has any effect
* of the matching type, targeted or untargeted. */
bool has_effect(efftype_id eff_id, body_part bp = num_bp) const;
/** Return the effect that matches the given arguments exactly. */
effect get_effect(efftype_id eff_id, body_part bp = num_bp) const;
/** Returns the duration of the matching effect. Returns 0 if effect doesn't exist. */
int get_effect_dur(efftype_id eff_id, body_part bp = num_bp) const;
/** Returns the intensity of the matching effect. Returns 0 if effect doesn't exist. */
int get_effect_int(efftype_id eff_id, body_part bp = num_bp) const;
// Methods for setting/getting misc key/value pairs.
void set_value( const std::string key, const std::string value );
void remove_value( const std::string key );
std::string get_value( const std::string key ) const;
/** Processes through all the effects on the Creature. */
virtual void process_effects();
/** Returns true if the player has the entered trait, returns false for non-humans */
virtual bool has_trait(const std::string &flag) const;
/** Handles health fluctuations over time */
virtual void update_health(int base_threshold = 0);
// not-quite-stats, maybe group these with stats later
virtual void mod_pain(int npain);
virtual void mod_moves(int nmoves);
virtual void set_moves(int nmoves);
virtual bool in_sleep_state() const;
/*
* Get/set our killer, this is currently used exclusively to allow
* mondeath effects to happen after death cleanup
*/
virtual Creature *get_killer() const;
/*
* getters for stats - combat-related stats will all be held within
* the Creature and re-calculated during every normalize() call
*/
virtual int get_str() const;
virtual int get_dex() const;
virtual int get_per() const;
virtual int get_int() const;
virtual int get_str_base() const;
virtual int get_dex_base() const;
virtual int get_per_base() const;
virtual int get_int_base() const;
virtual int get_str_bonus() const;
virtual int get_dex_bonus() const;
virtual int get_per_bonus() const;
virtual int get_int_bonus() const;
virtual int get_healthy() const;
virtual int get_healthy_mod() const;
virtual int get_num_blocks() const;
virtual int get_num_dodges() const;
virtual int get_num_blocks_bonus() const;
virtual int get_num_dodges_bonus() const;
virtual int get_env_resist(body_part bp) const;
virtual int get_armor_bash(body_part bp) const;
virtual int get_armor_cut(body_part bp) const;
virtual int get_armor_bash_base(body_part bp) const;
virtual int get_armor_cut_base(body_part bp) const;
virtual int get_armor_bash_bonus() const;
virtual int get_armor_cut_bonus() const;
virtual int get_speed() const;
virtual int get_dodge() const;
virtual int get_melee() const;
virtual int get_hit() const;
virtual m_size get_size() const = 0;
virtual int get_hp( hp_part bp = num_hp_parts ) const = 0;
virtual int get_hp_max( hp_part bp = num_hp_parts ) const = 0;
virtual std::string get_material() const
{
return "flesh";
}
virtual field_id bloodType () const = 0;
virtual field_id gibType () const = 0;
// TODO: replumb this to use a std::string along with monster flags.
virtual bool has_flag( const m_flag ) const
{
return false;
};
virtual int get_speed_base() const;
virtual int get_dodge_base() const;
virtual int get_hit_base() const;
virtual int get_speed_bonus() const;
virtual int get_dodge_bonus() const;
virtual int get_block_bonus() const;
virtual int get_hit_bonus() const;
virtual int get_bash_bonus() const;
virtual int get_cut_bonus() const;
virtual float get_bash_mult() const;
virtual float get_cut_mult() const;
virtual bool get_melee_quiet() const;
virtual int get_grab_resist() const;
virtual int get_throw_resist() const;
/*
* setters for stats and boni
*/
virtual void set_str_bonus(int nstr);
virtual void set_dex_bonus(int ndex);
virtual void set_per_bonus(int nper);
virtual void set_int_bonus(int nint);
virtual void mod_str_bonus(int nstr);
virtual void mod_dex_bonus(int ndex);
virtual void mod_per_bonus(int nper);
virtual void mod_int_bonus(int nint);
virtual void mod_stat( std::string stat, int modifier );
virtual void set_healthy(int nhealthy);
virtual void set_healthy_mod(int nhealthy_mod);
virtual void mod_healthy(int nhealthy);
virtual void mod_healthy_mod(int nhealthy_mod);
virtual void set_num_blocks_bonus(int nblocks);
virtual void set_num_dodges_bonus(int ndodges);
virtual void set_armor_bash_bonus(int nbasharm);
virtual void set_armor_cut_bonus(int ncutarm);
virtual void set_speed_base(int nspeed);
virtual void set_speed_bonus(int nspeed);
virtual void set_dodge_bonus(int ndodge);
virtual void set_block_bonus(int nblock);
virtual void set_hit_bonus(int nhit);
virtual void set_bash_bonus(int nbash);
virtual void set_cut_bonus(int ncut);
virtual void mod_speed_bonus(int nspeed);
virtual void mod_dodge_bonus(int ndodge);
virtual void mod_block_bonus(int nblock);
virtual void mod_hit_bonus(int nhit);
virtual void mod_bash_bonus(int nbash);
virtual void mod_cut_bonus(int ncut);
virtual void set_bash_mult(float nbashmult);
virtual void set_cut_mult(float ncutmult);
virtual void set_melee_quiet(bool nquiet);
virtual void set_grab_resist(int ngrabres);
virtual void set_throw_resist(int nthrowres);
virtual int weight_capacity() const;
/*
* Event handlers
*/
virtual void on_gethit(Creature *source, body_part bp_hit,
damage_instance &dam);
// innate stats, slowly move these to protected as we rewrite more of
// the codebase
int str_max, dex_max, per_max, int_max,
str_cur, dex_cur, per_cur, int_cur;
int moves, pain;
void draw(WINDOW *w, int plx, int ply, bool inv) const;
/**
* Write information about this creature.
* @param w the window to print the text into.
* @param vStart vertical start to print, that means the first line to print.
* @param vLines number of lines to print at most (printing less is fine).
* @param column horizontal start to print (column), horizontal end is
* one character before the right border of the window (to keep the border).
* @return The line just behind the last printed line, that means multiple calls
* to this can be stacked, the return value is acceptable as vStart for the next
* call without creating empty lines or overwriting lines.
*/
virtual int print_info(WINDOW *w, int vStart, int vLines, int column) const = 0;
// Message related stuff
virtual void add_msg_if_player(const char *, ...) const {};
virtual void add_msg_if_player(game_message_type, const char *, ...) const {};
virtual void add_msg_if_npc(const char *, ...) const {};
virtual void add_msg_if_npc(game_message_type, const char *, ...) const {};
virtual void add_msg_player_or_npc(const char *, const char *, ...) const {};
virtual void add_msg_player_or_npc(game_message_type, const char *, const char *, ...) const {};
virtual void add_memorial_log(const char *, const char *, ...) {};
virtual nc_color symbol_color() const;
virtual nc_color basic_symbol_color() const;
virtual const std::string &symbol() const;
virtual bool is_symbol_highlighted() const;
protected:
Creature *killer; // whoever killed us. this should be NULL unless we are dead
// Storing body_part as an int to make things easier for hash and JSON
std::unordered_map<std::string, std::unordered_map<body_part, effect, std::hash<int>>> effects;
// Miscellaneous key/value pairs.
std::unordered_map<std::string, std::string> values;
// used for innate bonuses like effects. weapon bonuses will be
// handled separately
int str_bonus;
int dex_bonus;
int per_bonus;
int int_bonus;
int healthy; //How healthy the creature is, currently only used by players
int healthy_mod;
int num_blocks; // base number of blocks/dodges per turn
int num_dodges;
int num_blocks_bonus; // bonus ""
int num_dodges_bonus;
int armor_bash_bonus;
int armor_cut_bonus;
int speed_base; // only speed needs a base, the rest are assumed at 0 and calced off skills
int speed_bonus;
int dodge_bonus;
int block_bonus;
int hit_bonus;
int bash_bonus;
int cut_bonus;
float bash_mult;
float cut_mult;
bool melee_quiet;
int grab_resist;
int throw_resist;
bool fake;
Creature();
Creature(const Creature &) = default;
Creature(Creature &&) = default;
Creature &operator=(const Creature &) = default;
Creature &operator=(Creature &&) = default;
body_part select_body_part(Creature *source, int hit_roll);
/**
* These two functions are responsible for storing and loading the members
* of this class to/from json data.
* All classes that inherit from this class should implement their own
* version of these functions. They are not virtual on purpose, as it's
* not needed.
* Every implementation of those functions should a) call the same function
* with the same parameters of the super class and b) store/load their own
* members, but *not* members of any sub or super class.
*
* The functions are (on purpose) not part of the json
* serialize/deserialize system (defined in json.h).
* The Creature class is incomplete, there won't be any instance of that
* class alone, but there will be instances of sub classes (e.g. player,
* monster).
* Those (complete) classes implement the deserialize/serialize interface
* of json. That way only one json object per npc/player/monster instance
* is created (inside of the serialize function).
* E.g. player::serialize() looks like this:
* <code>json.start_object();store(json);json.end_object()</code>
* player::store than stores the members of the player class, and it calls
* Character::store, which stores the members of the Character class and calls
* Creature::store, which stores the members of the Creature class.
* All data goes into the single json object created in player::serialize.
*/
// Store data of *this* class in the stream
void store(JsonOut &jsout) const;
// Load creature data from the given json object.
void load(JsonObject &jsin);
};
#endif