mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-14 03:12:30 +00:00
Extends and reworks how various extended information text (desc_info, desc_build, desc_upgrades) are handled to make object interactions and mechanics A.) much more clearly documented in-game and B.) much easier to support from the back-end. Almost certainly a candidate for test merge. Assembly/Disassembly instructions are noticeably sporadic, largely due to our current lack of a unified framework. That's a future thing I'd like to attack so that it can be handled programmatically, but for now I only targeted the biggest culprits as I came across them. --------- Signed-off-by: Batrachophreno <Batrochophreno@gmail.com>
252 lines
7.4 KiB
Plaintext
252 lines
7.4 KiB
Plaintext
/obj/structure/weapons_rack
|
|
name = "weapon rack"
|
|
desc = "A rack designed to store weapons."
|
|
icon = 'icons/obj/machinery/weapons_rack.dmi'
|
|
icon_state = "rack_base"
|
|
anchored = TRUE
|
|
density = TRUE
|
|
|
|
///The maximum number of weapons that can be stored in the rack
|
|
VAR_PRIVATE/max_weapons_loaded = 4
|
|
|
|
///Boolean, if the rack is locked (no weapon can be added or removed)
|
|
VAR_PRIVATE/locked = FALSE
|
|
|
|
///Boolean, if the rack is forced open (eg. it was cut open, melted open or whatever)
|
|
VAR_PRIVATE/forced_open = FALSE
|
|
|
|
VAR_PRIVATE/obj/effect/visual_holder
|
|
|
|
/obj/structure/weapons_rack/feedback_hints(mob/user, distance, is_adjacent)
|
|
. += ..()
|
|
|
|
if(locate(/obj/item/gun) in src)
|
|
. += "<br/>It contains:<br/>"
|
|
for(var/obj/item/gun/G in src.contents)
|
|
. += "\A [G.name]"
|
|
|
|
if(locked)
|
|
. += SPAN_WARNING("It is locked.")
|
|
|
|
/obj/structure/weapons_rack/Initialize(mapload)
|
|
..()
|
|
visual_holder = new()
|
|
visual_holder.vis_flags |= VIS_INHERIT_ID
|
|
visual_holder.appearance_flags |= KEEP_TOGETHER|RESET_TRANSFORM
|
|
|
|
//This is used to hide any stray pixels that the rifles could have, eg. for overboarding the rack sprite
|
|
var/mask_for_rifles_filter = filter(type="alpha", icon = icon(src.icon, "rack_mask"))
|
|
visual_holder.filters += mask_for_rifles_filter
|
|
|
|
src.vis_contents += visual_holder
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/structure/weapons_rack/LateInitialize()
|
|
. = ..()
|
|
|
|
for(var/obj/item/gun in get_turf(src))
|
|
gun.forceMove(src)
|
|
|
|
//This protects us from mapper mistakes
|
|
//don't worry, they will find a way to get this to bug out, just not this particular one
|
|
if(length(src.contents) > max_weapons_loaded)
|
|
stack_trace("Weapon rack at [src.x],[src.y],[src.z] is full and still find weapons to load on init in the turf!")
|
|
qdel(gun)
|
|
|
|
if(length(req_one_access))
|
|
locked = TRUE
|
|
|
|
update_icon()
|
|
|
|
/obj/structure/weapons_rack/Destroy()
|
|
QDEL_NULL(visual_holder)
|
|
|
|
. = ..()
|
|
|
|
/obj/structure/weapons_rack/attackby(obj/item/attacking_item, mob/user, params)
|
|
. = ..()
|
|
|
|
//Hit with a gun, to add it to the rack
|
|
if(istype(attacking_item, /obj/item/gun))
|
|
//No adding or removing weapons from the rack while locked
|
|
if(locked)
|
|
to_chat(user, SPAN_WARNING("The rack is locked."))
|
|
return
|
|
|
|
if(length(src.contents) >= max_weapons_loaded)
|
|
to_chat(user, SPAN_WARNING("The rack is full."))
|
|
return
|
|
|
|
if(!user.unEquip(attacking_item))
|
|
return
|
|
|
|
attacking_item.forceMove(src)
|
|
update_icon()
|
|
|
|
//Hit with ID, to lock/unlock the rack
|
|
else if(istype(attacking_item, /obj/item/card/id))
|
|
var/obj/item/card/id/identification_card = attacking_item
|
|
if(!forced_open && has_access(req_one_access = src.req_one_access, accesses = identification_card.access))
|
|
balloon_alert_to_viewers("[locked ? "unlocked" : "locked"]")
|
|
playsound(src, 'sound/items/metal_shutter.ogg', 50, TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
|
toggle_lock(user)
|
|
|
|
else
|
|
balloon_alert(user, "it won't budge!")
|
|
to_chat(user, SPAN_WARNING("You lack the required access to operate this rack's lock, or the lock mechanism is broken."))
|
|
|
|
else if(locked && attacking_item.iswelder())
|
|
var/obj/item/weldingtool/WT = attacking_item
|
|
|
|
balloon_alert_to_viewers("cutting through the lock...")
|
|
|
|
if(WT.use_tool(src, user, 20 SECONDS, extra_checks = CALLBACK(src, PROC_REF(can_be_opened))))
|
|
//Last check because use_tool() is shitcoded
|
|
if(forced_open || !can_be_opened())
|
|
return
|
|
toggle_lock(user)
|
|
balloon_alert_to_viewers("lock cut")
|
|
forced_open = TRUE
|
|
|
|
else
|
|
to_chat(user, SPAN_NOTICE("\The [src] was unlocked while you were working on it!"))
|
|
|
|
|
|
/obj/structure/weapons_rack/attack_hand(mob/living/user)
|
|
. = ..()
|
|
if(length(src.contents))
|
|
//No adding or removing weapons from the rack while locked
|
|
if(locked)
|
|
to_chat(user, SPAN_WARNING("The rack is locked."))
|
|
return
|
|
|
|
//Build a list of options for the radial menu, based on our content
|
|
var/list/radial_options = list()
|
|
for(var/obj/item/gun/gun_in_rack in src.contents)
|
|
radial_options[gun_in_rack] = image(gun_in_rack.icon, gun_in_rack.icon_state)
|
|
|
|
//Show the user the radial menu
|
|
var/obj/item/gun/rifle_to_take = show_radial_menu(user, src, radial_options, require_near = TRUE, tooltips = TRUE)
|
|
|
|
//No choice was made, return
|
|
if(isnull(rifle_to_take))
|
|
return
|
|
|
|
//Assuming the rifle is still in the rack when the user chooses it, deliver the rifle
|
|
if(rifle_to_take in src.contents)
|
|
rifle_to_take.forceMove(get_turf(user))
|
|
user.put_in_hands(rifle_to_take)
|
|
update_icon()
|
|
|
|
else
|
|
to_chat(user, SPAN_WARNING("\The [rifle_to_take] is not in the rack anymore!"))
|
|
|
|
|
|
#define BASE_OFFSET_RIFLE_SLOT -1
|
|
#define INTER_OFFSET_RIFLE_SLOT 7
|
|
/obj/structure/weapons_rack/update_icon()
|
|
. = ..()
|
|
visual_holder.overlays.Cut()
|
|
ClearOverlays()
|
|
|
|
for(var/i in 1 to length(src.contents))
|
|
var/obj/item/gun/G = src.contents[i]
|
|
var/matrix/transform_matrix = matrix(G.transform)
|
|
|
|
transform_matrix.Turn(-90)
|
|
transform_matrix.Scale(0.8, 0.8)
|
|
transform_matrix.Translate((((world.icon_size/2)+BASE_OFFSET_RIFLE_SLOT) - world.icon_size) + (i*INTER_OFFSET_RIFLE_SLOT), 0)
|
|
|
|
//Why not the rifle itself you might ask? Because there's the safety icon on it
|
|
var/mutable_appearance/weapon_appearance = mutable_appearance(G.icon, G.icon_state, plane = src.plane, flags = G.appearance_flags, layer = G.layer)
|
|
weapon_appearance.transform = transform_matrix
|
|
|
|
visual_holder.overlays += weapon_appearance
|
|
|
|
if(locked)
|
|
AddOverlays(image(src.icon, "locked_overlay", layer = ABOVE_OBJ_LAYER))
|
|
|
|
#undef BASE_OFFSET_RIFLE_SLOT
|
|
#undef INTER_OFFSET_RIFLE_SLOT
|
|
|
|
/obj/structure/weapons_rack/emag_act(remaining_charges, mob/user, emag_source)
|
|
. = ..()
|
|
|
|
to_chat(user, SPAN_NOTICE("You start to fiddle with the electronic lock of \the [src]."))
|
|
if(do_after(user, 10 SECONDS, src, extra_checks = CALLBACK(src, PROC_REF(can_be_opened))))
|
|
to_chat(user, SPAN_NOTICE("You manage to unlock \the [src]."))
|
|
toggle_lock(user)
|
|
|
|
/obj/structure/weapons_rack/ex_act(severity)
|
|
if(severity > 1 && can_be_opened())
|
|
toggle_lock()
|
|
forced_open = TRUE
|
|
|
|
if(severity > 2)
|
|
for(var/obj/item/gun/G in src.contents)
|
|
if(prob(10))
|
|
//Uh oh, the munitions cooked in the gun!
|
|
fragem(get_turf(G), 4, 7, 3, 3, 10, 1, TRUE)
|
|
qdel(G)
|
|
else
|
|
throw_at_random(TRUE, 4, 7)
|
|
|
|
. = ..()
|
|
|
|
/obj/structure/weapons_rack/fire_act(exposed_temperature, exposed_volume)
|
|
. = ..()
|
|
|
|
if(exposed_temperature > 1811) //Melting temperature of steel, in kelvin
|
|
//You melted the door
|
|
if(can_be_opened())
|
|
if(prob(20))
|
|
toggle_lock()
|
|
forced_open = TRUE
|
|
|
|
else
|
|
var/picked = pick_weight(list("burn_weapon" = 2, "explode_ammos" = 10, "nothing" = 80))
|
|
|
|
//Burn down one of the guns
|
|
if(picked == "burn_weapon" && length(src.contents))
|
|
var/obj/item/gun/G = pick(src.contents)
|
|
G.forceMove(get_turf(src))
|
|
qdel(G)
|
|
|
|
//Just some explosion effect
|
|
else if(picked == "explode_ammos")
|
|
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(fragem), get_turf(src), 2, 3, 3, 3, 10, 1, TRUE)
|
|
|
|
|
|
/**
|
|
* Locks/unlocks the rack
|
|
*
|
|
* * user - A `/mob` that is unlocking the rack, optional
|
|
*/
|
|
/obj/structure/weapons_rack/proc/toggle_lock(mob/user, force_lock_state)
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
|
|
if(user)
|
|
add_fibers(user)
|
|
add_fingerprint(user)
|
|
|
|
locked = !locked
|
|
update_icon()
|
|
|
|
/**
|
|
* Checks if the locker can be opened (NOT permissions, as in "did someone else already open it" kind of thing)
|
|
*
|
|
*/
|
|
/obj/structure/weapons_rack/proc/can_be_opened()
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
SHOULD_BE_PURE(TRUE)
|
|
|
|
//Can't open it, it's forced open
|
|
if(forced_open)
|
|
return FALSE
|
|
|
|
if(locked)
|
|
return TRUE
|
|
else
|
|
return FALSE
|