forked from cataclysmbnteam/Cataclysm-BN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
active_tile_data.cpp
407 lines (345 loc) · 11.1 KB
/
active_tile_data.cpp
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
#include "active_tile_data.h"
#include "active_tile_data_def.h"
#include "coordinate_conversions.h"
#include "debug.h"
#include "distribution_grid.h"
#include "item.h"
#include "itype.h"
#include "json.h"
#include "map.h"
#include "mapbuffer.h"
#include "rng.h"
#include "vehicle.h"
#include "vpart_range.h"
#include "weather.h"
// TODO: Shouldn't use
#include "submap.h"
static const itype_id itype_battery( "battery" );
static const std::string flag_RECHARGE( "RECHARGE" );
static const std::string flag_USE_UPS( "USE_UPS" );
namespace active_tiles
{
template<typename T>
T *furn_at( const tripoint_abs_ms &p )
{
tripoint_abs_sm p_abs_sm;
point_sm_ms p_within_sm;
std::tie( p_abs_sm, p_within_sm ) = project_remain<coords::sm>( p );
submap *sm = MAPBUFFER.lookup_submap( p_abs_sm );
if( sm == nullptr ) {
return nullptr;
}
auto iter = sm->active_furniture.find( p_within_sm );
if( iter == sm->active_furniture.end() ) {
return nullptr;
}
return dynamic_cast<T *>( &*iter->second );
}
template active_tile_data *furn_at<active_tile_data>( const tripoint_abs_ms & );
template vehicle_connector_tile *furn_at<vehicle_connector_tile>( const tripoint_abs_ms & );
template battery_tile *furn_at<battery_tile>( const tripoint_abs_ms & );
template steady_consumer_tile *furn_at<steady_consumer_tile>( const tripoint_abs_ms & );
template charge_watcher_tile *furn_at<charge_watcher_tile>( const tripoint_abs_ms & );
void furn_transform::serialize( JsonOut &jsout ) const
{
jsout.start_object();
jsout.member( "id", id );
jsout.member( "msg", msg );
jsout.end_object();
}
void furn_transform::deserialize( JsonIn &jsin )
{
JsonObject jo = jsin.get_object();
jo.read( "id", id );
jo.read( "msg", msg );
}
} // namespace active_tiles
active_tile_data::~active_tile_data() = default;
void active_tile_data::serialize( JsonOut &jsout ) const
{
jsout.member( "last_updated", last_updated );
store( jsout );
}
void active_tile_data::deserialize( JsonIn &jsin )
{
JsonObject jo( jsin );
jo.read( "last_updated", last_updated );
load( jo );
}
class null_tile_data : public active_tile_data
{
void update_internal( time_point, const tripoint_abs_ms &, distribution_grid & ) override
{}
active_tile_data *clone() const override {
return new null_tile_data( *this );
}
const std::string &get_type() const override {
static const std::string type( "null" );
return type;
}
void store( JsonOut & ) const override
{}
void load( JsonObject & ) override
{}
};
// Copypasted from character.cpp
// TODO: Move somewhere (calendar?)
inline int ticks_between( const time_point &from, const time_point &to,
const time_duration &tick_length )
{
return ( to_turn<int>( to ) / to_turns<int>( tick_length ) ) - ( to_turn<int>
( from ) / to_turns<int>( tick_length ) );
}
void solar_tile::update_internal( time_point to, const tripoint_abs_ms &p, distribution_grid &grid )
{
constexpr time_point zero = time_point::from_turn( 0 );
constexpr time_duration tick_length = 10_minutes;
constexpr int tick_turns = to_turns<int>( tick_length );
time_duration till_then = get_last_updated() - zero;
time_duration till_now = to - zero;
// This is just for rounding to nearest tick
time_duration ticks_then = till_then / tick_turns;
time_duration ticks_now = till_now / tick_turns;
// This is to cut down on sum_conditions
if( ticks_then == ticks_now ) {
return;
}
time_duration rounded_then = ticks_then * tick_turns;
time_duration rounded_now = ticks_now * tick_turns;
// TODO: Use something that doesn't calc a ton of worthless crap
float sunlight = sum_conditions( zero + rounded_then, zero + rounded_now,
p.raw() ).sunlight / default_daylight_level();
// int64 because we can have years in here
std::int64_t produced = power * static_cast<std::int64_t>( sunlight ) / 1000;
grid.mod_resource( static_cast<int>( std::min( static_cast<std::int64_t>( INT_MAX ), produced ) ) );
}
active_tile_data *solar_tile::clone() const
{
return new solar_tile( *this );
}
const std::string &solar_tile::get_type() const
{
static const std::string type( "solar" );
return type;
}
void solar_tile::store( JsonOut &jsout ) const
{
jsout.member( "power", power );
}
void solar_tile::load( JsonObject &jo )
{
// Can't use generic_factory because we don't have unique ids
jo.read( "power", power );
// TODO: Remove all of this, it's a hack around a mistake
int dummy;
jo.read( "stored_energy", dummy, false );
jo.read( "max_energy", dummy, false );
}
void battery_tile::update_internal( time_point, const tripoint_abs_ms &, distribution_grid & )
{
// TODO: Shouldn't have this function!
}
active_tile_data *battery_tile::clone() const
{
return new battery_tile( *this );
}
const std::string &battery_tile::get_type() const
{
static const std::string type( "battery" );
return type;
}
void battery_tile::store( JsonOut &jsout ) const
{
jsout.member( "stored", stored );
jsout.member( "max_stored", max_stored );
}
void battery_tile::load( JsonObject &jo )
{
jo.read( "stored", stored );
jo.read( "max_stored", max_stored );
}
int battery_tile::get_resource() const
{
return stored;
}
int battery_tile::mod_resource( int amt )
{
// TODO: Avoid int64 math if possible
std::int64_t sum = static_cast<std::int64_t>( stored ) + amt;
if( sum >= max_stored ) {
stored = max_stored;
return sum - max_stored;
} else if( sum <= 0 ) {
stored = 0;
return sum - stored;
} else {
stored = sum;
return 0;
}
}
void charge_watcher_tile::update_internal( time_point /*to*/, const tripoint_abs_ms &p,
distribution_grid &grid )
{
int amt_stored = grid.get_resource();
if( amt_stored >= min_power ) {
get_distribution_grid_tracker().get_transform_queue().add( p, transform.id, transform.msg );
}
}
active_tile_data *charge_watcher_tile::clone() const
{
return new charge_watcher_tile( *this );
}
const std::string &charge_watcher_tile::get_type() const
{
static const std::string type( "charge_watcher" );
return type;
}
void charge_watcher_tile::store( JsonOut &jsout ) const
{
jsout.member( "min_power", min_power );
jsout.member( "transform", transform );
}
void charge_watcher_tile::load( JsonObject &jo )
{
jo.read( "min_power", min_power );
jo.read( "transform", transform );
}
void charger_tile::update_internal( time_point to, const tripoint_abs_ms &p,
distribution_grid &grid )
{
tripoint_abs_sm p_abs_sm;
point_sm_ms p_within_sm;
std::tie( p_abs_sm, p_within_sm ) = project_remain<coords::sm>( p );
submap *sm = MAPBUFFER.lookup_submap( p_abs_sm );
if( sm == nullptr ) {
return;
}
std::int64_t power = this->power * to_seconds<std::int64_t>( to - get_last_updated() );
// TODO: Make not a copy from map.cpp
for( item &outer : sm->get_items( p_within_sm.raw() ) ) {
outer.visit_items( [&power, &grid]( item * it ) {
item &n = *it;
if( !n.has_flag( flag_RECHARGE ) && !n.has_flag( flag_USE_UPS ) ) {
return VisitResponse::NEXT;
}
if( n.ammo_capacity() > n.ammo_remaining() ||
( n.type->battery && n.type->battery->max_capacity > n.energy_remaining() ) ) {
while( power >= 1000 || x_in_y( power, 1000 ) ) {
const int missing = grid.mod_resource( -1 );
if( missing == 0 ) {
if( n.is_battery() ) {
n.mod_energy( 1_kJ );
} else {
n.ammo_set( itype_battery, n.ammo_remaining() + 1 );
}
}
power -= 1000;
}
return VisitResponse::ABORT;
}
return VisitResponse::SKIP;
} );
}
}
active_tile_data *charger_tile::clone() const
{
return new charger_tile( *this );
}
const std::string &charger_tile::get_type() const
{
static const std::string type( "charger" );
return type;
}
void charger_tile::store( JsonOut &jsout ) const
{
jsout.member( "power", power );
}
void charger_tile::load( JsonObject &jo )
{
jo.read( "power", power );
}
void steady_consumer_tile::update_internal( time_point to, const tripoint_abs_ms &p,
distribution_grid &grid )
{
int ticks = ticks_between( get_last_updated(), to, consume_every );
if( ticks == 0 ) {
return;
}
std::int64_t power = this->power * ticks;
int missing = grid.mod_resource( -power );
if( missing == 0 ) {
return;
}
if( transform.id.is_null() ) {
return;
}
get_distribution_grid_tracker().get_transform_queue().add( p, transform.id, transform.msg );
}
active_tile_data *steady_consumer_tile::clone() const
{
return new steady_consumer_tile( *this );
}
const std::string &steady_consumer_tile::get_type() const
{
static const std::string type( "steady_consumer" );
return type;
}
void steady_consumer_tile::store( JsonOut &jsout ) const
{
jsout.member( "power", power );
jsout.member( "consume_every", consume_every );
jsout.member( "transform", transform );
}
void steady_consumer_tile::load( JsonObject &jo )
{
jo.read( "power", power );
jo.read( "consume_every", consume_every );
jo.read( "transform", transform );
}
void vehicle_connector_tile::update_internal( time_point, const tripoint_abs_ms &,
distribution_grid & )
{
}
active_tile_data *vehicle_connector_tile::clone() const
{
return new vehicle_connector_tile( *this );
}
const std::string &vehicle_connector_tile::get_type() const
{
static const std::string type( "vehicle_connector" );
return type;
}
void vehicle_connector_tile::store( JsonOut &jsout ) const
{
jsout.member( "connected_vehicles", connected_vehicles );
}
void vehicle_connector_tile::load( JsonObject &jo )
{
jo.read( "connected_vehicles", connected_vehicles );
}
static std::map<std::string, std::unique_ptr<active_tile_data>> build_type_map()
{
std::map<std::string, std::unique_ptr<active_tile_data>> type_map;
const auto add_type = [&type_map]( active_tile_data * arg ) {
type_map[arg->get_type()].reset( arg );
};
add_type( new battery_tile() );
add_type( new charge_watcher_tile() );
add_type( new charger_tile() );
add_type( new solar_tile() );
add_type( new steady_consumer_tile() );
add_type( new vehicle_connector_tile() );
return type_map;
}
active_tile_data *active_tile_data::create( const std::string &id )
{
static const auto type_map = build_type_map();
const auto iter = type_map.find( id );
if( iter == type_map.end() ) {
debugmsg( "Invalid active_tile_data id %s", id.c_str() );
return new null_tile_data();
}
active_tile_data *new_tile = iter->second->clone();
new_tile->last_updated = calendar::start_of_cataclysm;
return new_tile;
}