Skip to content

Commit 6e67a15

Browse files
authored
Gives abandoned crates UI (#841)
* learning is hard (also ports an abandoned crate refactor) * I wish all map_icons a very die * why didn't it do this one too
1 parent c0334f8 commit 6e67a15

6 files changed

Lines changed: 518 additions & 261 deletions

File tree

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
//Originally coded by ISaidNo, later modified by Kelenius. Ported from Baystation12.
2+
3+
/obj/structure/closet/crate/secure/loot
4+
name = "abandoned crate"
5+
desc = "What could be inside?"
6+
icon_state = "securecrate"
7+
base_icon_state = "securecrate"
8+
integrity_failure = 0 //no breaking open the crate
9+
var/code = null
10+
/// Associated list of previous attempts w/ bulls & cows
11+
var/list/previous_attempts = list()
12+
var/attempts = 10
13+
var/code_length = 4
14+
var/qdel_on_open = FALSE
15+
var/spawned_loot = FALSE
16+
tamperproof = 90
17+
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND
18+
19+
divable = FALSE // Stop people from "diving into" the crate accidentally, and then detonating it.
20+
21+
/// Possible loot from the crate, selected according to a weighted list: [typepath] = probability %
22+
var/static/list/possible_loot = list(
23+
list( // Toys & Entertainment
24+
/obj/item/melee/skateboard/pro = 5,
25+
/obj/effect/spawner/abandoned_crate/snappop = 5,
26+
/obj/effect/spawner/abandoned_crate/posters = 5,
27+
/obj/item/toy/balloon/corgi = 2,
28+
/obj/effect/spawner/abandoned_crate/mecha = 2,
29+
/obj/item/toy/balloon/syndicate = 2,
30+
/obj/item/toy/plush/snakeplushie = 2,
31+
/obj/item/bikehorn/airhorn = 2,
32+
/obj/item/toy/plush/beeplushie = 2,
33+
/obj/item/toy/plush/lizard_plushie = 2,
34+
/obj/item/toy/plush/nukeplushie = 1,
35+
/obj/effect/spawner/abandoned_crate/bwoink = 1,
36+
/obj/effect/spawner/abandoned_crate/pay_day = 1,
37+
/obj/item/melee/skateboard/hoverboard = 1,
38+
/obj/item/implanter/sad_trombone = 1,
39+
) = 34, // sum of weights inside list
40+
41+
list( // Weapons & Combat
42+
/obj/item/melee/baton = 2,
43+
/obj/item/clothing/gloves/boxing/evil = 1,
44+
/obj/item/melee/energy/sword/bananium = 1,
45+
/obj/item/katana = 1,
46+
) = 5,
47+
48+
list( // Clothing
49+
/obj/item/storage/box/syndie_kit/chameleon/broken = 5,
50+
/obj/item/clothing/shoes/kindle_kicks = 2,
51+
/obj/effect/spawner/abandoned_crate/kitty = 2,
52+
/obj/effect/spawner/abandoned_crate/space_suit = 2,
53+
/obj/effect/spawner/abandoned_crate/fursuit = 2,
54+
) = 13,
55+
56+
list( // Tools & Equipment
57+
/obj/item/modular_computer/pda/clear = 5,
58+
/obj/item/defibrillator/compact = 2,
59+
) = 7,
60+
61+
list( // Materials
62+
/obj/effect/spawner/abandoned_crate/diamonds = 5,
63+
/obj/effect/spawner/abandoned_crate/bluespace_crystal = 2,
64+
/obj/effect/spawner/abandoned_crate/bananium = 2,
65+
) = 9,
66+
67+
list( // Seed & Plants
68+
/obj/item/seeds/firelemon = 5,
69+
/obj/effect/spawner/abandoned_crate/weed = 1,
70+
) = 6,
71+
72+
list( // Consumables
73+
/obj/effect/spawner/abandoned_crate/booze = 5,
74+
/obj/effect/spawner/abandoned_crate/boda = 5,
75+
/obj/item/reagent_containers/cup/glass/bottle/lizardwine = 1,
76+
) = 11,
77+
78+
list( // Mobs
79+
/mob/living/simple_animal/bot/secbot/honkbot = 5,
80+
/mob/living/simple_animal/pet/gondola = 2,
81+
/obj/effect/spawner/abandoned_crate/bloodroaches = 1,
82+
) = 8,
83+
84+
list( // Medical & Science
85+
/obj/item/dnainjector/xraymut = 1,
86+
/obj/item/dnainjector/wackymut = 1,
87+
) = 2,
88+
89+
list( // Dangerous
90+
/obj/effect/spawner/abandoned_crate/gibtonite = 2,
91+
/obj/effect/spawner/abandoned_crate/mimic = 1,
92+
/obj/effect/spawner/abandoned_crate/bees = 1,
93+
) = 4,
94+
95+
list( // Misc
96+
/obj/effect/spawner/random/structure/closet_empty/crate = 1, //crate with crate
97+
) = 1,
98+
)
99+
100+
/obj/structure/closet/crate/secure/loot/Initialize(mapload)
101+
. = ..()
102+
code = generate_code(code_length)
103+
104+
/// Generates a random code of specified length with no repeating digits
105+
/obj/structure/closet/crate/secure/loot/proc/generate_code(length)
106+
var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
107+
var/list/code_digits = list()
108+
109+
for(var/i in 1 to length)
110+
if(!digits.len)
111+
break
112+
var/digit = pick(digits)
113+
code_digits += digit
114+
digits -= digit //there are never matching digits in the answer
115+
116+
return code_digits.Join("")
117+
118+
//ATTACK HAND IGNORING PARENT RETURN VALUE
119+
/obj/structure/closet/crate/secure/loot/attack_hand(mob/user, list/modifiers)
120+
if(!locked)
121+
return ..()
122+
if(!user.can_perform_action(src))
123+
return
124+
125+
var/input = tgui_input_text(user, title = "Deca-code lock", message = "Enter [code_length] digits. All digits must be unique.", max_length = code_length)
126+
127+
if(input == code)
128+
if(!spawned_loot)
129+
spawn_loot()
130+
tamperproof = 0 // set explosion chance to zero, so we dont accidently hit it with a multitool and instantly die
131+
SStgui.close_user_uis(user, src)
132+
togglelock(user)
133+
return
134+
135+
if(!validate_input(input))
136+
to_chat(user, span_notice("You leave the crate alone."))
137+
return
138+
139+
to_chat(user, span_warning("A red light flashes."))
140+
previous_attempts += list(bulls_and_cows(input))
141+
attempts--
142+
143+
if(attempts <= 0)
144+
boom(user)
145+
146+
/// Checks if user input is a valid code attempt
147+
/obj/structure/closet/crate/secure/loot/proc/validate_input(input)
148+
if(!input || code_length != length(input))
149+
return FALSE
150+
151+
var/list/used_digits = list()
152+
for(var/i = 1 to length(input))
153+
var/char = input[i]
154+
if(!(char >= "0" && char <= "9")) //if a non-digit is found, reject the input
155+
return FALSE
156+
if(char in used_digits) //if a digit is repeated, reject the input
157+
return FALSE
158+
used_digits += char
159+
160+
return TRUE
161+
162+
/obj/structure/closet/crate/secure/loot/click_alt(mob/living/user)
163+
attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom.
164+
return CLICK_ACTION_SUCCESS
165+
166+
/obj/structure/closet/crate/secure/loot/ui_interact(mob/user, datum/tgui/ui)
167+
. = ..()
168+
169+
// Attempt to update tgui ui, open and update if needed.
170+
ui = SStgui.try_update_ui(user, src, ui)
171+
if(!ui)
172+
ui = new(user, src, "AbandonedCrate", name)
173+
ui.open()
174+
175+
/obj/structure/closet/crate/secure/loot/ui_data(mob/user)
176+
var/list/data = list()
177+
178+
data["previous_attempts"] = previous_attempts
179+
data["attempts_left"] = attempts
180+
181+
return data
182+
183+
/obj/structure/closet/crate/secure/loot/multitool_act(mob/living/user, obj/item/tool)
184+
if(!locked)
185+
return
186+
if(Adjacent(user))
187+
ui_interact(user)
188+
189+
return ITEM_INTERACT_SUCCESS
190+
191+
/// Implements bulls and cows algorithm to compare guess against actual code
192+
/obj/structure/closet/crate/secure/loot/proc/bulls_and_cows(guess)
193+
var/bulls = 0
194+
var/cows = 0
195+
196+
for(var/i = 1 to code_length)
197+
var/guess_char = guess[i]
198+
var/code_char = code[i]
199+
200+
if(guess_char == code_char)
201+
bulls++
202+
else if(findtext(code, guess_char))
203+
cows++
204+
205+
return list("attempt" = guess, "bulls" = bulls, "cows" = cows)
206+
207+
/obj/structure/closet/crate/secure/loot/emag_act(mob/user, obj/item/card/emag/emag_card)
208+
. = ..()
209+
210+
if(locked)
211+
boom(user) // no feedback since it just explodes, thats its own feedback
212+
return TRUE
213+
return
214+
215+
/obj/structure/closet/crate/secure/loot/togglelock(mob/user, silent = FALSE)
216+
if(!locked)
217+
. = ..() //Run the normal code.
218+
if(locked) //Double check if the crate actually locked itself when the normal code ran.
219+
//reset the anti-tampering, number of attempts and last attempt when the lock is re-enabled.
220+
tamperproof = initial(tamperproof)
221+
attempts = initial(attempts)
222+
previous_attempts = list()
223+
return
224+
if(tamperproof)
225+
return
226+
return ..()
227+
228+
/obj/structure/closet/crate/secure/loot/atom_deconstruct(disassembled = TRUE)
229+
if(locked)
230+
boom()
231+
return
232+
return ..()
233+
234+
/obj/structure/closet/crate/secure/loot/after_open(mob/living/user, force)
235+
. = ..()
236+
if(qdel_on_open)
237+
qdel(src)
238+
239+
/obj/structure/closet/crate/secure/loot/proc/spawn_loot()
240+
var/loot = pick_weight_recursive(possible_loot)
241+
new loot(src)
242+
spawned_loot = TRUE

0 commit comments

Comments
 (0)