-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
item.h
3355 lines (2932 loc) · 150 KB
/
item.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
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#ifndef CATA_SRC_ITEM_H
#define CATA_SRC_ITEM_H
#include <algorithm>
#include <climits>
#include <cstdint>
#include <functional>
#include <iosfwd>
#include <list>
#include <map>
#include <new>
#include <optional>
#include <set>
#include <type_traits>
#include <utility>
#include <vector>
#include "calendar.h"
#include "cata_lazy.h"
#include "cata_utility.h"
#include "compatibility.h"
#include "enums.h"
#include "gun_mode.h"
#include "io_tags.h"
#include "item_components.h"
#include "item_contents.h"
#include "item_location.h"
#include "item_tname.h"
#include "material.h"
#include "requirements.h"
#include "safe_reference.h"
#include "type_id.h"
#include "units.h"
#include "value_ptr.h"
#include "visitable.h"
#include "vpart_position.h"
#include "rng.h"
class Character;
class Creature;
class JsonObject;
class JsonOut;
class book_proficiency_bonuses;
class enchantment;
class enchant_cache;
class faction;
class gun_type_type;
class gunmod_location;
class item;
class iteminfo_query;
class monster;
class nc_color;
enum class pocket_type;
class recipe;
class relic;
struct part_material;
struct armor_portion_data;
struct itype_variant_data;
struct islot_comestible;
struct itype;
struct item_comp;
template<typename CompType>
struct comp_selection;
struct tool_comp;
struct mtype;
struct tripoint;
template<typename T>
class ret_val;
template <typename T> struct enum_traits;
class vehicle;
namespace enchant_vals
{
enum class mod : int;
} // namespace enchant_vals
using bodytype_id = std::string;
using faction_id = string_id<faction>;
class item_category;
struct islot_armor;
struct use_function;
enum art_effect_passive : int;
enum class side : int;
class body_part_set;
class map;
struct damage_instance;
struct damage_unit;
struct fire_data;
enum class link_state : int;
enum clothing_mod_type : int;
struct light_emission {
unsigned short luminance;
short width;
short direction;
};
extern light_emission nolight;
/**
* Value and metadata for one property of an item
*
* Contains the value of one property of an item, as well as various metadata items required to
* output that value. This is used primarily for user output of information about an item, for
* example in the various inventory menus. See @ref item::info() for the main example of how a
* class desiring to provide user output might obtain a class of this type.
*
* As an example, if the item being queried was a piece of clothing, then several properties might
* be returned. All would have sType "ARMOR". There would be one for the coverage stat with
* sName "Coverage: ", another for the warmth stat with sName "Warmth: ", etc.
*/
struct iteminfo {
public:
/** Category of item that owns this iteminfo. See @ref item_category. */
std::string sType;
/** Main text of this property's name */
std::string sName;
/** Formatting text to be placed between the name and value of this item. */
std::string sFmt;
/** Numerical value of this property. Set to -999 if no compare value is present */
std::string sValue;
/** Internal double floating point version of value, for numerical comparisons */
double dValue;
/** Same as dValue, adjusted for the minimum unit (for numerical comparisons) */
double dUnitAdjustedVal;
/** Flag indicating type of sValue. True if integer, false if single decimal */
bool is_int;
/** Flag indicating whether a newline should be printed after printing this item */
bool bNewLine;
/** Reverses behavior of red/green text coloring; smaller values are green if true */
bool bLowerIsBetter;
/** Whether to print sName. If false, use for comparisons but don't print for user. */
bool bDrawName;
/** Whether to print a sign on positive values */
bool bShowPlus;
/** Flag indicating decimal with three points of precision. */
bool three_decimal;
/** info is ASCII art (prefer monospaced font) */
bool bIsArt;
enum flags {
no_flags = 0,
is_decimal = 1 << 0, ///< Print as decimal rather than integer
is_three_decimal = 1 << 1, ///< Print as decimal with three points of precision
no_newline = 1 << 2, ///< Do not follow with a newline
lower_is_better = 1 << 3, ///< Lower values are better for this stat
no_name = 1 << 4, ///< Do not print the name
show_plus = 1 << 5, ///< Use a + sign for positive values
is_art = 1 << 6, ///< is ascii art (prefer monospaced font)
};
/**
* @param Type The item type of the item this iteminfo belongs to.
* @param Name The name of the property this iteminfo describes.
* @param Fmt Formatting text desired between item name and value
* @param Flags Additional flags to customize this entry
* @param Value Numerical value of this property, -999 for none.
*/
iteminfo( const std::string &Type, const std::string &Name, const std::string &Fmt = "",
flags Flags = no_flags, double Value = -999, double UnitVal = 0 );
iteminfo( const std::string &Type, const std::string &Name, flags Flags );
iteminfo( const std::string &Type, const std::string &Name, double Value, double UnitVal = 0 );
};
template<>
struct enum_traits<iteminfo::flags> {
static constexpr bool is_flag_enum = true;
};
iteminfo vol_to_info( const std::string &type, const std::string &left,
const units::volume &vol, int decimal_places = 2, bool lower_is_better = true );
iteminfo weight_to_info( const std::string &type, const std::string &left,
const units::mass &weight, int decimal_places = 2, bool lower_is_better = true );
inline bool is_crafting_component( const item &component );
struct stacking_info {
tname::segment_bitset bits;
// NOLINTNEXTLINE(google-explicit-constructor)
operator bool() const {
return bits.all();
}
};
class item : public visitable
{
public:
using FlagsSetType = std::set<flag_id>;
item();
item( item && ) noexcept;
item( const item & );
item &operator=( item && ) noexcept;
item &operator=( const item & );
explicit item( const itype_id &id, time_point turn = calendar::turn, int qty = -1 );
explicit item( const itype *type, time_point turn = calendar::turn, int qty = -1 );
/** Suppress randomization and always start with default quantity of charges */
struct default_charges_tag {};
item( const itype_id &id, time_point turn, default_charges_tag );
item( const itype *type, time_point turn, default_charges_tag );
/** Default (or randomized) charges except if counted by charges then only one charge */
struct solitary_tag {};
item( const itype_id &id, time_point turn, solitary_tag );
item( const itype *type, time_point turn, solitary_tag );
/** For constructing in-progress crafts */
item( const recipe *rec, int qty, item_components items, std::vector<item_comp> selections );
/** For constructing in-progress disassemblies */
item( const recipe *rec, int qty, item &component );
// Legacy constructor for constructing from string rather than itype_id
// TODO: remove this and migrate code using it.
template<typename... Args>
explicit item( const std::string &itype, Args &&... args ) :
item( itype_id( itype ), std::forward<Args>( args )... )
{}
~item() override;
/** Return a pointer-like type that's automatically invalidated if this
* item is destroyed or assigned-to */
safe_reference<item> get_safe_reference();
/**
* Filter converting this instance to another type preserving all other aspects
* @param new_type the type id to convert to
* @param carrier A pointer to the character that's carrying the item, nullptr if none, which is the default.
* @return same instance to allow method chaining
*/
item &convert( const itype_id &new_type, Character *carrier = nullptr );
/**
* Filter converting this instance to the inactive type
* If the item is either inactive or cannot be deactivated is a no-op
* @param ch character currently possessing or acting upon the item (if any)
* @param alert whether to display any messages
* @return same instance to allow method chaining
*/
item &deactivate( Character *ch = nullptr, bool alert = true );
/** Filter converting instance to active state */
item &activate();
/**
* Invoke use function on a thrown item that had "ACT_ON_RANGED_HIT" flag.
* The function is called on the spot where the item landed.
* @param pos position
* @return true if the item was destroyed (exploded)
*/
bool activate_thrown( const tripoint &pos );
/**
* Add or remove energy from a battery.
* If adding the specified energy quantity would go over the battery's capacity fill
* the battery and ignore the remainder.
* If adding the specified energy quantity would reduce the battery's charge level
* below 0 do nothing and return how far below 0 it would have gone.
* @param qty energy quantity to add (can be negative)
* @return 0 valued energy quantity on success
*/
units::energy mod_energy( const units::energy &qty );
/**
* Filter setting the ammo for this instance
* Any existing ammo is removed. If necessary a magazine is also added.
* @param ammo specific type of ammo (must be compatible with item ammo type)
* @param qty maximum ammo (capped by item capacity) or negative to fill to capacity
* @return same instance to allow method chaining
*/
item &ammo_set( const itype_id &ammo, int qty = -1 );
/**
* Filter removing all ammo from this instance
* If the item is neither a tool, gun nor magazine is a no-op
* For items reloading using magazines any empty magazine remains present.
*/
item &ammo_unset();
/**
* Sets item damage constrained by [@ref degradation and @ref max_damage]
*/
void set_damage( int qty );
/**
* Sets item's degradation constrained by [0 and @ref max_damage]
* If item damage is lower it is raised up to @ref degradation
*/
void set_degradation( int qty );
/**
* Splits a count-by-charges item always leaving source item with minimum of 1 charge
* @param qty number of required charges to split from source
* @return new instance containing exactly qty charges or null item if splitting failed
*/
item split( int qty );
/**
* Make a corpse of the given monster type.
* The monster type id must be valid (see @ref MonsterGenerator::get_all_mtypes).
*
* The turn parameter sets the birthday of the corpse, in other words: the turn when the
* monster died. Because corpses are removed from the map when they reach a certain age,
* one has to be careful when placing corpses with a birthday of 0. They might be
* removed immediately when the map is loaded without been seen by the player.
*
* The name parameter can be used to give the corpse item a name. This is
* used instead of the monster type name ("corpse of X" instead of "corpse of bear").
*
* With the default parameters it makes a human corpse, created at the current turn.
*/
/*@{*/
static item make_corpse( const mtype_id &mt = string_id<mtype>::NULL_ID(),
time_point turn = calendar::turn, const std::string &name = "", int upgrade_time = -1 );
/*@}*/
/**
* @return The monster type associated with this item (@ref corpse). It is usually the
* type that this item is made of (e.g. corpse, meat or blood of the monster).
* May return a null-pointer.
*/
const mtype *get_mtype() const;
/**
* Sets the monster type associated with this item (@ref corpse). You must not pass a
* null pointer.
* TODO: change this to take a reference instead.
*/
void set_mtype( const mtype *m );
/**
* Whether this is a corpse item. Corpses always have valid monster type (@ref corpse)
* associated (@ref get_mtype return a non-null pointer) and have been created
* with @ref make_corpse.
*/
bool is_corpse() const;
/**
* Whether this is a corpse that can be revived.
*/
bool can_revive() const;
/**
* Whether this corpse should revive now. Note that this function includes some randomness,
* the return value can differ on successive calls.
* @param pos The location of the item (see REVIVE_SPECIAL flag).
*/
bool ready_to_revive( map &here, const tripoint &pos ) const;
bool is_money() const;
private:
bool is_money( const std::set<ammotype> &ammo ) const;
public:
bool is_cash_card() const;
bool is_software() const;
bool is_software_storage() const;
bool is_ebook_storage() const;
/**
* Checks whether the item's components (and sub-components if deep_search) are food items
* Used for calculating nutrients of crafted food
*/
bool made_of_any_food_components( bool deep_search = false ) const;
/**
* A heuristic on whether it's a good idea to use this as a melee weapon.
* Used for nicer messages only.
*/
bool is_maybe_melee_weapon() const;
/**
* Returns whether this weapon does any damage type suitable for diamond coating.
*/
bool has_edged_damage() const;
/**
* Returns a symbol for indicating the current dirt or fouling level for a gun.
*/
std::string dirt_symbol() const;
/**
* Returns a symbol for indicating the overheat level for a gun.
*/
std::string overheat_symbol() const;
/**
* Returns a symbol indicating the current degradation of the item.
*/
std::string degradation_symbol() const;
/**
* Returns the default color of the item (e.g. @ref itype::color).
*/
nc_color color() const;
/**
* Returns the color of the item depending on usefulness for the player character,
* e.g. differently if it its an unread book or a spoiling food item etc.
* This should only be used for displaying data, it should not affect game play.
*/
nc_color color_in_inventory( const Character *ch = nullptr ) const;
/**
* Return the (translated) item name.
* @param quantity used for translation to the proper plural form of the name, e.g.
* returns "rock" for quantity 1 and "rocks" for quantity > 0.
* @param segments determines which tname elements are included
*/
std::string tname( unsigned int quantity = 1,
tname::segment_bitset const &segments = tname::default_tname ) const;
std::string tname( unsigned int quantity, bool with_prefix ) const;
static std::string tname( const itype_id &id, unsigned int quantity = 1,
tname::segment_bitset const &segments = tname::default_tname );
std::string display_money( unsigned int quantity, unsigned int total,
const std::optional<unsigned int> &selected = std::nullopt ) const;
/**
* Returns the item name and the charges or contained charges (if the item can have
* charges at all). Calls @ref tname with given quantity and with_prefix being true.
*/
std::string display_name( unsigned int quantity = 1 ) const;
std::vector<iteminfo> get_info( bool showtext ) const;
std::vector<iteminfo> get_info( bool showtext, int batch ) const;
std::vector<iteminfo> get_info( const iteminfo_query *parts, int batch ) const;
/**
* Return all the information about the item and its type.
*
* This includes the different
* properties of the @ref itype (if they are visible to the player). The returned string
* is already translated and can be *very* long.
* @param showtext If true, shows the item description, otherwise only the properties item type.
*/
std::string info( bool showtext = false ) const;
/**
* Return all the information about the item and its type, and dump to vector.
*
* This includes the different
* properties of the @ref itype (if they are visible to the player). The returned string
* is already translated and can be *very* long.
* @param showtext If true, shows the item description, otherwise only the properties item type.
* @param iteminfo The properties (encapsulated into @ref iteminfo) are added to this vector,
* the vector can be used to compare them to properties of another item.
*/
std::string info( bool showtext, std::vector<iteminfo> &iteminfo ) const;
/**
* Return all the information about the item and its type, and dump to vector.
*
* This includes the different
* properties of the @ref itype (if they are visible to the player). The returned string
* is already translated and can be *very* long.
* @param showtext If true, shows the item description, otherwise only the properties item type.
* @param iteminfo The properties (encapsulated into @ref iteminfo) are added to this vector,
* the vector can be used to compare them to properties of another item.
* @param batch The batch crafting number to multiply data by
*/
std::string info( bool showtext, std::vector<iteminfo> &iteminfo, int batch ) const;
/**
* Return all the information about the item and its type, and dump to vector.
*
* This includes the different
* properties of the @ref itype (if they are visible to the player). The returned string
* is already translated and can be *very* long.
* @param parts controls which parts of the iteminfo to return.
* @param info The properties (encapsulated into @ref iteminfo) are added to this vector,
* the vector can be used to compare them to properties of another item.
* @param batch The batch crafting number to multiply data by
*/
std::string info( std::vector<iteminfo> &info, const iteminfo_query *parts = nullptr,
int batch = 1 ) const;
/* type specific helper functions for info() that should probably be in itype() */
void basic_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void debug_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void med_info( const item *med_item, std::vector<iteminfo> &info, const iteminfo_query *parts,
int batch, bool debug ) const;
void food_info( const item *food_item, std::vector<iteminfo> &info, const iteminfo_query *parts,
int batch, bool debug ) const;
void rot_info( const item *food_item, std::vector<iteminfo> &info, const iteminfo_query *parts,
int batch, bool debug ) const;
void magazine_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void ammo_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void gun_info( const item *mod, std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void gunmod_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void armor_protection_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug, const sub_bodypart_id &sbp = sub_bodypart_id() ) const;
void armor_material_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug, const sub_bodypart_id &sbp = sub_bodypart_id() ) const;
void armor_attribute_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug, const sub_bodypart_id &sbp = sub_bodypart_id() ) const;
void pet_armor_protection_info( std::vector<iteminfo> &info, const iteminfo_query *parts ) const;
void armor_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void animal_armor_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void armor_fit_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void book_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void battery_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void tool_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void actions_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void component_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void enchantment_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void repair_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void disassembly_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void qualities_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void bionic_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void melee_combat_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void contents_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void properties_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void ascii_art_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
void final_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool debug ) const;
/**
* Calculate all burning calculations, but don't actually apply them to item.
* DO apply them to @ref fire_data argument, though.
* @return Amount of "burn" that would be applied to the item.
*/
float simulate_burn( fire_data &frd ) const;
/** Burns the item. Returns true if the item was destroyed. */
bool burn( fire_data &frd );
// Returns the category of this item, regardless of contents.
const item_category &get_category_shallow() const;
// Returns the dominant category of items inside this one.
// "can of meat" would be food, instead of container.
const item_category &get_category_of_contents( int depth = 0, int maxdepth = 2 ) const;
class reload_option
{
public:
reload_option() = default;
reload_option( const reload_option & );
reload_option &operator=( const reload_option & );
reload_option( const Character *who, const item_location &target, const item_location &ammo );
const Character *who = nullptr;
item_location target;
item_location ammo;
int qty() const {
return qty_;
}
void qty( int val );
int moves() const;
explicit operator bool() const {
return who && target && ammo && qty_ > 0;
}
private:
int qty_ = 0;
int max_qty = INT_MAX;
};
/**
* Reload item using ammo from location returning true if successful
* @param u Player doing the reloading
* @param ammo Location of ammo to be reloaded
* @param qty caps reloading to this (or fewer) units
*/
bool reload( Character &u, item_location ammo, int qty );
// is this speedloader compatible with this item?
bool allows_speedloader( const itype_id &speedloader_id ) const;
template<typename Archive>
void io( Archive & );
using archive_type_tag = io::object_archive_tag;
void serialize( JsonOut &json ) const;
void deserialize( const JsonObject &data );
const std::string &symbol() const;
/**
* Returns the monetary value of an item.
* If `practical` is false, returns pre-Cataclysm market value,
* otherwise returns approximate post-cataclysm value.
*/
int price( bool practical ) const;
/**
* Returns the monetary value of an item by itself.
* If `practical` is false, returns pre-Cataclysm market value,
* otherwise returns approximate post-cataclysm value.
*/
int price_no_contents( bool practical, std::optional<int> price_override = std::nullopt ) const;
/**
* Whether two items should stack when displayed in a inventory menu.
* This is different from stacks_with, when two previously non-stackable
* items are now stackable and mergeable because, for example, they
* reaches the same temperature. This is necessary to avoid misleading
* stacks like "3 items-count-by-charge (5)".
*/
bool display_stacked_with( const item &rhs, bool check_components = false ) const;
/**
* Check wether each element of tname::segments stacks, ie. wether the respective
* pieces of information are considered equal for display purposes
*
* stacking_info is implicitly convertible to bool and will be true only if ALL segments stack
*/
stacking_info stacks_with( const item &rhs, bool check_components = false,
bool combine_liquid = false, bool check_cat = false,
int depth = 0, int maxdepth = 2, bool precise = false ) const;
/**
* Whether the two items have same contents.
* Checks the contents and the contents of the contents.
*/
bool same_contents( const item &rhs ) const;
/**
* Whether item is the same as `rhs` for RLE compression purposes.
* Essentially a stricter version of `stacks_with`.
* @return true if items are same, i.e. *this is "equal" to `item(rhs)`
* @note false negative results are OK
* @note must be transitive
*/
bool same_for_rle( const item &rhs ) const;
/** combines two items together if possible. returns false if it fails. */
bool combine( const item &rhs );
bool can_combine( const item &rhs ) const;
/**
* Merge charges of the other item into this item.
* @return true if the items have been merged, otherwise false.
* Merging is only done for items counted by charges (@ref count_by_charges) and
* items that stack together (@ref stacks_with).
*/
bool merge_charges( const item &rhs );
/**
* Total weight of an item accounting for all contained/integrated items
* @param include_contents if true include weight of contained items
* @param integral if true return effective weight if this item was integrated into another
*/
units::mass weight( bool include_contents = true, bool integral = false ) const;
/**
* Total volume of an item accounting for all contained/integrated items
* NOTE: Result is rounded up to next nearest milliliter when working with stackable (@ref count_by_charges) items that have fractional volume per charge.
* If trying to determine how many of an item can fit in a given space, @ref charges_per_volume should be used instead.
* @param integral if true return effective volume if this item was integrated into another
* @param ignore_contents if true return effective volume for the item alone, ignoring its contents
* @param charges_in_vol if specified, get the volume for this many charges instead of current charges
*/
units::volume volume( bool integral = false, bool ignore_contents = false,
int charges_in_vol = -1 ) const;
units::length length() const;
units::length barrel_length() const;
/**
* Simplified, faster volume check for when processing time is important and exact volume is not.
* NOTE: Result is rounded up to next nearest milliliter when working with stackable (@ref count_by_charges) items that have fractional volume per charge.
* If trying to determine how many of an item can fit in a given space, @ref charges_per_volume should be used instead.
*/
units::volume base_volume() const;
/** Volume check for corpses, helper for base_volume(). */
units::volume corpse_volume( const mtype *corpse ) const;
/**
* Volume to subtract when the item is collapsed or folded.
* @result positive value when the item increases in volume when wielded and 0 if no change.
*/
units::volume collapsed_volume_delta() const;
/** Required strength to be able to successfully lift the item unaided by equipment */
int lift_strength() const;
/**
* @name Melee
*
* The functions here assume the item is used in melee, even if's a gun or not a weapon at
* all. Because the functions apply to all types of items, several of the is_* functions here
* may return true for the same item. This only indicates that it can be used in various ways.
*/
/*@{*/
/**
* Base number of moves (@ref Creature::moves) that a single melee attack with this items
* takes. The actual time depends heavily on the attacker, see melee.cpp.
*/
int attack_time( const Character &you ) const;
/** Damage of given type caused when this item is used as melee weapon */
int damage_melee( const damage_type_id &dt ) const;
/** All damage types this item deals when used in melee (no skill modifiers etc. applied). */
damage_instance base_damage_melee() const;
/** All damage types this item deals when thrown (no skill modifiers etc. applied). */
damage_instance base_damage_thrown() const;
/**
* Calculate the item's effective damage per second past armor when wielded by a
* character against a monster.
*/
double effective_dps( const Character &guy, Creature &mon ) const;
/**
* calculate effective dps against a stock set of monsters. by default, assume g->u
* is wielding
* for_display - include monsters intended for display purposes
* for_calc - include monsters intended for evaluation purposes
* for_display and for_calc are inclusive
*/
std::map<std::string, double> dps( bool for_display, bool for_calc, const Character &guy ) const;
std::map<std::string, double> dps( bool for_display, bool for_calc ) const;
/** return the average dps of the weapon against evaluation monsters */
double average_dps( const Character &guy ) const;
/**
* Whether the character needs both hands to wield this item.
*/
bool is_two_handed( const Character &guy ) const;
/** Is this item an effective melee weapon for the given damage type? */
bool is_melee( const damage_type_id &dt ) const;
/**
* Is this item an effective melee weapon for any damage type?
* @see item::is_gun()
* @note an item can be both a gun and melee weapon concurrently
*/
bool is_melee() const;
/**
* The most relevant skill used with this melee weapon. Can be "null" if this is not a weapon.
* Note this function returns null if the item is a gun for which you can use gun_skill() instead.
*/
skill_id melee_skill() const;
/*@}*/
/*
* Max range of melee attack this weapon can be used for.
* Accounts for character's abilities and installed gun mods.
* Guaranteed to be at least 1
*/
int reach_range( const Character &guy ) const;
/*
* Max range of melee attack this weapon can be used for in its current state.
* Accounts for character's abilities and installed gun mods.
* Guaranteed to be at least 1
*/
int current_reach_range( const Character &guy ) const;
/**
* Sets time until activation for an item that will self-activate in the future.
**/
void set_countdown( int num_turns );
/**
* Consumes specified charges (or fewer) from this and any contained items
* @param what specific type of charge required, e.g. 'battery'
* @param qty maximum charges to consume. On return set to number of charges not found (or zero)
* @param used filled with duplicates of each item that provided consumed charges
* @param pos position at which the charges are being consumed
* @param filter Must return true for use to occur.
* @return true if this item should be deleted (count-by-charges items with no remaining charges)
*/
bool use_charges( const itype_id &what, int &qty, std::list<item> &used, const tripoint &pos,
const std::function<bool( const item & )> &filter = return_true<item>,
Character *carrier = nullptr, bool in_tools = false );
/**
* Invokes item type's @ref itype::drop_action.
* This function can change the item.
* @param pos Where is the item being placed. Note: the item isn't there yet.
* @return true if the item was destroyed during placement.
*/
bool on_drop( const tripoint &pos );
/**
* Invokes item type's @ref itype::drop_action.
* This function can change the item.
* @param pos Where is the item being placed. Note: the item isn't there yet.
* @param map A map object associated with that position.
* @return true if the item was destroyed during placement.
*/
// TODO: Get rid of untyped overload.
bool on_drop( const tripoint &pos, map &map );
bool on_drop( const tripoint_bub_ms &pos, map &map );
/**
* Consume a specific amount of items of a specific type.
* This includes this item, and any of its contents (recursively).
* @see item::use_charges - this is similar for items, not charges.
* @param it Type of consumable item.
* @param quantity How much to consumed.
* @param used On success all consumed items will be stored here.
* @param filter Must return true for use to occur.
*/
bool use_amount( const itype_id &it, int &quantity, std::list<item> &used,
const std::function<bool( const item & )> &filter = return_true<item> );
/** Permits filthy components, should only be used as a helper in creating filters */
bool allow_crafting_component() const;
// seal the item's pockets. used for crafting and spawning items.
bool seal();
bool all_pockets_sealed() const;
bool any_pockets_sealed() const;
/** Whether this is container. Note that container does not necessarily means it's
* suitable for liquids. */
bool is_container() const;
/** Whether it is a container, and if it is has some restrictions */
bool is_container_with_restriction() const;
/** Whether it is a container with only one pocket, and if it is has some restrictions */
bool is_single_container_with_restriction() const;
// whether the contents has a pocket with the associated type
bool has_pocket_type( pocket_type pk_type ) const;
bool has_any_with( const std::function<bool( const item & )> &filter,
pocket_type pk_type ) const;
/** True if every pocket is rigid or we have no pockets */
bool all_pockets_rigid() const;
bool container_type_pockets_empty() const;
// gets all pockets contained in this item
std::vector<const item_pocket *> get_all_contained_pockets() const;
std::vector<item_pocket *> get_all_contained_pockets();
std::vector<const item_pocket *> get_all_standard_pockets() const;
std::vector<item_pocket *> get_all_standard_pockets();
std::vector<item_pocket *> get_all_ablative_pockets();
std::vector<const item_pocket *> get_all_ablative_pockets() const;
/**
* Updates the pockets of this item to be correct based on the mods that are installed.
* Pockets which are modified that contain an item will be spilled
* NOTE: This assumes that there is always one and only one pocket where ammo goes (mag or mag well)
*/
void update_modified_pockets();
// for pocket update stuff, which pocket is @contained in?
// returns a nullptr if the item is not contained, and prints a debug message
item_pocket *contained_where( const item &contained );
const item_pocket *contained_where( const item &contained ) const;
/** Whether this is a container which can be used to store liquids. */
bool is_watertight_container() const;
/** Whether this item has no contents at all. */
bool is_container_empty() const;
/**
* Whether this item has no more free capacity for its current content.
* @param allow_bucket Allow filling non-sealable containers
*/
bool is_container_full( bool allow_bucket = false ) const;
/**
* Whether the magazine pockets of this item have room for additional items
*/
bool is_magazine_full() const;
/**
* Fill item with an item up to @amount number of items. This works for any item with container pockets.
* @param contained item to fill the container with.
* @param amount Amount to fill item with, capped by remaining capacity
* @returns amount of contained that was put into it
*/
int fill_with( const item &contained, int amount = INFINITE_CHARGES,
bool unseal_pockets = false,
bool allow_sealed = false,
bool ignore_settings = false,
bool into_bottom = false,
Character *carrier = nullptr );
/**
* How much more of this liquid (in charges) can be put in this container.
* If this is not a container (or not suitable for the liquid), it returns 0.
* Note that mixing different types of liquid is not possible.
* Also note that this works for guns and tools that accept liquid ammo.
* @param liquid Liquid to check capacity for
* @param allow_bucket Allow filling non-sealable containers
* @param err Message to print if no more material will fit
*/
int get_remaining_capacity_for_liquid( const item &liquid, bool allow_bucket = false,
std::string *err = nullptr ) const;
int get_remaining_capacity_for_liquid( const item &liquid, const Character &p,
std::string *err = nullptr ) const;
units::volume total_contained_volume() const;
/**
* It returns the maximum volume of any contents, including liquids,
* ammo, magazines, weapons, etc.
*/
units::volume get_total_capacity( bool unrestricted_pockets_only = false ) const;
units::mass get_total_weight_capacity( bool unrestricted_pockets_only = false ) const;
units::volume get_remaining_capacity( bool unrestricted_pockets_only = false ) const;
units::mass get_remaining_weight_capacity( bool unrestricted_pockets_only = false ) const;
units::volume get_total_contained_volume( bool unrestricted_pockets_only = false ) const;
units::mass get_total_contained_weight( bool unrestricted_pockets_only = false ) const;
int get_used_holsters() const;
int get_total_holsters() const;
units::volume get_total_holster_volume() const;
units::volume get_used_holster_volume() const;
units::mass get_total_holster_weight() const;
units::mass get_used_holster_weight() const;
// recursive function that checks pockets for remaining free space
units::volume check_for_free_space() const;
units::volume get_selected_stack_volume( const std::map<const item *, int> &without ) const;
bool has_unrestricted_pockets() const;
units::volume get_contents_volume_with_tweaks( const std::map<const item *, int> &without ) const;
units::volume get_nested_content_volume_recursive( const std::map<const item *, int> &without )
const;
// returns the abstract 'size' of the pocket
// used for attaching to molle items
int get_pocket_size() const;
/**
* Returns true if the item can be attached with PALS straps
*/
bool can_attach_as_pocket() const;
// what will the move cost be of taking @it out of this container?
// should only be used from item_location if possible, to account for
// player inventory handling penalties from traits
int obtain_cost( const item &it ) const;
// what will the move cost be of storing @it into this container? (CONTAINER pocket type)
int insert_cost( const item &it ) const;
/**
* Puts the given item into this one.
*/
ret_val<void> put_in( const item &payload, pocket_type pk_type,
bool unseal_pockets = false, Character *carrier = nullptr );
void force_insert_item( const item &it, pocket_type pk_type );
/**
* Returns this item into its default container. If it does not have a default container,
* returns this. It's intended to be used like \code newitem = newitem.in_its_container();\endcode
* qty <= 0 means the current quantity of the item will be used. Any quantity exceeding the capacity
* of the container will be ignored.
*/
item in_its_container( int qty = 0 ) const;
item in_container( const itype_id &container_type, int qty = 0, bool sealed = true,
const std::string &container_variant = "" ) const;
void add_automatic_whitelist();
void clear_automatic_whitelist();
/**
* True if item and its contents have any uses.
* @param contents_only Set to true to ignore the item itself and check only its contents.
*/
bool item_has_uses_recursive( bool contents_only = false ) const;
/*@{*/
/**
* Funnel related functions. See weather.cpp for their usage.
*/
bool is_funnel_container( units::volume &bigger_than ) const;
void add_rain_to_container( int charges = 1 );
/*@}*/
/**
* Returns true if this item itself is of at least quality level
* This version is non-recursive and does not check the item contents.
*/