1 #pragma once
2 
3 #include "beh-type.h"
4 #include "coord.h"
5 #include "god-type.h"
6 #include "mgen-enum.h"
7 #include "mon-flags.h"
8 #include "xp-tracking-type.h"
9 
10 // Hash key for passing a weapon to be given to
11 // a dancing weapon.
12 #define TUKIMA_WEAPON "tukima-weapon"
13 #define TUKIMA_POWER "tukima-power"
14 
15 #define MGEN_NUM_HEADS "num_heads"
16 #define MGEN_BLOB_SIZE "blob_size"
17 #define MGEN_TENTACLE_CONNECT "tentacle_connect"
18 /// doesn't automatically perish over time (for pillars of salt, blocks of ice)
19 #define MGEN_NO_AUTO_CRUMBLE "no_auto_crumble"
20 
21 // A structure with all the data needed to whip up a new monster.
22 struct mgen_data
23 {
24     // Monster type.
25     monster_type    cls;
26 
27     // Determines the behaviour of the monster after it is generated. This
28     // behaviour is an unholy combination of monster attitude
29     // (friendly, hostile) and monster initial state (asleep, wandering).
30     // XXX: Could use splitting up these aspects.
31     beh_type        behaviour;
32 
33     // Who summoned this monster?  Important to know for death accounting
34     // and the summon cap, if and when it goes in. nullptr is no summoner.
35     const actor*    summoner;
36 
37     // For summoned monsters, this is a measure of how long the summon will
38     // hang around, on a scale of 1-6, 6 being longest. Use 0 for monsters
39     // that aren't summoned.
40     int             abjuration_duration;
41 
42     // For summoned monsters this is their type of summoning, either the
43     // spell which summoned them or one of the values of the enumeration
44     // mon_summon_type in mon-enum.h.
45     int             summon_type;
46 
47     // Where the monster will be created.
48     coord_def       pos;
49 
50     // The monster's foe, i.e. which monster it will want to attack. foe
51     // may be an index into the monster array (0 - (MAX_MONSTERS-1)), or
52     // it may be MHITYOU to indicate that the monster wants to attack the
53     // player, or MHITNOT, to indicate that the monster has no foe and is
54     // just wandering around.
55     unsigned short  foe;
56 
57     // Generation flags.
58     mgen_flags      flags;
59 
60     // What god the monster worships, if any. Used for monsters that
61     // are god gifts, to indicate which god sent them, and by priest
62     // monsters, to indicate whose priest they are.
63     god_type        god;
64 
65     // If the monster is zombie-like, or a specialised draconian, this
66     // is the base monster that the monster is based on - should be
67     // set to MONS_NO_MONSTER when not used.
68     monster_type    base_type;
69 
70     // The colour of the monster, or COLOUR_UNDEF for col:any
71     int             colour;
72 
73     // How close to or far from the player the monster should be created.
74     // Is usually used only when the initial position (pos) is unspecified.
75     proximity_type  proximity;
76 
77     // What place we're in, or pretending to be in, usually the place
78     // the player is actually in.
79     level_id        place;
80 
81     int             hd;
82     int             hp;
83 
84     // These flags will be appended to the monster's flags after placement.
85     monster_flags_t extra_flags;
86 
87     string          mname;
88 
89     // This is used to account for non-actor summoners. Blasted by an Ice
90     // Fiend ... summoned by the effects of Hell.
91     string          non_actor_summoner;
92 
93     // This simply stores the initial shape-shifter type.
94     monster_type    initial_shifter;
95 
96     // A grid feature to prefer when finding a place to create monsters.
97     // For instance, using DNGN_FLOOR when placing flying monsters or
98     // merfolk in the Shoals will force them to appear on land.
99     // preferred_grid_feature will be ignored if it is incompatible with
100     // the monster's native habitat (for instance, if trying to place
101     // a electric eel with preferred_grid_feature DNGN_FLOOR).
102     dungeon_feature_type preferred_grid_feature = DNGN_UNSEEN;
103 
104     // Some predefined vaults (aka maps) include flags to suppress random
105     // generation of monsters. When generating monsters, this is a mask of
106     // map flags to honour (such as MMT_NO_MONS to specify that we shouldn't
107     // randomly generate a monster inside a map that doesn't want it). These
108     // map flags are usually respected only when a dungeon level is being
109     // constructed, since at future points vault information may no longer
110     // be available (vault metadata is not preserved across game saves).
111     unsigned        map_mask = 0;
112 
113     // This can eventually be used to store relevant information.
114     CrawlHashTable  props;
115 
116     // What class of XP is this for LevelXPInfo tracking purposes.
117     xp_tracking_type xp_tracking;
118 
119     mgen_data(monster_type mt = RANDOM_MONSTER,
120               beh_type beh = BEH_HOSTILE,
121               const coord_def &p = coord_def(-1, -1),
122               unsigned short mfoe = MHITNOT,
123               mgen_flags genflags = MG_NONE,
124               god_type which_god = GOD_NO_GOD)
125 
clsmgen_data126         : cls(mt), behaviour(beh), summoner(nullptr), abjuration_duration(0),
127           summon_type(0), pos(p), foe(mfoe), flags(genflags), god(which_god),
128           base_type(MONS_NO_MONSTER), colour(COLOUR_INHERIT),
129           proximity(PROX_ANYWHERE), place(level_id::current()), hd(0), hp(0),
130           extra_flags(MF_NO_FLAGS), mname(""), non_actor_summoner(""),
131           initial_shifter(RANDOM_MONSTER), xp_tracking(XP_NON_VAULT)
132     { }
133 
set_non_actor_summonermgen_data134     mgen_data &set_non_actor_summoner(string nas)
135     {
136         non_actor_summoner = nas;
137         return *this;
138     }
139 
set_placemgen_data140     mgen_data &set_place(level_id _place)
141     {
142         place = _place;
143         return *this;
144     }
145 
set_proxmgen_data146     mgen_data &set_prox(proximity_type prox)
147     {
148         proximity = prox;
149         return *this;
150     }
151 
set_colmgen_data152     mgen_data &set_col(int col)
153     {
154         colour = col;
155         return *this;
156     }
157 
set_basemgen_data158     mgen_data &set_base(monster_type base)
159     {
160         base_type = base;
161         return *this;
162     }
163 
164     mgen_data &set_summoned(const actor* _summoner, int abjuration_dur,
165                             int _summon_type, god_type _god = GOD_NO_GOD)
166     {
167         summoner = _summoner;
168         abjuration_duration = abjuration_dur;
169         summon_type = _summon_type;
170         if (_god != GOD_NO_GOD)
171             god = _god;
172 
173         ASSERT(summon_type == 0 || abjuration_dur >= 1 && abjuration_dur <= 6
174                || cls == MONS_BALL_LIGHTNING || cls == MONS_ORB_OF_DESTRUCTION
175                || cls == MONS_BATTLESPHERE || cls == MONS_BALLISTOMYCETE_SPORE
176                || summon_type == SPELL_DEATH_CHANNEL
177                || summon_type == SPELL_BIND_SOULS
178                || summon_type == SPELL_SIMULACRUM
179                || summon_type == SPELL_AWAKEN_VINES
180                || summon_type == SPELL_FULMINANT_PRISM
181                || summon_type == SPELL_INFESTATION
182                || summon_type == SPELL_FOXFIRE
183                || summon_type == SPELL_MARSHLIGHT);
184         return *this;
185     }
186 
permit_bandsmgen_data187     bool permit_bands() const
188     {
189         // The permit flag is set but the forbid flag is not.
190         return (flags & (MG_PERMIT_BANDS|MG_FORBID_BANDS)) == MG_PERMIT_BANDS;
191     }
192 
force_placemgen_data193     bool force_place() const        { return bool(flags & MG_FORCE_PLACE); }
needs_patrol_pointmgen_data194     bool needs_patrol_point() const { return bool(flags & MG_PATROLLING); }
195 
196     // Is there a valid position set on this struct that we want to use
197     // when placing the monster?
use_positionmgen_data198     bool use_position() const { return in_bounds(pos); };
199 
summonedmgen_data200     bool summoned() const { return abjuration_duration > 0; }
201 
202     static mgen_data sleeper_at(monster_type what,
203                                 const coord_def &where,
204                                 mgen_flags genflags = MG_NONE)
205     {
206         return mgen_data(what, BEH_SLEEP, where, MHITNOT, genflags);
207     }
208 
209     static mgen_data hostile_at(monster_type mt,
210                                 bool alert = false,
211                                 const coord_def &p = coord_def(-1, -1))
212 
213     {
214         return mgen_data(mt, BEH_HOSTILE, p, alert ? MHITYOU : MHITNOT);
215     }
216 };
217