[MIRROR] Updates paper biscuits and the paper cutter [MDB IGNORE] (#20312)

* Updates paper biscuits and the paper cutter (#74473)

## About The Pull Request

Well this started as a PR updating some of the spelling and grammar on
the biscuits... though spilled out a little into other aspects of the
relevant code.
There are a few things I've done here.

**Paper biscuits:**

- Updated spelling and grammar for paper biscuits. Confidental ->
confidential, that sort of thing.
- A little reorganisation and cleanup of the code itself.
- Preset slips are now generated on init on the parent from a var,
rather than each having its own init proc.
- Early returns, clearer vars, etc

**Paper Cutters**
Ended up doing more here, even though it wasn't the original reason I
started looking at this code.

- Added one (1) paper cutter blade to the paper cutters cargo crate.
Raised the price a little. This is just a reskinned hatchet, so I don't
think it's much of a balance concern.
- Clarifies and docs vars
- Cleans up refs on destroy
- Many `to_chat`s to `balloon_alert`s
- Removed single-letter vars
- Cancelled attack chains when trying to actually use the cutter. You
now pick it up either by having the blade secured and no paper inside,
or by dragging it into your hand.

## Changelog
🆑
spellcheck: Paper biscuits now have more proper spelling and grammar
qol: You now get one spare paper cutter blade in the paper cutter cargo
crate.
tweak: You now use right click to cut paper with a paper cutter
fix: You can now remove paper from a paper cutter if you change your
mind.
/🆑

---------

Co-authored-by: san7890 <the@ san7890.com>

* Updates paper biscuits and the paper cutter

---------

Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com>
Co-authored-by: san7890 <the@ san7890.com>
This commit is contained in:
SkyratBot
2023-04-04 05:45:59 +02:00
committed by GitHub
parent 6e6c3c2492
commit ccb8a92cc9
7 changed files with 199 additions and 130 deletions
+2 -2
View File
@@ -1033,7 +1033,7 @@ SUBSYSTEM_DEF(job)
if(!id_safe_code)
CRASH("Cannot promote [new_captain.real_name] to Captain, there is no id_safe_code.")
var/paper = new /obj/item/folder/biscuit/confidental/spare_id_safe_code()
var/paper = new /obj/item/folder/biscuit/confidential/spare_id_safe_code()
var/list/slots = list(
LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
@@ -1059,7 +1059,7 @@ SUBSYSTEM_DEF(job)
/// Send a drop pod containing a piece of paper with the spare ID safe code to loc
/datum/controller/subsystem/job/proc/send_spare_id_safe_code(loc)
new /obj/effect/pod_landingzone(loc, /obj/structure/closet/supplypod/centcompod, new /obj/item/folder/biscuit/confidental/emergency_spare_id_safe_code())
new /obj/effect/pod_landingzone(loc, /obj/structure/closet/supplypod/centcompod, new /obj/item/folder/biscuit/confidential/emergency_spare_id_safe_code())
safe_code_timer_id = null
safe_code_request_loc = null
+1 -1
View File
@@ -52,7 +52,7 @@
return COMPONENT_CANCEL_ATTACK_CHAIN
if(H.has_status_effect(/datum/status_effect/neck_slice))
return
return
INVOKE_ASYNC(src, PROC_REF(startNeckSlice), source, H, user)
return COMPONENT_CANCEL_ATTACK_CHAIN
+7 -5
View File
@@ -300,9 +300,11 @@ SKYRAT REMOVAL END */
/datum/supply_pack/misc/papercutter
name = "Paper Cutters Crate"
desc = "Contains 3 office duty paper cutters.\
Those are equipped with sharp blades that can cut any paper into two slick paper slips.\
Blade can be removed from the cutter using screwdriver for cleaning and sharpening of course."
cost = CARGO_CRATE_VALUE * 3.2
contains = list(/obj/item/papercutter = 3)
desc = "Contains 3 office-grade paper cutters, equipped with sharp blades that can cut any paper into two thin slips.\
Comes with one replacement blade."
cost = CARGO_CRATE_VALUE * 3.5
contains = list(
/obj/item/papercutter = 3,
/obj/item/hatchet/cutterblade = 1,
)
crate_name = "paper cutters crate"
+4 -2
View File
@@ -15,6 +15,8 @@
/obj/item/documents,
/obj/item/paperwork,
))
/// Do we hide the contents on examine?
var/contents_hidden = FALSE
/obj/item/folder/suicide_act(mob/living/user)
user.visible_message(span_suicide("[user] begins filing an imaginary death warrant! It looks like [user.p_theyre()] trying to commit suicide!"))
@@ -33,8 +35,8 @@
/obj/item/folder/examine()
. = ..()
if(length(contents))
. += span_notice("Right-click to remove [contents[1]].")
if(length(contents) && !contents_hidden)
. += span_notice("<b>Right-click</b> to remove [contents[1]].")
/obj/item/folder/proc/rename(mob/user, obj/item/writing_instrument)
if(!user.can_write(writing_instrument))
+64 -51
View File
@@ -1,28 +1,41 @@
/obj/item/folder/biscuit
name = "\proper biscuit card"
desc = "An biscuit card. Has label which says <b>DO NOT DIGEST</b>."
name = "biscuit card"
desc = "A biscuit card. On the back, <b>DO NOT DIGEST</b> is printed in large lettering."
icon_state = "paperbiscuit"
bg_color = "#ffffff"
w_class = WEIGHT_CLASS_TINY
max_integrity = 130
drop_sound = 'sound/items/handling/disk_drop.ogg'
pickup_sound = 'sound/items/handling/disk_pickup.ogg'
contents_hidden = TRUE
/// Is biscuit cracked open or not?
var/cracked = FALSE
/// The paper slip inside, if there is one
var/obj/item/paper/paperslip/contained_slip
/obj/item/folder/biscuit/Initialize(mapload)
. = ..()
if(!isnull(contained_slip))
contained_slip = new contained_slip(src)
/obj/item/folder/biscuit/Destroy()
if(contained_slip)
QDEL_NULL(contained_slip)
return ..()
/obj/item/folder/biscuit/suicide_act(mob/living/user)
user.visible_message(span_suicide("[user] tries to eat the paper biscuit! [user.p_theyre()] trying to commit suicide!"))
user.visible_message(span_suicide("[user] tries to eat [src]! [user.p_theyre()] trying to commit suicide!"))
playsound(get_turf(user), 'sound/effects/wounds/crackandbleed.ogg', 40, TRUE) //Don't eat plastic cards kids, they get really sharp if you chew on them.
return BRUTELOSS
/obj/item/folder/biscuit/update_overlays()
. = ..()
if(contents.len) //This is to prevent the not-sealed biscuit to have the folder_paper overlay when it gets sealed
if(contents.len) //This is to prevent the unsealed biscuit from having the folder_paper overlay when it gets sealed
. -= "folder_paper"
if(cracked) //Shows overlay only when it has content and is cracked open
if(cracked) //Shows overlay only when it has contents and is cracked open
. += "paperbiscuit_paper"
///Checks if the biscuit has been already cracked. If its not then it dipsplays "unopened!" ballon alert. If it is cracked then it lets the code continue.
///Checks if the biscuit has been already cracked.
/obj/item/folder/biscuit/proc/crack_check(mob/user)
if (cracked)
return TRUE
@@ -31,10 +44,14 @@
/obj/item/folder/biscuit/examine()
. = ..()
if(!cracked)
. += span_notice("To reach contents you need to crack it open.")
if(cracked)
. += span_notice("It's been cracked open.")
else
. += span_notice("You'll need to crack it open to access its contents.")
if(contained_slip)
. += "This one contains [contained_slip.name]."
//All next is done so you can't reach contents, or put any new contents when its not cracked open
//The next few checks are done to prevent you from reaching the contents or putting anything inside when it's not cracked open
/obj/item/folder/biscuit/remove_item(obj/item/item, mob/user)
if (!crack_check(user))
return
@@ -59,67 +76,63 @@
if (tgui_alert(user, "Do you want to crack it open?", "Biscuit Cracking", list("Yes", "No")) != "Yes")
return
cracked = TRUE
contents_hidden = FALSE
playsound(get_turf(user), 'sound/effects/wounds/crack1.ogg', 60)
icon_state = "[icon_state]_cracked"
update_appearance()
ui_interact(user)
//Corporate "confidental" biscuit cards
/obj/item/folder/biscuit/confidental
name = "\proper confidental biscuit card"
desc = "An confidental biscuit card. In a tasteful blue color with NT logo, looks like a chocolate bar. Has label which says <b>DO NOT DIGEST</b>."
//Corporate "confidential" biscuit cards
/obj/item/folder/biscuit/confidential
name = "confidential biscuit card"
desc = "A confidential biscuit card. The tasteful blue color and NT logo on the front makes it look a little like a chocolate bar. \
On the back, <b>DO NOT DIGEST</b> is printed in large lettering."
icon_state = "paperbiscuit_secret"
bg_color = "#355e9f"
/obj/item/folder/biscuit/confidental/spare_id_safe_code
name = "\proper spare ID safe code biscuit card"
desc = "An biscuit card containing confidental spare ID safe code. In a tasteful blue color with NT logo, looks like a chocolate bar. Has label which says <b>DO NOT DIGEST</b>."
/obj/item/folder/biscuit/confidential/spare_id_safe_code
name = "spare ID safe code biscuit card"
contained_slip = /obj/item/paper/paperslip/corporate/fluff/spare_id_safe_code
/obj/item/folder/biscuit/confidental/spare_id_safe_code/Initialize(mapload)
. = ..()
new /obj/item/paper/paperslip/corporate/fluff/spare_id_safe_code(src)
/obj/item/folder/biscuit/confidential/emergency_spare_id_safe_code
name = "spare emergency ID safe code biscuit card"
contained_slip = /obj/item/paper/paperslip/corporate/fluff/emergency_spare_id_safe_code
/obj/item/folder/biscuit/confidental/emergency_spare_id_safe_code
name = "\proper spare emergency ID safe code biscuit card"
desc = "An biscuit card containing <i>not so confidental</i> emergency spare ID safe code. In a tasteful blue color with NT logo, looks like a chocolate bar. Has label which says <b>DO NOT DIGEST</b>."
/obj/item/folder/biscuit/confidental/emergency_spare_id_safe_code/Initialize(mapload)
. = ..()
new /obj/item/paper/paperslip/corporate/fluff/emergency_spare_id_safe_code(src)
//Biscuits which start not-sealed/cracked initially for the crafting, printing and such
//Biscuits which start open. Used for crafting, printing, and such
/obj/item/folder/biscuit/unsealed
name = "\proper biscuit card"
desc = "An biscuit card. Has label which says <b>DO NOT DIGEST</b>."
name = "biscuit card"
desc = "A biscuit card. On the back, <b>DO NOT DIGEST</b> is printed in large lettering."
icon_state = "paperbiscuit_cracked"
contents_hidden = FALSE
cracked = TRUE
///Was the biscuit already sealed by players? To prevent several tgui alerts
var/sealed = FALSE
///What is the sprite for when its not cracked? As it starts already cracked, and for re-sealing needs to have a sprite
var/not_cracked_icon = "paperbiscuit"
///Was the biscuit already sealed by players? Prevents re-sealing after use
var/has_been_sealed = FALSE
///What is the sprite for when it's sealed? It starts unsealed, so needs a sprite for when it's sealed.
var/sealed_icon = "paperbiscuit"
/obj/item/folder/biscuit/unsealed/examine()
. = ..()
if(!sealed)
. += span_notice("This one have not been sealed yet. You many insert anything to seal it by pressing it in hand. Once sealed, the contents are inaccessible until cracked open (irreversible).")
if(!has_been_sealed)
. += span_notice("This one could be sealed <b>in hand</b>. Once sealed, the contents are inaccessible until cracked open again - but once opened this is irreversible.")
//Asks if you want to seal the biscuit, after you do that it behaves like normal paper biscuit.
//Asks if you want to seal the biscuit, after you do that it behaves like a normal paper biscuit.
/obj/item/folder/biscuit/unsealed/attack_self(mob/user)
add_fingerprint(user)
if (!sealed)
if (tgui_alert(user, "Do you want to seal it? You must crack it open to reach the contents again!", "Biscuit Sealing", list("Yes", "No")) != "Yes")
return
cracked = FALSE
sealed = TRUE
playsound(get_turf(user), 'sound/items/duct_tape_snap.ogg', 60)
icon_state = "[not_cracked_icon]"
update_appearance()
if(!cracked)
return ..()
if(tgui_alert(user, "Do you want to seal it? This can only be done once.", "Biscuit Sealing", list("Yes", "No")) != "Yes")
return
cracked = FALSE
has_been_sealed = TRUE
contents_hidden = TRUE
playsound(get_turf(user), 'sound/items/duct_tape_snap.ogg', 60)
icon_state = "[sealed_icon]"
update_appearance()
return ..()
/obj/item/folder/biscuit/unsealed/confidental
name = "\proper confidental biscuit card"
desc = "An confidental biscuit card. In a tasteful blue color with NT logo, looks like a chocolate bar. To reach contents you need to crack it open. Has label which says <b>DO NOT DIGEST</b>."
/obj/item/folder/biscuit/unsealed/confidential
name = "confidential biscuit card"
desc = "A confidential biscuit card. The tasteful blue color and NT logo on the front makes it look a little like a chocolate bar. On the back, <b>DO NOT DIGEST</b> is printed in large lettering."
icon_state = "paperbiscuit_secret_cracked"
bg_color = "#355e9f"
not_cracked_icon = "paperbiscuit_secret"
sealed_icon = "paperbiscuit_secret"
+116 -64
View File
@@ -6,108 +6,160 @@
force = 5
throwforce = 5
w_class = WEIGHT_CLASS_NORMAL
var/obj/item/paper/storedpaper = null
var/obj/item/hatchet/cutterblade/storedcutter = null
var/cuttersecured = TRUE
pass_flags = PASSTABLE
/// The paper currently loaded inside the cutter
var/obj/item/paper/stored_paper
/// The blade currently loaded inside the cutter
var/obj/item/hatchet/cutterblade/stored_blade
/// Whether the cutter blade is secured or not.
var/blade_secured = TRUE
/// The chance for a clumsy person to cut themselves on the blade
/// Should probably be low-ish to prevent people spamming it quite so easily
var/cut_self_chance = 5
/obj/item/papercutter/Initialize(mapload)
. = ..()
storedcutter = new /obj/item/hatchet/cutterblade(src)
stored_blade = new /obj/item/hatchet/cutterblade(src)
update_appearance()
/obj/item/papercutter/Destroy(force)
if(stored_paper)
stored_paper.forceMove(get_turf(src))
stored_paper = null
if(stored_blade)
stored_blade.forceMove(get_turf(src))
stored_blade = null
return ..()
/obj/item/papercutter/examine(mob/user)
. = ..()
. += "<b>Right-Click</b> to cut paper once it's inside."
if(stored_blade)
. += "The blade could be [blade_secured ? "un" : ""]secured with a <b>screwdriver</b>[blade_secured ? "" : " or removed with an <b>empty hand</b>"]."
/obj/item/papercutter/suicide_act(mob/living/user)
if(storedcutter)
user.visible_message(span_suicide("[user] is beheading [user.p_them()]self with [src.name]! It looks like [user.p_theyre()] trying to commit suicide!"))
if(iscarbon(user))
var/mob/living/carbon/C = user
var/obj/item/bodypart/BP = C.get_bodypart(BODY_ZONE_HEAD)
if(BP)
BP.drop_limb()
playsound(loc, SFX_DESECRATION ,50, TRUE, -1)
return BRUTELOSS
else
user.visible_message(span_suicide("[user] repeatedly bashes [src.name] against [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!"))
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
if(iscarbon(user) && stored_blade)
var/mob/living/carbon/carbon_user = user
var/obj/item/bodypart/user_head = carbon_user.get_bodypart(BODY_ZONE_HEAD)
if(isnull(user_head)) // So no head?
user.visible_message(span_suicide("[user] tries to behead [user.p_them()]self with [src], but [user.p_they()] [user.p_were()] already missing it! How embarassing!"))
return SHAME
user.visible_message(span_suicide("[user] is beheading [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
user_head.drop_limb()
playsound(loc, SFX_DESECRATION, 50, TRUE, -1)
return BRUTELOSS
// If we have no blade, just beat ourselves up
user.visible_message(span_suicide("[user] repeatedly bashes [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!"))
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
return BRUTELOSS
/obj/item/papercutter/update_icon_state()
icon_state = (storedcutter ? "[initial(icon_state)]-cutter" : "[initial(icon_state)]")
icon_state = (stored_blade ? "[initial(icon_state)]-cutter" : "[initial(icon_state)]")
return ..()
/obj/item/papercutter/update_overlays()
. =..()
if(storedpaper)
if(stored_paper)
. += "paper"
/obj/item/papercutter/screwdriver_act(mob/living/user, obj/item/tool)
if(!storedcutter)
if(!stored_blade && !blade_secured)
balloon_alert(user, "no blade to secure!")
return
tool.play_tool_sound(src)
to_chat(user, span_notice("[storedcutter] has been [cuttersecured ? "unsecured" : "secured"]."))
cuttersecured = !cuttersecured
balloon_alert(user, "blade [blade_secured ? "un" : ""]secured")
blade_secured = !blade_secured
return TOOL_ACT_TOOLTYPE_SUCCESS
/obj/item/papercutter/attackby(obj/item/P, mob/user, params)
if(istype(P, /obj/item/paper) && !storedpaper && !istype(P, /obj/item/paper/paperslip))
if(!user.transferItemToLoc(P, src))
/obj/item/papercutter/attackby(obj/item/inserted_item, mob/user, params)
if(istype(inserted_item, /obj/item/paper) && !istype(inserted_item, /obj/item/paper/paperslip))
if(stored_paper)
balloon_alert(user, "already paper inside!")
if(!user.transferItemToLoc(inserted_item, src))
return
playsound(loc, SFX_PAGE_TURN, 60, TRUE)
to_chat(user, span_notice("You place [P] in [src]."))
storedpaper = P
update_appearance()
return
if(istype(P, /obj/item/hatchet/cutterblade) && !storedcutter)
if(!user.transferItemToLoc(P, src))
balloon_alert(user, "paper inserted")
stored_paper = inserted_item
if(istype(inserted_item, /obj/item/hatchet/cutterblade))
if(stored_blade)
balloon_alert(user, "already a blade inside!")
return
to_chat(user, span_notice("You replace [src]'s [P]."))
P.forceMove(src)
storedcutter = P
update_appearance()
return
..()
if(!user.transferItemToLoc(inserted_item, src))
return
balloon_alert(user, "blade inserted")
inserted_item.forceMove(src)
stored_blade = inserted_item
update_appearance()
return ..()
/obj/item/papercutter/attack_hand(mob/user, list/modifiers)
. = ..()
if(.)
return
add_fingerprint(user)
if(!storedcutter)
to_chat(user, span_warning("The cutting blade is gone! You can't use [src] now."))
return
if(!cuttersecured)
to_chat(user, span_notice("You remove [src]'s [storedcutter]."))
user.put_in_hands(storedcutter)
storedcutter = null
update_appearance()
if(!stored_blade && stored_paper)
balloon_alert(user, "no blade!")
return COMPONENT_CANCEL_ATTACK_CHAIN
if(storedpaper)
playsound(src.loc, 'sound/weapons/slash.ogg', 50, TRUE)
to_chat(user, span_notice("You neatly cut [storedpaper]."))
storedpaper = null
qdel(storedpaper)
new /obj/item/paper/paperslip(get_turf(src))
new /obj/item/paper/paperslip(get_turf(src))
else if(!blade_secured)
balloon_alert(user, "blade removed")
user.put_in_hands(stored_blade)
stored_blade = null
update_appearance()
return COMPONENT_CANCEL_ATTACK_CHAIN
else if(stored_paper)
balloon_alert(user, "paper removed")
user.put_in_hands(stored_paper)
stored_paper = null
update_appearance()
return COMPONENT_CANCEL_ATTACK_CHAIN
// If there's a secured blade but no paper, just pick it up
return ..()
/obj/item/papercutter/attack_hand_secondary(mob/user, list/modifiers)
if(!stored_blade)
balloon_alert(user, "no blade!")
else if(!blade_secured)
balloon_alert(user, "blade unsecured!")
else if(!stored_paper)
balloon_alert(user, "nothing to cut!")
else
cut_paper(user)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/item/papercutter/proc/cut_paper(mob/user)
playsound(src.loc, 'sound/weapons/slash.ogg', 50, TRUE)
var/clumsy = (iscarbon(user) && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(cut_self_chance))
to_chat(user, span_userdanger("You neatly cut [stored_paper][clumsy ? "... and your finger in the process!" : "."]"))
if(clumsy)
var/obj/item/bodypart/finger = user.get_active_hand()
var/datum/wound/slash/moderate/papercut = new
papercut.apply_wound(finger)
stored_paper = null
qdel(stored_paper)
new /obj/item/paper/paperslip(get_turf(src))
new /obj/item/paper/paperslip(get_turf(src))
update_appearance()
/obj/item/papercutter/MouseDrop(atom/over_object)
. = ..()
var/mob/M = usr
if(M.incapacitated() || !Adjacent(M))
var/mob/user = usr
if(user.incapacitated() || !Adjacent(user))
return
if(over_object == M)
M.put_in_hands(src)
if(over_object == user)
user.put_in_hands(src)
else if(istype(over_object, /atom/movable/screen/inventory/hand))
var/atom/movable/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
add_fingerprint(M)
var/atom/movable/screen/inventory/hand/target_hand = over_object
user.putItemFromInventoryInHandIfPossible(src, target_hand.held_index)
add_fingerprint(user)
/obj/item/paper/paperslip
name = "paper slip"
@@ -120,7 +172,7 @@
/obj/item/paper/paperslip/corporate //More fancy and sturdy paper slip which is a "plastic card", used for things like spare ID safe code
name = "corporate plastic card"
desc = "A plastic card for confidental corporate matters. Can be written on with pen somehow."
desc = "A plastic card for confidential corporate matters. Can be written on with pen somehow."
icon_state = "corppaperslip"
grind_results = list(/datum/reagent/plastic_polymers = 1.5) //It's a plastic card after all
max_integrity = 130 //Slightly more sturdy because of being made out of a plastic
@@ -130,7 +182,7 @@
throw_speed = 2
/obj/item/hatchet/cutterblade
name = "paper cutter"
name = "paper cutter blade"
desc = "The blade of a paper cutter. Most likely removed for polishing or sharpening."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "cutterblade"
@@ -564,13 +564,13 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_CARGO
/datum/design/paper_biscuit_confidental
name = "Confidental Paper Biscuit"
desc = "An paper biscuit which can seal in itself paperwork, this one is used for confidental Nanotrasen documents. After sealing it the only way to open is through cracking it, cracking is irreversible and makes it permamently open. Not actually a biscuit."
id = "confidental_biscuit"
/datum/design/paper_biscuit_confidential
name = "Confidential Paper Biscuit"
desc = "An paper biscuit which can seal in itself paperwork, this one is used for confidential Nanotrasen documents. After sealing it the only way to open is through cracking it, cracking is irreversible and makes it permamently open. Not actually a biscuit."
id = "confidential_biscuit"
build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE
materials = list(/datum/material/plastic = 30)
build_path = /obj/item/folder/biscuit/unsealed/confidental
build_path = /obj/item/folder/biscuit/unsealed/confidential
category = list(
RND_CATEGORY_HACKED,
RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_SERVICE,