forked from CleverRaven/Cataclysm-DDA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ammo_test.cpp
267 lines (222 loc) · 10.6 KB
/
ammo_test.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
#include "cata_catch.h"
#include <set>
#include "damage.h"
#include "item.h"
#include "type_id.h"
#include "units.h"
static const ammotype ammo_762( "762" );
static const ammotype ammo_9mm( "9mm" );
static const ammotype ammo_battery( "battery" );
static const itype_id itype_44army( "44army" );
static const itype_id itype_9mm( "9mm" );
static const itype_id itype_battery( "battery" );
static const itype_id itype_fish_bait( "fish_bait" );
static const itype_id itype_pebble( "pebble" );
static const itype_id itype_test_100mm_ammo( "test_100mm_ammo" );
static const itype_id itype_test_100mm_ammo_relative( "test_100mm_ammo_relative" );
static const itype_id itype_thread( "thread" );
// Functions:
// - item::ammo_types
//
// TODO:
// - ammo_type
// - common_ammo_default
// - ammo_sort_name
// item::ammo_types returns the ammo types an item may *contain*, which is distinct from the ammo
// types an item may *use*.
//
// Only magazines have ammo_types().
//
// Tools, tool mods, and (all other item types?) have empty ammo_types()
// Return true if the given item has non-empty ammo_types
static bool has_ammo_types( const item &it )
{
return !it.ammo_types().empty();
}
TEST_CASE( "ammo_types", "[ammo][ammo_types]" )
{
// Only a few kinds of item have ammo_types:
// - Items with type=MAGAZINE (including batteries as well as gun magazines)
// - Tools/weapons with magazine_integral (pocket_data has a MAGAZINE rather than MAGAZINE_WELL)
SECTION( "items with MAGAZINE pockets have ammo_types" ) {
// Batteries are magazines
REQUIRE( item( "light_battery_cell" ).is_magazine() );
REQUIRE( item( "battery_car" ).is_magazine() );
// Tool batteries
CHECK( has_ammo_types( item( "light_battery_cell" ) ) );
CHECK( has_ammo_types( item( "medium_battery_cell" ) ) );
CHECK( has_ammo_types( item( "heavy_battery_cell" ) ) );
CHECK( has_ammo_types( item( "light_disposable_cell" ) ) );
CHECK( has_ammo_types( item( "medium_disposable_cell" ) ) );
CHECK( has_ammo_types( item( "heavy_disposable_cell" ) ) );
// Vehicle batteries
CHECK( has_ammo_types( item( "battery_car" ) ) );
CHECK( has_ammo_types( item( "battery_motorbike" ) ) );
CHECK( has_ammo_types( item( "large_storage_battery" ) ) );
SECTION( "battery magazines include 'battery' ammo type" ) {
CHECK( item( "light_battery_cell" ).ammo_types().count( ammo_battery ) == 1 );
CHECK( item( "battery_car" ).ammo_types().count( ammo_battery ) == 1 );
}
// Gun magazines
REQUIRE( item( "belt40mm" ).is_magazine() );
REQUIRE( item( "akmag10" ).is_magazine() );
CHECK( has_ammo_types( item( "belt40mm" ) ) );
CHECK( has_ammo_types( item( "belt308" ) ) );
CHECK( has_ammo_types( item( "akmag10" ) ) );
CHECK( has_ammo_types( item( "akdrum75" ) ) );
CHECK( has_ammo_types( item( "glockmag" ) ) );
SECTION( "gun magazines include ammo type for that magazine" ) {
CHECK( item( "glockmag" ).ammo_types().count( ammo_9mm ) == 1 );
CHECK( item( "akmag10" ).ammo_types().count( ammo_762 ) == 1 );
}
}
SECTION( "GUN items with integral MAGAZINE pockets have ammo_types" ) {
REQUIRE( item( "nailgun" ).magazine_integral() );
REQUIRE( item( "colt_army" ).magazine_integral() );
CHECK( has_ammo_types( item( "nailgun" ) ) );
CHECK( has_ammo_types( item( "colt_army" ) ) );
CHECK( has_ammo_types( item( "hand_crossbow" ) ) );
CHECK( has_ammo_types( item( "compositebow" ) ) );
CHECK( has_ammo_types( item( "sling" ) ) );
CHECK( has_ammo_types( item( "slingshot" ) ) );
}
SECTION( "TOOL items with integral MAGAZINE pockets have ammo_types" ) {
REQUIRE( item( "sewing_kit" ).magazine_integral() );
CHECK( has_ammo_types( item( "needle_bone" ) ) );
CHECK( has_ammo_types( item( "needle_wood" ) ) );
CHECK( has_ammo_types( item( "sewing_kit" ) ) );
CHECK( has_ammo_types( item( "tailors_kit" ) ) );
}
SECTION( "TOOL items with NO pockets have ammo_types" ) {
// NOTE: Fish trap is a TOOL with "ammo", but no "pocket_data", so an implicit MAGAZINE
// pocket is added by Item_factory::check_and_create_magazine_pockets on JSON load.
// This item would be considered needing data migration to an explicit MAGAZINE pocket.
REQUIRE( item( "fish_trap" ).magazine_integral() );
CHECK( has_ammo_types( item( "fish_trap" ) ) );
}
// These items have NO ammo_types:
SECTION( "GUN items with MAGAZINE_WELL pockets also have ammo_types" ) {
REQUIRE_FALSE( item( "m1911" ).magazine_integral() );
CHECK( has_ammo_types( item( "m1911" ) ) );
CHECK( has_ammo_types( item( "usp_9mm" ) ) );
CHECK( has_ammo_types( item( "tommygun" ) ) );
CHECK( has_ammo_types( item( "ak74" ) ) );
CHECK( has_ammo_types( item( "ak47" ) ) );
}
SECTION( "TOOL items with MAGAZINE_WELL pockets do NOT have ammo_types" ) {
REQUIRE( item( "flashlight" ).is_tool() );
CHECK_FALSE( has_ammo_types( item( "flashlight" ) ) );
CHECK_FALSE( has_ammo_types( item( "hotplate" ) ) );
CHECK_FALSE( has_ammo_types( item( "vac_sealer" ) ) );
CHECK_FALSE( has_ammo_types( item( "forge" ) ) );
CHECK_FALSE( has_ammo_types( item( "cordless_drill" ) ) );
}
SECTION( "AMMO items themselves do NOT have ammo_types" ) {
REQUIRE( item( "38_special" ).is_ammo() );
REQUIRE( item( "sinew" ).is_ammo() );
// Ammo for guns
CHECK_FALSE( has_ammo_types( item( "38_special" ) ) );
CHECK_FALSE( has_ammo_types( item( "reloaded_308" ) ) );
CHECK_FALSE( has_ammo_types( item( "bp_9mm" ) ) );
CHECK_FALSE( has_ammo_types( item( "44magnum" ) ) );
// Not for guns but classified as ammo
CHECK_FALSE( has_ammo_types( item( "sinew" ) ) );
CHECK_FALSE( has_ammo_types( item( "nail" ) ) );
CHECK_FALSE( has_ammo_types( item( "rock" ) ) );
CHECK_FALSE( has_ammo_types( item( "solder_wire" ) ) );
}
SECTION( "TOOLMOD items do NOT have ammo_types" ) {
item med_mod( "magazine_battery_medium_mod" );
REQUIRE( med_mod.is_toolmod() );
CHECK_FALSE( has_ammo_types( med_mod ) );
}
}
// The same items with no ammo_types, also have no ammo_default.
TEST_CASE( "ammo_default", "[ammo][ammo_default]" )
{
// TOOLMOD type, and TOOL type items with MAGAZINE_WELL pockets have no ammo_default
SECTION( "items without ammo_default" ) {
item flashlight( "flashlight" );
item med_mod( "magazine_battery_medium_mod" );
CHECK( flashlight.ammo_default().is_null() );
CHECK( med_mod.ammo_default().is_null() );
}
// MAGAZINE type, and TOOL/GUN items with integral MAGAZINE pockets do have ammo_default
SECTION( "items with ammo_default" ) {
// MAGAZINE type items
item battery( "light_battery_cell" );
item glockmag( "glockmag" );
CHECK( battery.ammo_default() == itype_battery );
CHECK( glockmag.ammo_default() == itype_9mm );
// TOOL type items with integral magazines
item sewing_kit( "sewing_kit" );
item needle( "needle_bone" );
item fishtrap( "fish_trap" );
CHECK( sewing_kit.ammo_default() == itype_thread );
CHECK( needle.ammo_default() == itype_thread );
CHECK( fishtrap.ammo_default() == itype_fish_bait );
// GUN type items with integral magazine
item slingshot( "slingshot" );
item colt( "colt_army" );
item lemat( "lemat_revolver" );
CHECK( slingshot.ammo_default() == itype_pebble );
// Revolver ammo is "44paper" but default ammunition type is "44army"
CHECK( colt.ammo_default() == itype_44army );
CHECK( lemat.ammo_default() == itype_44army );
}
}
TEST_CASE( "barrel_test", "[ammo][weapon]" )
{
SECTION( "basic ammo and barrel length test" ) {
item base_gun( "test_glock_super_long" );
CHECK( base_gun.gun_damage( itype_test_100mm_ammo ).total_damage() == 65 );
}
SECTION( "basic ammo and mod length test" ) {
item base_gun( "test_glock_super_long" );
item gun_mod( "barrel_glock_short" );
REQUIRE( base_gun.put_in( gun_mod, pocket_type::MOD ).success() );
REQUIRE( base_gun.barrel_length().value() == 100 );
CHECK( base_gun.gun_damage( itype_test_100mm_ammo ).total_damage() == 60 );
}
SECTION( "inherited ammo and barrel length test" ) {
item base_gun( "test_glock_super_long" );
CHECK( base_gun.gun_damage( itype_test_100mm_ammo_relative ).total_damage() == 66 );
}
}
TEST_CASE( "battery_energy_test", "[ammo][energy][item]" )
{
item test_battery( "medium_battery_cell" );
test_battery.ammo_set( test_battery.ammo_default(), 300 );
SECTION( "Integer drain from battery" ) {
REQUIRE( test_battery.energy_remaining( nullptr ) == 300_kJ );
units::energy consumed = test_battery.energy_consume( 200_kJ, tripoint_zero, nullptr );
CHECK( test_battery.energy_remaining( nullptr ) == 100_kJ );
CHECK( consumed == 200_kJ );
}
SECTION( "Integer over-drain from battery" ) {
REQUIRE( test_battery.energy_remaining( nullptr ) == 300_kJ );
units::energy consumed = test_battery.energy_consume( 400_kJ, tripoint_zero, nullptr );
CHECK( test_battery.energy_remaining( nullptr ) == 0_kJ );
CHECK( consumed == 300_kJ );
}
SECTION( "Non-integer drain from battery" ) {
// Battery charge is in chunks of kj. Non integer kj drain is rounded up.
// 4.5 kJ drain becomes 5 kJ drain
REQUIRE( test_battery.energy_remaining( nullptr ) == 300_kJ );
units::energy consumed = test_battery.energy_consume( 4500_J, tripoint_zero, nullptr );
CHECK( test_battery.energy_remaining( nullptr ) == 295_kJ );
CHECK( consumed == 5_kJ );
}
SECTION( "Non-integer over-drain from battery" ) {
REQUIRE( test_battery.energy_remaining( nullptr ) == 300_kJ );
units::energy consumed = test_battery.energy_consume( 500500_J, tripoint_zero, nullptr );
CHECK( test_battery.energy_remaining( nullptr ) == 0_kJ );
CHECK( consumed == 300_kJ );
}
SECTION( "zero drain from battery" ) {
REQUIRE( test_battery.energy_remaining( nullptr ) == 300_kJ );
units::energy consumed = test_battery.energy_consume( 0_J, tripoint_zero, nullptr );
CHECK( test_battery.energy_remaining( nullptr ) == 300_kJ );
CHECK( consumed == 0_kJ );
}
}