mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 12:01:47 +00:00
* removes double spaces AFTER symbols * Fixing conflicts Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: GoldenAlpharex <jerego1234@hotmail.com>
457 lines
15 KiB
Plaintext
457 lines
15 KiB
Plaintext
/**
|
|
* Paper
|
|
* also scraps of paper
|
|
*
|
|
* lipstick wiping is in code/game/objects/items/weapons/cosmetics.dm!
|
|
*/
|
|
#define MAX_PAPER_LENGTH 5000
|
|
#define MAX_PAPER_STAMPS 30 // Too low?
|
|
#define MAX_PAPER_STAMPS_OVERLAYS 4
|
|
#define MODE_READING 0
|
|
#define MODE_WRITING 1
|
|
#define MODE_STAMPING 2
|
|
|
|
#define DEFAULT_ADD_INFO_COLOR "black"
|
|
#define DEFAULT_ADD_INFO_FONT "Verdana"
|
|
#define DEFAULT_ADD_INFO_SIGN "signature"
|
|
|
|
/**
|
|
* Paper is now using markdown (like in github pull notes) for ALL rendering
|
|
* so we do loose a bit of functionality but we gain in easy of use of
|
|
* paper and getting rid of that crashing bug
|
|
*/
|
|
/obj/item/paper
|
|
name = "paper"
|
|
gender = NEUTER
|
|
icon = 'icons/obj/bureaucracy.dmi'
|
|
icon_state = "paper"
|
|
inhand_icon_state = "paper"
|
|
worn_icon_state = "paper"
|
|
custom_fire_overlay = "paper_onfire_overlay"
|
|
throwforce = 0
|
|
w_class = WEIGHT_CLASS_TINY
|
|
throw_range = 1
|
|
throw_speed = 1
|
|
pressure_resistance = 0
|
|
slot_flags = ITEM_SLOT_HEAD
|
|
body_parts_covered = HEAD
|
|
resistance_flags = FLAMMABLE
|
|
max_integrity = 50
|
|
dog_fashion = /datum/dog_fashion/head
|
|
drop_sound = 'sound/items/handling/paper_drop.ogg'
|
|
pickup_sound = 'sound/items/handling/paper_pickup.ogg'
|
|
grind_results = list(/datum/reagent/cellulose = 3)
|
|
color = "white"
|
|
/// What's actually written on the paper.
|
|
var/info = ""
|
|
/**
|
|
* What's been written on the paper by things other than players.
|
|
* Will be sanitized by the UI, and finally
|
|
* added to info when the user edits the paper text.
|
|
*/
|
|
var/list/add_info
|
|
/// The font color, face and the signature of the above.
|
|
var/list/add_info_style
|
|
|
|
var/show_written_words = TRUE
|
|
|
|
/// The (text for the) stamps on the paper.
|
|
var/list/stamps /// Positioning for the stamp in tgui
|
|
var/list/stamped /// Overlay info
|
|
|
|
var/contact_poison // Reagent ID to transfer on contact
|
|
var/contact_poison_volume = 0
|
|
|
|
/// When the sheet can be "filled out"
|
|
/// This is an associated list
|
|
var/list/form_fields = list()
|
|
var/field_counter = 1
|
|
|
|
/obj/item/paper/Destroy()
|
|
stamps = null
|
|
stamped = null
|
|
form_fields = null
|
|
stamped = null
|
|
. = ..()
|
|
|
|
/**
|
|
* This proc copies this sheet of paper to a new
|
|
* sheet. Used by carbon papers and the photocopier machine.
|
|
*/
|
|
/obj/item/paper/proc/copy(paper_type = /obj/item/paper, atom/location = loc, colored = TRUE)
|
|
var/obj/item/paper/new_paper = new paper_type (location)
|
|
if(colored)
|
|
new_paper.color = color
|
|
new_paper.info = info
|
|
new_paper.add_info_style = add_info_style.Copy()
|
|
else //This basically just breaks the existing color tag, which we need to do because the innermost tag takes priority.
|
|
var/static/greyscale_info = regex("(?<=<font style=\")color=(.*)?>", "i")
|
|
new_paper.info = replacetext(info, greyscale_info, "nocolor=$1>")
|
|
for(var/list/style as anything in add_info_style)
|
|
LAZYADD(new_paper.add_info_style, list(list(DEFAULT_ADD_INFO_COLOR, style[ADD_INFO_FONT], style[ADD_INFO_SIGN])))
|
|
new_paper.add_info = add_info?.Copy()
|
|
new_paper.stamps = stamps?.Copy()
|
|
new_paper.stamped = stamped?.Copy()
|
|
new_paper.form_fields = form_fields.Copy()
|
|
new_paper.field_counter = field_counter
|
|
new_paper.update_icon_state()
|
|
copy_overlays(new_paper, TRUE)
|
|
return new_paper
|
|
|
|
/**
|
|
* This proc sets the text of the paper and updates the
|
|
* icons. You can modify the pen_color after if need
|
|
* be.
|
|
*/
|
|
/obj/item/paper/proc/setText(text, update_icon = TRUE)
|
|
info = text
|
|
add_info = null
|
|
add_info_style = null
|
|
form_fields = null
|
|
field_counter = 0
|
|
if(update_icon)
|
|
update_appearance()
|
|
|
|
/obj/item/paper/pickup(user)
|
|
if(contact_poison && ishuman(user))
|
|
var/mob/living/carbon/human/H = user
|
|
var/obj/item/clothing/gloves/G = H.gloves
|
|
if(!istype(G) || G.transfer_prints)
|
|
H.reagents.add_reagent(contact_poison,contact_poison_volume)
|
|
contact_poison = null
|
|
. = ..()
|
|
|
|
/obj/item/paper/Initialize(mapload)
|
|
. = ..()
|
|
pixel_x = base_pixel_x + rand(-9, 9)
|
|
pixel_y = base_pixel_y + rand(-8, 8)
|
|
update_appearance()
|
|
|
|
/obj/item/paper/update_icon_state()
|
|
if((info || add_info) && show_written_words)
|
|
icon_state = "[initial(icon_state)]_words"
|
|
return ..()
|
|
|
|
/obj/item/paper/verb/rename()
|
|
set name = "Rename paper"
|
|
set category = "Object"
|
|
set src in usr
|
|
|
|
if(!usr.can_read(src) || usr.incapacitated(TRUE, TRUE) || (isobserver(usr) && !isAdminGhostAI(usr)))
|
|
return
|
|
if(ishuman(usr))
|
|
var/mob/living/carbon/human/H = usr
|
|
if(HAS_TRAIT(H, TRAIT_CLUMSY) && prob(25))
|
|
to_chat(H, span_warning("You cut yourself on the paper! Ahhhh! Ahhhhh!"))
|
|
H.damageoverlaytemp = 9001
|
|
H.update_damage_hud()
|
|
return
|
|
var/n_name = stripped_input(usr, "What would you like to label the paper?", "Paper Labelling", null, MAX_NAME_LEN)
|
|
if(((loc == usr || istype(loc, /obj/item/clipboard)) && usr.stat == CONSCIOUS))
|
|
name = "paper[(n_name ? text("- '[n_name]'") : null)]"
|
|
add_fingerprint(usr)
|
|
|
|
/obj/item/paper/suicide_act(mob/user)
|
|
user.visible_message(span_suicide("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku..."))
|
|
return (BRUTELOSS)
|
|
|
|
/obj/item/paper/proc/clearpaper()
|
|
setText("", update_icon = FALSE)
|
|
stamps = null
|
|
LAZYCLEARLIST(stamped)
|
|
cut_overlays()
|
|
update_icon_state()
|
|
|
|
/obj/item/paper/examine(mob/user)
|
|
. = ..()
|
|
if(!in_range(user, src) && !isobserver(user))
|
|
. += span_warning("You're too far away to read it!")
|
|
return
|
|
if(user.can_read(src))
|
|
ui_interact(user)
|
|
return
|
|
. += span_warning("You cannot read it!")
|
|
|
|
/obj/item/paper/ui_status(mob/user,/datum/ui_state/state)
|
|
// Are we on fire? Hard ot read if so
|
|
if(resistance_flags & ON_FIRE)
|
|
return UI_CLOSE
|
|
if(!in_range(user, src) && !isobserver(user))
|
|
return UI_CLOSE
|
|
if(user.incapacitated(TRUE, TRUE) || (isobserver(user) && !isAdminGhostAI(user)))
|
|
return UI_UPDATE
|
|
// Even harder to read if your blind...braile? humm
|
|
// .. or if you cannot read
|
|
if(!user.can_read(src))
|
|
return UI_CLOSE
|
|
if(in_contents_of(/obj/machinery/door/airlock) || in_contents_of(/obj/item/clipboard))
|
|
return UI_INTERACTIVE
|
|
return ..()
|
|
|
|
|
|
|
|
/obj/item/paper/can_interact(mob/user)
|
|
if(in_contents_of(/obj/machinery/door/airlock))
|
|
return TRUE
|
|
return ..()
|
|
|
|
|
|
/obj/item/proc/burn_paper_product_attackby_check(obj/item/I, mob/living/user, bypass_clumsy)
|
|
var/ignition_message = I.ignition_effect(src, user)
|
|
if(!ignition_message)
|
|
return
|
|
. = TRUE
|
|
if(!bypass_clumsy && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && Adjacent(user))
|
|
user.visible_message(span_warning("[user] accidentally ignites [user.p_them()]self!"), \
|
|
span_userdanger("You miss [src] and accidentally light yourself on fire!"))
|
|
if(user.is_holding(I)) //checking if they're holding it in case TK is involved
|
|
user.dropItemToGround(I)
|
|
user.adjust_fire_stacks(1)
|
|
user.IgniteMob()
|
|
return
|
|
|
|
if(user.is_holding(src)) //no TK shit here.
|
|
user.dropItemToGround(src)
|
|
user.visible_message(ignition_message)
|
|
add_fingerprint(user)
|
|
fire_act(I.get_temperature())
|
|
|
|
/obj/item/paper/proc/add_info(text, color = DEFAULT_ADD_INFO_COLOR, font = DEFAULT_ADD_INFO_FONT, signature = DEFAULT_ADD_INFO_SIGN)
|
|
LAZYADD(add_info, text)
|
|
LAZYADD(add_info_style, list(list(color, font, signature)))
|
|
|
|
/obj/item/paper/proc/get_info_length()
|
|
. = length_char(info)
|
|
for(var/index in 1 to length(add_info))
|
|
var/style = LAZYACCESS(add_info_style, index)
|
|
if(style)
|
|
var/static/regex/sign_regex = regex("%s(?:ign)?(?=\\s|$)?", "igm")
|
|
var/signed_text = sign_regex.Replace(add_info[index], style[ADD_INFO_SIGN])
|
|
. += length_char(PAPER_MARK_TEXT(signed_text, style[ADD_INFO_COLOR], style[ADD_INFO_FONT]))
|
|
else
|
|
. += length_char(add_info[index])
|
|
|
|
/obj/item/paper/attackby(obj/item/P, mob/living/user, params)
|
|
if(burn_paper_product_attackby_check(P, user))
|
|
SStgui.close_uis(src)
|
|
return
|
|
|
|
// Enable picking paper up by clicking on it with the clipboard or folder
|
|
if(istype(P, /obj/item/clipboard) || istype(P, /obj/item/folder) || istype(P, /obj/item/paper_bin))
|
|
P.attackby(src, user)
|
|
return
|
|
else if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
|
|
if(get_info_length() >= MAX_PAPER_LENGTH) // Sheet must have less than 5000 charaters
|
|
to_chat(user, span_warning("This sheet of paper is full!"))
|
|
return
|
|
ui_interact(user)
|
|
return
|
|
else if(istype(P, /obj/item/stamp))
|
|
to_chat(user, span_notice("You ready your stamp over the paper! "))
|
|
ui_interact(user)
|
|
return /// Normaly you just stamp, you don't need to read the thing
|
|
else
|
|
// cut paper? the sky is the limit!
|
|
ui_interact(user) // The other ui will be created with just read mode outside of this
|
|
|
|
return ..()
|
|
|
|
|
|
/obj/item/paper/fire_act(exposed_temperature, exposed_volume)
|
|
. = ..()
|
|
if(.)
|
|
info = "[stars(info)]"
|
|
for(var/index in 1 to add_info)
|
|
add_info[index] = "[stars(add_info[index])]"
|
|
|
|
/obj/item/paper/ui_assets(mob/user)
|
|
return list(
|
|
get_asset_datum(/datum/asset/spritesheet/simple/paper),
|
|
)
|
|
|
|
/obj/item/paper/ui_interact(mob/user, datum/tgui/ui)
|
|
// Update the UI
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "PaperSheet", name)
|
|
ui.open()
|
|
|
|
/obj/item/paper/ui_static_data(mob/user)
|
|
. = list()
|
|
.["text"] = info
|
|
if(length(add_info))
|
|
.["add_text"] = add_info
|
|
.["add_color"] = list()
|
|
.["add_font"] = list()
|
|
.["add_sign"] = list()
|
|
for(var/index in 1 to length(add_info))
|
|
var/list/style = LAZYACCESS(add_info_style, index)
|
|
if(!islist(index) || length(style) < ADD_INFO_SIGN) // failsafe for malformed add_info_style.
|
|
var/list/corrected_style = list(DEFAULT_ADD_INFO_COLOR, DEFAULT_ADD_INFO_FONT, DEFAULT_ADD_INFO_SIGN)
|
|
LAZYADD(add_info_style, corrected_style)
|
|
style = corrected_style
|
|
.["add_color"] += style[ADD_INFO_COLOR]
|
|
.["add_font"] += style[ADD_INFO_FONT]
|
|
.["add_sign"] += style[ADD_INFO_SIGN]
|
|
|
|
.["max_length"] = MAX_PAPER_LENGTH
|
|
.["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set
|
|
.["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling?
|
|
.["stamps"] = stamps
|
|
|
|
|
|
/obj/item/paper/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["edit_usr"] = "[user.real_name]"
|
|
|
|
var/obj/holding = user.get_active_held_item()
|
|
// Use a clipboard's pen, if applicable
|
|
if(istype(loc, /obj/item/clipboard))
|
|
var/obj/item/clipboard/clipboard = loc
|
|
// This is just so you can still use a stamp if you're holding one. Otherwise, it'll
|
|
// use the clipboard's pen, if applicable.
|
|
if(!istype(holding, /obj/item/stamp) && clipboard.pen)
|
|
holding = clipboard.pen
|
|
if(istype(holding, /obj/item/toy/crayon))
|
|
var/obj/item/toy/crayon/PEN = holding
|
|
data["pen_font"] = CRAYON_FONT
|
|
data["pen_color"] = PEN.paint_color
|
|
data["edit_mode"] = MODE_WRITING
|
|
data["is_crayon"] = TRUE
|
|
data["stamp_class"] = "FAKE"
|
|
data["stamp_icon_state"] = "FAKE"
|
|
else if(istype(holding, /obj/item/pen))
|
|
var/obj/item/pen/PEN = holding
|
|
data["pen_font"] = PEN.font
|
|
data["pen_color"] = PEN.colour
|
|
data["edit_mode"] = MODE_WRITING
|
|
data["is_crayon"] = FALSE
|
|
data["stamp_class"] = "FAKE"
|
|
data["stamp_icon_state"] = "FAKE"
|
|
else if(istype(holding, /obj/item/stamp))
|
|
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper)
|
|
data["stamp_icon_state"] = holding.icon_state
|
|
data["stamp_class"] = sheet.icon_class_name(holding.icon_state)
|
|
data["edit_mode"] = MODE_STAMPING
|
|
data["pen_font"] = "FAKE"
|
|
data["pen_color"] = "FAKE"
|
|
data["is_crayon"] = FALSE
|
|
else
|
|
data["edit_mode"] = MODE_READING
|
|
data["pen_font"] = "FAKE"
|
|
data["pen_color"] = "FAKE"
|
|
data["is_crayon"] = FALSE
|
|
data["stamp_icon_state"] = "FAKE"
|
|
data["stamp_class"] = "FAKE"
|
|
if(istype(loc, /obj/structure/noticeboard))
|
|
var/obj/structure/noticeboard/noticeboard = loc
|
|
if(!noticeboard.allowed(user))
|
|
data["edit_mode"] = MODE_READING
|
|
data["field_counter"] = field_counter
|
|
data["form_fields"] = form_fields
|
|
|
|
return data
|
|
|
|
/obj/item/paper/ui_act(action, params,datum/tgui/ui)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
switch(action)
|
|
if("stamp")
|
|
var/stamp_x = text2num(params["x"])
|
|
var/stamp_y = text2num(params["y"])
|
|
var/stamp_r = text2num(params["r"]) // rotation in degrees
|
|
var/stamp_icon_state = params["stamp_icon_state"]
|
|
var/stamp_class = params["stamp_class"]
|
|
if (isnull(stamps))
|
|
stamps = list()
|
|
if(stamps.len < MAX_PAPER_STAMPS)
|
|
// I hate byond when dealing with freaking lists
|
|
stamps[++stamps.len] = list(stamp_class, stamp_x, stamp_y, stamp_r) /// WHHHHY
|
|
|
|
/// This does the overlay stuff
|
|
if (isnull(stamped))
|
|
stamped = list()
|
|
if(stamped.len < MAX_PAPER_STAMPS_OVERLAYS)
|
|
var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[stamp_icon_state]")
|
|
stampoverlay.pixel_x = rand(-2, 2)
|
|
stampoverlay.pixel_y = rand(-3, 2)
|
|
add_overlay(stampoverlay)
|
|
LAZYADD(stamped, stamp_icon_state)
|
|
update_icon()
|
|
|
|
update_static_data(usr,ui)
|
|
var/obj/O = ui.user.get_active_held_item()
|
|
ui.user.visible_message(span_notice("[ui.user] stamps [src] with \the [O.name]!"), span_notice("You stamp [src] with \the [O.name]!"))
|
|
else
|
|
to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!"))
|
|
. = TRUE
|
|
|
|
if("save")
|
|
var/in_paper = params["text"]
|
|
var/paper_len = length(in_paper)
|
|
field_counter = params["field_counter"] ? text2num(params["field_counter"]) : field_counter
|
|
|
|
if(paper_len > MAX_PAPER_LENGTH)
|
|
// Side note, the only way we should get here is if
|
|
// the javascript was modified, somehow, outside of
|
|
// byond. but right now we are logging it as
|
|
// the generated html might get beyond this limit
|
|
log_paper("[key_name(ui.user)] writing to paper [name], and overwrote it by [paper_len-MAX_PAPER_LENGTH]")
|
|
if(paper_len == 0)
|
|
to_chat(ui.user, pick("Writing block strikes again!", "You forgot to write anthing!"))
|
|
else
|
|
log_paper("[key_name(ui.user)] writing to paper [name]")
|
|
if(info != in_paper)
|
|
to_chat(ui.user, "You have added to your paper masterpiece!");
|
|
info = in_paper
|
|
add_info = null
|
|
add_info_style = null
|
|
update_static_data(usr,ui)
|
|
|
|
update_appearance()
|
|
. = TRUE
|
|
|
|
/obj/item/paper/ui_host(mob/user)
|
|
if(istype(loc, /obj/structure/noticeboard))
|
|
return loc
|
|
return ..()
|
|
|
|
/**
|
|
* Construction paper
|
|
*/
|
|
/obj/item/paper/construction
|
|
|
|
/obj/item/paper/construction/Initialize(mapload)
|
|
. = ..()
|
|
color = pick("FF0000", "#33cc33", "#ffb366", "#551A8B", "#ff80d5", "#4d94ff")
|
|
|
|
/**
|
|
* Natural paper
|
|
*/
|
|
/obj/item/paper/natural/Initialize(mapload)
|
|
. = ..()
|
|
color = "#FFF5ED"
|
|
|
|
/obj/item/paper/crumpled
|
|
name = "paper scrap"
|
|
icon_state = "scrap"
|
|
slot_flags = null
|
|
show_written_words = FALSE
|
|
|
|
/obj/item/paper/crumpled/bloody
|
|
icon_state = "scrap_bloodied"
|
|
|
|
/obj/item/paper/crumpled/muddy
|
|
icon_state = "scrap_mud"
|
|
|
|
#undef MAX_PAPER_LENGTH
|
|
#undef MAX_PAPER_STAMPS
|
|
#undef MAX_PAPER_STAMPS_OVERLAYS
|
|
#undef MODE_READING
|
|
#undef MODE_WRITING
|
|
#undef MODE_STAMPING
|
|
#undef DEFAULT_ADD_INFO_COLOR
|
|
#undef DEFAULT_ADD_INFO_FONT
|
|
#undef DEFAULT_ADD_INFO_SIGN
|