-
Notifications
You must be signed in to change notification settings - Fork 220
/
equipment_tests.dm
206 lines (171 loc) · 9.16 KB
/
equipment_tests.dm
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
/datum/unit_test/vision_glasses
name = "EQUIPMENT: Vision Template"
template = /datum/unit_test/vision_glasses
var/mob/living/human/H = null
var/expectation = SEE_INVISIBLE_NOLIGHTING
var/glasses_type = null
async = 1
/datum/unit_test/vision_glasses/start_test()
var/list/test = create_test_mob_with_mind(get_safe_turf(), /mob/living/human)
if(isnull(test))
fail("Check Runtimed in Mob creation")
if(test["result"] == FAILURE)
fail(test["msg"])
async = 0
return 0
H = locate(test["mobref"])
H.equip_to_slot(new glasses_type(H), slot_glasses_str)
return 1
/datum/unit_test/vision_glasses/check_result()
if(isnull(H) || H.life_tick < 2)
return 0
if(isnull(H.get_equipped_item(slot_glasses_str)))
fail("Mob doesn't have glasses on")
H.handle_vision() // Because Life has a client check that bypasses updating vision
if(H.see_invisible == expectation)
pass("Mob See invisible is [H.see_invisible]")
else
fail("Mob See invisible is [H.see_invisible] / expected [expectation]")
return 1
/datum/unit_test/vision_glasses/NVG
name = "EQUIPMENT: NVG see_invis"
glasses_type = /obj/item/clothing/glasses/night
/datum/unit_test/vision_glasses/mesons
name = "EQUIPMENT: Mesons see_invis"
glasses_type = /obj/item/clothing/glasses/meson
/datum/unit_test/vision_glasses/plain
name = "EQUIPMENT: Plain glasses. see_invis"
glasses_type = /obj/item/clothing/glasses/prescription
expectation = SEE_INVISIBLE_LIVING
// ============================================================================
/datum/unit_test/storage_capacity_test
name = "EQUIPMENT: Storage items should be able to actually hold their initial contents"
/datum/unit_test/storage_capacity_test/start_test()
var/bad_tests = 0
for(var/storage_type in typesof(/obj))
var/obj/thing = storage_type
if(TYPE_IS_ABSTRACT(thing) || !ispath(initial(thing.storage), /datum/storage))
continue
thing = new thing //should be fine to put it in nullspace...
var/bad_msg = "[ascii_red]--------------- [thing.name] \[[thing.type] | [thing.storage]\]"
bad_tests += test_storage_capacity(thing.storage, bad_msg)
if(bad_tests)
fail("\[[bad_tests]\] Some storage item types were not able to hold their default initial contents.")
else
pass("All storage item types were able to hold their default initial contents.")
return 1
/proc/test_storage_capacity(datum/storage/storage, bad_msg)
var/bad_tests = 0
var/list/contents = storage?.get_contents()
var/atom/movable/thing = storage?.holder
if(!istype(thing))
log_unit_test("[bad_msg] Null or invalid storage holder [istype(thing, /datum) ? thing.type : (thing || "NULL")]. [ascii_reset]")
else if(isnull(storage))
log_unit_test("[bad_msg] Null storage extension. [ascii_reset]")
bad_tests++
else if(!isnull(storage.storage_slots) && length(contents) > storage.storage_slots)
log_unit_test("[bad_msg] Contains more items than it has slots for ([length(contents)] / [storage.storage_slots]). [ascii_reset]")
bad_tests++
if(thing && storage)
var/total_storage_space = 0
for(var/obj/item/I in contents)
if(I.w_class > storage.max_w_class)
log_unit_test("[bad_msg] Contains an item \[[I.type]\] that is too big to be held ([I.w_class] / [storage.max_w_class]). [ascii_reset]")
bad_tests++
if(I.storage && I.w_class >= thing.get_object_size())
log_unit_test("[bad_msg] Contains a storage item \[[I.type]\] the same size or larger than its container ([I.w_class] / [thing.get_object_size()]). [ascii_reset]")
bad_tests++
total_storage_space += I.get_storage_cost()
if(total_storage_space > storage.max_storage_space)
log_unit_test("[bad_msg] Contains more items than it has storage space for ([total_storage_space] / [storage.max_storage_space]). [ascii_reset]")
bad_tests++
return bad_tests
// ============================================================================
/datum/unit_test/equipment_slot_test
name = "EQUIPMENT: Equipment should equip and unequip to slots in the expected manner"
var/list/slot_to_valid_type
var/slot_invalid_type = /obj/item/toy/balloon
var/list/created_atoms = list()
/datum/unit_test/equipment_slot_test/New()
..()
/// Ordering is important here, dependencies like ID should be after uniform, etc.
slot_to_valid_type = list(
"[slot_w_uniform_str]" = /obj/item/clothing/costume/clown,
"[slot_back_str]" = /obj/item/backpack/clown,
"[slot_wear_id_str]" = /obj/item/card/id,
"[slot_glasses_str]" = /obj/item/clothing/glasses/meson,
"[slot_wear_mask_str]" = /obj/item/clothing/mask/gas/sexyclown,
"[slot_head_str]" = /obj/item/clothing/head/hairflower,
"[slot_shoes_str]" = /obj/item/clothing/shoes/magboots,
"[slot_gloves_str]" = /obj/item/clothing/gloves/rainbow,
"[slot_l_ear_str]" = /obj/item/clothing/head/hairflower,
"[slot_r_ear_str]" = /obj/item/clothing/head/hairflower,
"[slot_belt_str]" = /obj/item/ore, // note: this should be an item without ITEM_FLAG_IS_BELT
"[slot_wear_suit_str]" = /obj/item/clothing/suit/chickensuit
)
/datum/unit_test/equipment_slot_test/proc/check_slot_equip_successful(mob/living/human/subject, obj/item/item, which_slot, list/failure_list)
created_atoms |= item
subject.equip_to_slot_if_possible(item, which_slot)
if(!subject.isEquipped(item))
failure_list += "[item] was equipped to [which_slot] but failed isEquipped."
else if(subject.get_equipped_slot_for_item(item) != which_slot)
var/equipped_location = subject.get_equipped_slot_for_item(item)
failure_list += "[item] was expected to be equipped to [which_slot] but get_equipped_slot_for_item returned [isnull(equipped_location) ? "NULL" : equipped_location]."
/datum/unit_test/equipment_slot_test/proc/check_slot_unequip_successful(mob/living/human/subject, obj/item/item, which_slot, list/failure_list)
created_atoms |= item
subject.try_unequip(item)
if(subject.isEquipped(item))
failure_list += "[item] remained equipped to [subject.get_equipped_slot_for_item(item)] after unEquip was called."
/datum/unit_test/equipment_slot_test/proc/check_slot_equip_failure(mob/living/human/subject, obj/item/item, which_slot, list/failure_list)
created_atoms |= item
subject.equip_to_slot_if_possible(item, which_slot)
if(subject.isEquipped(item))
var/equipped_location = subject.get_equipped_slot_for_item(item)
failure_list += "isEquipped([item]) returned true but should have failed (was equipped to [isnull(equipped_location) ? "NULL" : equipped_location])."
else if(subject.get_equipped_slot_for_item(item))
var/equipped_location = subject.get_equipped_slot_for_item(item)
failure_list += "[item] was equipped to [equipped_location] despite failing isEquipped (should not be equipped)."
/datum/unit_test/equipment_slot_test/start_test()
var/mob/living/human/subject = new(get_safe_turf(), SPECIES_HUMAN) // force human so default map species doesn't mess with anything
created_atoms |= subject
var/list/failures = list()
// First we try to dress them up.
for(var/slot in slot_to_valid_type)
var/slot_type = slot_to_valid_type[slot]
check_slot_equip_successful(subject, new slot_type, slot, failures)
// Now we try to unequip.
for(var/i = length(slot_to_valid_type) to 1 step -1)
var/slot = slot_to_valid_type[i]
var/item = subject.get_equipped_item(slot)
if(item) // If something failed to equip last step, it might be missing now.
check_slot_unequip_successful(subject, item, slot, failures)
// Try to equip an unequippable item.
subject.dump_contents()
for(var/slot in slot_to_valid_type)
check_slot_equip_failure(subject, new slot_invalid_type, slot, failures)
// Check ID, belt and pockets depending on uniform.
var/belt_type = slot_to_valid_type[slot_belt_str]
var/id_type = slot_to_valid_type[slot_wear_id_str]
var/uniform_type = slot_to_valid_type[slot_w_uniform_str]
check_slot_equip_failure(subject, new belt_type, slot_belt_str, failures)
check_slot_equip_failure(subject, new id_type, slot_wear_id_str, failures)
check_slot_equip_failure(subject, new /obj/item/screwdriver, slot_l_store_str, failures)
check_slot_equip_failure(subject, new /obj/item/coin, slot_r_store_str, failures)
check_slot_equip_successful(subject, new uniform_type, slot_w_uniform_str, failures)
check_slot_equip_successful(subject, new belt_type, slot_belt_str, failures)
check_slot_equip_successful(subject, new id_type, slot_wear_id_str, failures)
check_slot_equip_successful(subject, new /obj/item/screwdriver, slot_l_store_str, failures)
check_slot_equip_successful(subject, new /obj/item/coin, slot_r_store_str, failures)
// Check suit storage depending on suit.
var/obj/item/clothing/suit/suit = new /obj/item/clothing/suit/space/void/mining
var/suit_item_type = suit.allowed[1]
check_slot_equip_failure(subject, new suit_item_type, slot_s_store_str, failures)
check_slot_equip_successful(subject, suit, slot_wear_suit_str, failures)
check_slot_equip_successful(subject, new suit_item_type, slot_s_store_str, failures)
// Report results.
if(length(failures))
fail("[length(failures)] problems with equipment slots:\n\t- [jointext(failures,"\n\t- ")]")
else
pass("No problems with equipment slots detected.")
QDEL_NULL_LIST(created_atoms)
return TRUE