-
Notifications
You must be signed in to change notification settings - Fork 30
/
field.h
228 lines (183 loc) · 6.12 KB
/
field.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
#ifndef _FIELD_H_
#define _FIELD_H_
#include "enum.h" // For Body_part
#include "damage_set.h"
#include "enum.h" // For Terrain_flag
#include "enum.h" // For Item_flag
#include "glyph.h"
#include "terrain.h" // For Terrain*
#include "geometry.h" // For Tripoint
#include "explosion.h" // For fuel explosions
#include <string>
#include <vector>
#include <list>
#include <istream>
class Entity;
class Map;
/* If you're familiar with them, fields in Cataclysm 2 are very similar to those
* in Cataclysm 1.
* TODO: Do we need a "dangerous" flag to warn players against stepping into a
* field?
*/
enum Field_flag
{
FIELD_FLAG_NULL = 0,
FIELD_FLAG_SOLID, // "solid" - can be placed on solid terrain
FIELD_FLAG_DIFFUSE, // "diffuse" - spread even if the cost will destroy us
FIELD_FLAG_RISE, // "rise" - goes up, loses duration if empty ter above
FIELD_FLAG_MAX
};
Field_flag lookup_field_flag(std::string name);
std::string field_flag_name(Field_flag flag);
struct Field_fuel
{
Field_fuel(Terrain_flag TF = TF_NULL, Item_flag IF = ITEM_FLAG_NULL,
int _fuel = 0, Dice damage = Dice());
~Field_fuel() { }
Terrain_flag terrain_flag;
Item_flag item_flag;
bool any_item; // If true, then we consume any item!
int fuel; // Fuel gained; may be negative! (e.g. water puts fire out)
/* Damage done to the terrain/item each turn
* If 0, then the terrain/item is not damaged or destroyed at all! This is
* permitted, but note that if the value of fuel is > 0, this will result in the
* field basically being perpetual.
*/
Dice damage;
std::string output_field; // A field created as output, e.g. smoke
// Duration of the output field; if a negative number is rolled, no output field
Dice output_duration;
// Explosion data; has_explosion is false, set to true when explosion loads
bool has_explosion;
Explosion explosion; // Explosion caused!
bool load_data(std::istream& data, std::string owner_name = "Unknown");
};
class Field_level
{
public:
Field_level();
~Field_level();
std::string name;
glyph sym;
int duration; // Our starting "hp," lose one per turn
int duration_lost_without_fuel; // Extra duration lost if there's no fuel
std::list<Field_fuel> fuel; // Level-specific fuel.
/* Danger defaults to 0.
* If danger > 0, the player is warned before stepping in this field.
* Added to the move_cost of the tile for field-aware monster pathing.
*/
int danger;
std::string verb; // The fire [burns] you! The electricity [shocks] you!
Damage_set damage;
std::list<Body_part> body_parts_hit;
/* TODO: Add status effect inflicted
* And anything else?
* TODO: Maybe some flags for hard-coded effects; e.g. electricity stays close
* to walls
*/
bool load_data(std::istream& data, std::string owner_name);
std::string get_name();
bool has_flag(Field_flag ff);
bool has_flag(Terrain_flag tf);
private:
/* terrain_flags is mostly included so we can make a field block LoS, but it
* could have other uses too...?
*/
std::vector<bool> terrain_flags; // Same as terrain uses!
std::vector<bool> field_flags;
};
class Field_type
{
public:
Field_type();
~Field_type();
std::string name;
std::string display_name;
int uid;
std::list<Field_fuel> fuel;
int spread_chance; // Percentage chance each turn
int spread_cost; // Percentage of our duration lost when spreading
int output_chance; // Percentage chance of extra output each turn
int output_cost; // Percent of our duration lost when outputting
std::string output_type; // Name of the field we output
void assign_uid(int id) { uid = id; }
std::string get_data_name();
std::string get_name();
std::string get_level_name(int level);
Field_level* get_level(int level);
bool has_flag(Terrain_flag tf, int level = -1);
bool has_flag(Field_flag ff, int level = -1);
int duration_needed_to_reach_level(int level);
int get_uid();
bool load_data(std::istream& data);
private:
std::vector<Field_level*> levels;
/* terrain_flags is mostly included so we can make a field block LoS, but it
* could have other uses too...?
*/
std::vector<bool> terrain_flags; // Same as terrain uses!
std::vector<bool> field_flags;
};
// Used for attacks and tools
struct Field_pool
{
Field_pool();
~Field_pool();
Field_type* type;
Dice duration;
Dice tiles;
bool exists();
void drop(Tripoint pos, std::string creator = "");
bool load_data(std::istream& data, std::string owner_name = "Unknown");
};
// This one is actually used in Tile (part of Submaps)
class Field
{
public:
Field(Field_type* T = NULL, int L = 0, std::string C = "");
~Field();
Field_type* type;
int level;
int duration;
bool dead; // If true, this needs to be cleaned up
/* We use creator to tell the player what killed them; e.g. if creator is
* "a spitter zombie" then we got killed by "acid created by a spitter zombie"
*/
std::string creator; // Name of what created us
// Type information
int get_type_uid() const;
bool is_valid();
bool has_flag(Field_flag flag);
bool has_flag(Terrain_flag flag);
std::string get_name(); // Type name
std::string get_full_name(); // get_name() + " created by " + owner
glyph top_glyph();
// Status information
int get_full_duration() const;
// Active functions
Field& operator+=(const Field& rhs);
void set_duration(int dur);
void hit_entity(Entity* entity);
void process(Map* map, Tripoint pos);
void gain_level();
void lose_level();
void adjust_level(); // Fixes level based on duration
// File I/O
std::string save_data();
bool load_data(std::istream& data);
private:
// consume_fuel iterates over type/level's fuels and runs look_for_fuel on each
// It returns true if we consumed fuel.
bool consume_fuel(Map* map, Tripoint pos);
// look_for_fuel is the nuts & bolts of consuming a fuel/extinguisher
// It returns true if we consumed fuel.
// It modifies output - a list of "smoke" we put out.
bool look_for_fuel(Field_fuel fuel, Map* map, Tripoint pos,
std::vector<Field>& output);
};
inline Field operator+(Field lhs, const Field& rhs)
{
lhs += rhs;
return lhs;
}
#endif