forked from CleverRaven/Cataclysm-DDA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
creature_effect_test.cpp
550 lines (461 loc) · 20.3 KB
/
creature_effect_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
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
#include "avatar.h"
#include "calendar.h"
#include "cata_catch.h"
#include "monster.h"
#include "mtype.h"
#include "type_id.h"
static const efftype_id effect_badpoison( "badpoison" );
static const efftype_id effect_bleed( "bleed" );
static const efftype_id effect_corroding( "corroding" );
static const efftype_id effect_downed( "downed" );
static const efftype_id effect_grabbed( "grabbed" );
static const efftype_id effect_invisibility( "invisibility" );
static const efftype_id effect_paralyzepoison( "paralyzepoison" );
static const efftype_id effect_poison( "poison" );
static const efftype_id effect_venom_dmg( "venom_dmg" );
static const efftype_id effect_venom_player1( "venom_player1" );
static const efftype_id effect_venom_player2( "venom_player2" );
static const efftype_id effect_venom_weaken( "venom_weaken" );
static const flag_id json_flag_INVISIBLE( "INVISIBLE" );
static const mtype_id mon_flaming_eye( "mon_flaming_eye" );
static const mtype_id mon_fungaloid( "mon_fungaloid" );
static const mtype_id mon_graboid( "mon_graboid" );
static const mtype_id mon_hallu_mom( "mon_hallu_mom" );
static const mtype_id mon_razorclaw( "mon_razorclaw" );
static const mtype_id mon_zombie( "mon_zombie" );
static const species_id species_FUNGUS( "FUNGUS" );
static const species_id species_NETHER( "NETHER" );
static const species_id species_WORM( "WORM" );
static const species_id species_ZOMBIE( "ZOMBIE" );
static const trait_id trait_LEG_TENT_BRACE( "LEG_TENT_BRACE" );
static const trait_id trait_SLIMY( "SLIMY" );
// Test effect methods from `Creature` class on both `monster` and `player`
// Functions covered:
// Creature::add_effect
// Creature::remove_effect
// Creature::has_effect
// Creature::has_effect_with_flag
//
// TODO:
// - Creature::resists_effect
// - Creature::process_effects
// - Creature::add_env_effect
// - Creature::get_effect
// - Creature::get_effect_dur
// - Creature::get_effect_int
// Creature::add_effect
//
// TODO:
// - May be "deferred" to not process it immediately
// - For knockdown, if riding/ridden, force dismount
// - Duration is limited to maximum for effect
// - If already have same effect, modify duration and intensity
// - Otherwise, add effect, and check if it is blocked by another effect
// Characters have effects on separate body parts, or no particular part (indicated by `bp_null`)
TEST_CASE( "character add_effect", "[creature][character][effect][add]" )
{
avatar dummy;
dummy.set_body();
const bodypart_id left_arm( "arm_l" );
const bodypart_id right_arm( "arm_r" );
GIVEN( "character is susceptible to effect" ) {
REQUIRE_FALSE( dummy.is_immune_effect( effect_bleed ) );
REQUIRE_FALSE( dummy.is_immune_effect( effect_grabbed ) );
WHEN( "character add_effect is called without a body part" ) {
dummy.add_effect( effect_bleed, 1_minutes );
dummy.add_effect( effect_grabbed, 1_minutes );
THEN( "they have the effect" ) {
CHECK( dummy.has_effect( effect_bleed ) );
CHECK( dummy.has_effect( effect_grabbed ) );
}
}
// Make left arm bleed, and grab right arm
WHEN( "character add_effect is called with a body part" ) {
dummy.add_effect( effect_bleed, 1_minutes, left_arm );
dummy.add_effect( effect_grabbed, 1_minutes, right_arm );
// Left arm bleeding, right arm grabbed
THEN( "they have the effect on that body part" ) {
CHECK( dummy.has_effect( effect_bleed, left_arm.id() ) );
CHECK( dummy.has_effect( effect_grabbed, right_arm.id() ) );
}
// Left arm not grabbed, right arm not bleeding
THEN( "they do not have the effect on another body part" ) {
CHECK_FALSE( dummy.has_effect( effect_grabbed, left_arm.id() ) );
CHECK_FALSE( dummy.has_effect( effect_bleed, right_arm.id() ) );
}
}
}
}
// Monsters may have effects added to them, but they don't have separate body parts.
TEST_CASE( "monster add_effect", "[creature][monster][effect][add]" )
{
monster mummy( mon_hallu_mom );
mummy.clear_effects();
GIVEN( "monster is susceptible to effect" ) {
REQUIRE_FALSE( mummy.is_immune_effect( effect_grabbed ) );
WHEN( "monster add_effect is called" ) {
mummy.add_effect( effect_grabbed, 1_minutes );
THEN( "they have the effect" ) {
CHECK( mummy.has_effect( effect_grabbed ) );
}
}
}
// "Your mother" monster is of 'HALLUCINATION' species, which doesn't have any bleeding type set for it, so it is immune to bleeding.
GIVEN( "monster is immune to effect" ) {
REQUIRE( mummy.is_immune_effect( effect_bleed ) );
THEN( "monster add_effect is called with force = false" ) {
mummy.add_effect( effect_bleed, 1_minutes, false, 1, false );
THEN( "they do not have the effect" ) {
CHECK_FALSE( mummy.has_effect( effect_bleed ) );
}
}
WHEN( "monster add_effect is called with force = true" ) {
mummy.add_effect( effect_bleed, 1_minutes, false, 1, true );
THEN( "they have the effect" ) {
CHECK( mummy.has_effect( effect_bleed ) );
}
}
}
}
// Creature::remove_effect
//
TEST_CASE( "remove_effect", "[creature][effect][remove]" )
{
avatar dummy;
const bodypart_id left_arm( "arm_l" );
const bodypart_id right_arm( "arm_r" );
const bodypart_id left_leg( "leg_l" );
const bodypart_id right_leg( "leg_r" );
dummy.clear_effects();
WHEN( "character does not have effect" ) {
REQUIRE_FALSE( dummy.has_effect( effect_grabbed ) );
THEN( "remove_effect returns false" ) {
CHECK_FALSE( dummy.remove_effect( effect_grabbed ) );
}
}
// Left arm grabbed
WHEN( "character has effect on one body part" ) {
dummy.add_effect( effect_grabbed, 1_minutes, left_arm );
REQUIRE( dummy.has_effect( effect_grabbed, left_arm.id() ) );
THEN( "remove_effect with no body part returns true" ) {
// Release all grabs
CHECK( dummy.remove_effect( effect_grabbed ) );
// All grabs are released
AND_THEN( "effect is removed" ) {
CHECK_FALSE( dummy.has_effect( effect_grabbed ) );
}
}
THEN( "remove_effect with affected body part returns true" ) {
// Release grab on left arm
CHECK( dummy.remove_effect( effect_grabbed, left_arm ) );
// Left arm is released
AND_THEN( "effect is removed from that body part" ) {
CHECK_FALSE( dummy.has_effect( effect_grabbed, left_arm.id() ) );
}
}
THEN( "remove_effect with an unaffected body part returns false" ) {
// Release (nonexistent) grab on right arm
CHECK_FALSE( dummy.remove_effect( effect_grabbed, right_arm ) );
// Left arm is still grabbed
AND_THEN( "effect still applies to original body part" ) {
CHECK( dummy.has_effect( effect_grabbed, left_arm.id() ) );
}
}
}
// Both arms grabbed
WHEN( "character has effect on two body parts" ) {
dummy.add_effect( effect_grabbed, 1_minutes, left_arm );
dummy.add_effect( effect_grabbed, 1_minutes, right_arm );
REQUIRE( dummy.has_effect( effect_grabbed, left_arm.id() ) );
REQUIRE( dummy.has_effect( effect_grabbed, right_arm.id() ) );
// Release all grabs
THEN( "remove_effect with no body part returns true" ) {
CHECK( dummy.remove_effect( effect_grabbed ) );
// Both arms are released
AND_THEN( "effect is removed from all body parts" ) {
CHECK_FALSE( dummy.has_effect( effect_grabbed, left_arm.id() ) );
CHECK_FALSE( dummy.has_effect( effect_grabbed, right_arm.id() ) );
}
}
// Only release left arm
THEN( "remove_effect with an affected body part returns true" ) {
CHECK( dummy.remove_effect( effect_grabbed, left_arm ) );
// Left arm is released
AND_THEN( "effect is removed from that body part" ) {
CHECK_FALSE( dummy.has_effect( effect_grabbed, left_arm.id() ) );
}
// Right arm still grabbed
AND_THEN( "effect still applies to other body part" ) {
CHECK( dummy.has_effect( effect_grabbed, right_arm.id() ) );
}
}
// Release (nonexistent) grabs on legs
THEN( "remove_effect with an unaffected body part returns false" ) {
CHECK_FALSE( dummy.remove_effect( effect_grabbed, left_leg ) );
CHECK_FALSE( dummy.remove_effect( effect_grabbed, right_leg ) );
// Both arms still grabbed
AND_THEN( "effect still applies to original body parts" ) {
CHECK( dummy.has_effect( effect_grabbed, left_arm.id() ) );
CHECK( dummy.has_effect( effect_grabbed, right_arm.id() ) );
}
}
}
}
// Creature::has_effect
//
TEST_CASE( "has_effect", "[creature][effect][has]" )
{
// For monster, has_effect is not body-part-specific (uses bp_null)
SECTION( "monster has_effect" ) {
monster mummy( mon_hallu_mom );
mummy.clear_effects();
// Not downed or grabbed
WHEN( "monster does not have effect" ) {
THEN( "has_effect is false" ) {
CHECK_FALSE( mummy.has_effect( effect_downed ) );
CHECK_FALSE( mummy.has_effect( effect_grabbed ) );
}
}
// Downed but not grabbed
WHEN( "monster has one effect" ) {
mummy.add_effect( effect_downed, 1_minutes );
THEN( "has_effect is true for that effect" ) {
CHECK( mummy.has_effect( effect_downed ) );
}
THEN( "has_effect is false for other effect" ) {
CHECK_FALSE( mummy.has_effect( effect_grabbed ) );
}
}
// Both downed and grabbed
WHEN( "monster has two effects" ) {
mummy.add_effect( effect_downed, 1_minutes );
mummy.add_effect( effect_grabbed, 1_minutes );
THEN( "has_effect is true for both effects" ) {
CHECK( mummy.has_effect( effect_downed ) );
CHECK( mummy.has_effect( effect_grabbed ) );
}
}
}
// For character, has_effect may apply to individual body parts
SECTION( "character has_effect" ) {
avatar dummy;
const bodypart_id left_arm( "arm_l" );
const bodypart_id right_arm( "arm_r" );
dummy.clear_effects();
// Not downed or grabbed
WHEN( "character does not have effect" ) {
THEN( "has_effect is false" ) {
CHECK_FALSE( dummy.has_effect( effect_downed ) );
CHECK_FALSE( dummy.has_effect( effect_grabbed ) );
}
}
// Left arm grabbed
WHEN( "character has effect on one body part" ) {
dummy.add_effect( effect_grabbed, 1_minutes, left_arm );
THEN( "has_effect is true for affected body part" ) {
CHECK( dummy.has_effect( effect_grabbed, left_arm.id() ) );
}
THEN( "has_effect is false for an unaffected body part" ) {
CHECK_FALSE( dummy.has_effect( effect_grabbed, right_arm.id() ) );
}
THEN( "has_effect is true when body part is not specified" ) {
CHECK( dummy.has_effect( effect_grabbed ) );
CHECK( dummy.has_effect( effect_grabbed ) );
}
}
// Downed
WHEN( "character has effect on the whole body" ) {
dummy.add_effect( effect_downed, 1_minutes );
THEN( "has_effect is false for any body part" ) {
CHECK_FALSE( dummy.has_effect( effect_downed, left_arm.id() ) );
CHECK_FALSE( dummy.has_effect( effect_downed, right_arm.id() ) );
}
THEN( "has_effect is true when body part is not specified" ) {
CHECK( dummy.has_effect( effect_downed ) );
CHECK( dummy.has_effect( effect_downed ) );
}
}
}
}
// Creature::has_effect_with_flag
//
TEST_CASE( "has_effect_with_flag", "[creature][effect][has][flag]" )
{
monster mummy( mon_hallu_mom );
mummy.clear_effects();
WHEN( "monster does not have any effects" ) {
THEN( "has_effect_with_flag is false" ) {
CHECK_FALSE( mummy.has_effect_with_flag( json_flag_INVISIBLE ) );
}
}
WHEN( "monster has only effects without flag" ) {
mummy.add_effect( effect_downed, 1_minutes );
THEN( "has_effect_with_flag is false" ) {
CHECK_FALSE( mummy.has_effect_with_flag( json_flag_INVISIBLE ) );
}
}
WHEN( "monster has an effect with the flag" ) {
mummy.add_effect( effect_invisibility, 1_minutes );
THEN( "has_effect_with_flag is true" ) {
CHECK( mummy.has_effect_with_flag( json_flag_INVISIBLE ) );
}
}
}
// monster::is_immune_effect
//
TEST_CASE( "monster is_immune_effect", "[creature][monster][effect][immune]" )
{
// TODO: Monster may be immune to:
// - onfire (if is_immune_damage DT_HEAT, made_of LIQUID, has_flag MF_FIREY)
// - stunned (if has_flag MF_STUN_IMMUNE)
WHEN( "monster is made of flesh, is not zombified, has blood and has no legs" ) {
// graboid - fleshy, living snake of a species with bleed data
monster graboid( mon_graboid );
graboid.clear_effects();
REQUIRE( graboid.made_of_any( Creature::cmat_flesh ) );
REQUIRE( graboid.type->bodytype == "snake" );
REQUIRE( graboid.type->in_species( species_WORM ) );
THEN( "they can bleed" ) {
CHECK_FALSE( graboid.is_immune_effect( effect_bleed ) );
}
THEN( "they can be poisoned by all poisons" ) {
CHECK_FALSE( graboid.is_immune_effect( effect_poison ) );
CHECK_FALSE( graboid.is_immune_effect( effect_badpoison ) );
CHECK_FALSE( graboid.is_immune_effect( effect_paralyzepoison ) );
CHECK_FALSE( graboid.is_immune_effect( effect_venom_dmg ) );
CHECK_FALSE( graboid.is_immune_effect( effect_venom_player1 ) );
CHECK_FALSE( graboid.is_immune_effect( effect_venom_player2 ) );
CHECK_FALSE( graboid.is_immune_effect( effect_venom_weaken ) );
}
THEN( "they can't be downed" ) {
CHECK( graboid.is_immune_effect( effect_downed ) );
}
}
WHEN( "monster is a zombie, made of flesh, has blood and has legs" ) {
// Zombie - fleshy humanoid zombie
monster zed( mon_zombie );
zed.clear_effects();
REQUIRE( zed.made_of_any( Creature::cmat_flesh ) );
REQUIRE( zed.type->in_species( species_ZOMBIE ) );
REQUIRE( zed.type->bodytype == "human" );
THEN( "they can bleed" ) {
CHECK_FALSE( zed.is_immune_effect( effect_bleed ) );
}
THEN( "they can be poisoned by stronger poisons" ) {
CHECK_FALSE( zed.is_immune_effect( effect_venom_dmg ) );
CHECK_FALSE( zed.is_immune_effect( effect_venom_player1 ) );
CHECK_FALSE( zed.is_immune_effect( effect_venom_player2 ) );
}
THEN( "they can't be poisoned by weaker poisons" ) {
CHECK( zed.is_immune_effect( effect_poison ) );
CHECK( zed.is_immune_effect( effect_badpoison ) );
CHECK( zed.is_immune_effect( effect_paralyzepoison ) );
CHECK( zed.is_immune_effect( effect_venom_weaken ) );
}
THEN( "they can be downed" ) {
CHECK_FALSE( zed.is_immune_effect( effect_downed ) );
}
}
WHEN( "monster is made of nether flesh and is flying" ) {
// Flaming eye, flesh, Nether species and flying
monster feye( mon_flaming_eye );
feye.clear_effects();
REQUIRE( feye.made_of_any( Creature::cmat_flesh ) );
REQUIRE( feye.has_flag( MF_FLIES ) );
REQUIRE( feye.type->in_species( species_NETHER ) );
THEN( "they can bleed" ) {
CHECK_FALSE( feye.is_immune_effect( effect_bleed ) );
}
THEN( "they can't be poisoned" ) {
CHECK( feye.is_immune_effect( effect_poison ) );
CHECK( feye.is_immune_effect( effect_badpoison ) );
CHECK( feye.is_immune_effect( effect_paralyzepoison ) );
CHECK( feye.is_immune_effect( effect_venom_dmg ) );
CHECK( feye.is_immune_effect( effect_venom_player1 ) );
CHECK( feye.is_immune_effect( effect_venom_player2 ) );
CHECK( feye.is_immune_effect( effect_venom_weaken ) );
}
THEN( "they can't be downed" ) {
CHECK( feye.is_immune_effect( effect_downed ) );
}
}
WHEN( "monster is not made of flesh or iflesh" ) {
// Fungaloid - veggy, has no blood or bodytype
monster fungaloid( mon_fungaloid );
fungaloid.clear_effects();
REQUIRE_FALSE( fungaloid.made_of_any( Creature::cmat_flesh ) );
REQUIRE( fungaloid.type->in_species( species_FUNGUS ) );
REQUIRE( fungaloid.type->bleed_rate == 0 );
THEN( "their zero bleed rate makes them immune to bleed" ) {
CHECK( fungaloid.is_immune_effect( effect_bleed ) );
}
THEN( "they can't be poisoned" ) {
CHECK( fungaloid.is_immune_effect( effect_poison ) );
CHECK( fungaloid.is_immune_effect( effect_badpoison ) );
CHECK( fungaloid.is_immune_effect( effect_paralyzepoison ) );
CHECK( fungaloid.is_immune_effect( effect_venom_dmg ) );
CHECK( fungaloid.is_immune_effect( effect_venom_player1 ) );
CHECK( fungaloid.is_immune_effect( effect_venom_player2 ) );
CHECK( fungaloid.is_immune_effect( effect_venom_weaken ) );
}
THEN( "they can be downed" ) {
CHECK_FALSE( fungaloid.is_immune_effect( effect_downed ) );
}
}
WHEN( "monster species doesn't have bleeding type set, but it has flag describing its bleeding type" ) {
// Razorclaw - has `MUTANT` species which doesn't have any bleeding type set, but has arthropod blood
monster razorclaw( mon_razorclaw );
razorclaw.clear_effects();
REQUIRE( razorclaw.has_flag( MF_ARTHROPOD_BLOOD ) );
THEN( "they can bleed" ) {
CHECK_FALSE( razorclaw.is_immune_effect( effect_bleed ) );
}
}
}
// Character::is_immune_effect
//
TEST_CASE( "character is_immune_effect", "[creature][character][effect][immune]" )
{
avatar dummy;
dummy.set_body();
dummy.clear_mutations();
// TODO: Character may be immune to:
// - onfire (if immune_damage DT_HEAT)
// - deaf (if wearing something with DEAF/PARTIALDEAF, bionic ears, rm13 armor)
WHEN( "character has Slimy mutation" ) {
dummy.toggle_trait( trait_SLIMY );
REQUIRE( dummy.has_trait( trait_SLIMY ) );
THEN( "they are immune to the corroding effect" ) {
CHECK( dummy.is_immune_effect( effect_corroding ) );
}
AND_WHEN( "they lose their Slimy mutation" ) {
dummy.toggle_trait( trait_SLIMY );
REQUIRE_FALSE( dummy.has_trait( trait_SLIMY ) );
THEN( "they are no longer immune to the corroding effect" ) {
CHECK_FALSE( dummy.is_immune_effect( effect_corroding ) );
}
}
}
WHEN( "character has Tentacle bracing mutation" ) {
dummy.toggle_trait( trait_LEG_TENT_BRACE );
REQUIRE( dummy.has_trait( trait_LEG_TENT_BRACE ) );
THEN( "they are immune to the downed effect" ) {
CHECK( dummy.is_immune_effect( effect_downed ) );
}
AND_WHEN( "they lose their Tentacle bracing mutation" ) {
dummy.toggle_trait( trait_LEG_TENT_BRACE );
REQUIRE_FALSE( dummy.has_trait( trait_LEG_TENT_BRACE ) );
THEN( "they are no longer immune to the downed effect" ) {
CHECK_FALSE( dummy.is_immune_effect( effect_downed ) );
}
}
}
}
// Creature::resists_effect
//
TEST_CASE( "creature effect reistance", "[creature][effect][resist]" )
{
// TODO: Creature resists effect if:
// - has effect from eff.get_resist_effects
// - has trait from eff.get_resist_traits
}