mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 16:07:40 +00:00
This commit is contained in:
@@ -6,10 +6,12 @@
|
||||
#define RETURN_TYPE(X) set SpacemanDMM_return_type = X
|
||||
#define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X
|
||||
#define UNLINT(X) SpacemanDMM_unlint(X)
|
||||
#define SHOULD_BE_PURE(X) set SpacemanDMM_should_be_pure = X
|
||||
#else
|
||||
#define RETURN_TYPE(X)
|
||||
#define SHOULD_CALL_PARENT(X)
|
||||
#define UNLINT(X) X
|
||||
#define SHOULD_BE_PURE(X)
|
||||
#endif
|
||||
|
||||
/world/proc/enable_debugger()
|
||||
|
||||
@@ -207,6 +207,6 @@
|
||||
|
||||
/obj/item/paper/guides/recycler
|
||||
name = "paper - 'garbage duty instructions'"
|
||||
info = "<h2>New Assignment</h2> You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
|
||||
info = "_New Assignment_\n\n You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.<br><br>There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!"
|
||||
|
||||
#undef SAFETY_COOLDOWN
|
||||
|
||||
@@ -456,7 +456,6 @@
|
||||
|
||||
/obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server)
|
||||
info = "<center><h2>Daily Key Reset</h2></center><br>The new message monitor key is '[server.decryptkey]'.<br>Please keep this a secret and away from the clown.<br>If necessary, change the password to a more secure one."
|
||||
info_links = info
|
||||
add_overlay("paper_words")
|
||||
|
||||
/obj/item/paper/monitorkey/LateInitialize()
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
var/list/log = list()
|
||||
var/range = 8
|
||||
var/view_check = TRUE
|
||||
var/forensicPrintCount = 0
|
||||
actions_types = list(/datum/action/item_action/displayDetectiveScanResults)
|
||||
|
||||
/datum/action/item_action/displayDetectiveScanResults
|
||||
@@ -42,13 +43,16 @@
|
||||
/obj/item/detective_scanner/proc/PrintReport()
|
||||
// Create our paper
|
||||
var/obj/item/paper/P = new(get_turf(src))
|
||||
P.name = "paper- 'Scanner Report'"
|
||||
P.info = "<center><font size='6'><B>Scanner Report</B></font></center><HR><BR>"
|
||||
P.info += jointext(log, "<BR>")
|
||||
P.info += "<HR><B>Notes:</B><BR>"
|
||||
P.info_links = P.info
|
||||
P.updateinfolinks()
|
||||
|
||||
//This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm
|
||||
var frNum = ++forensicPrintCount
|
||||
|
||||
P.name = text(" FR-[] 'Forensic Record'", frNum)
|
||||
var/list/text = new
|
||||
text+= text("* _Forensic Record - (FR-[])_", frNum)
|
||||
text += log.Join("\n")
|
||||
text += "* _Notes:_"
|
||||
P.setText(text.Join("\n"))
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.put_in_hands(P)
|
||||
@@ -216,4 +220,4 @@
|
||||
return
|
||||
to_chat(user, "<span class='notice'><B>Scanner Report</B></span>")
|
||||
for(var/iterLog in log)
|
||||
to_chat(user, iterLog)
|
||||
to_chat(user, iterLog)
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
|
||||
/obj/item/paper/fluff/holodeck/trek_diploma
|
||||
name = "paper - Starfleet Academy Diploma"
|
||||
info = {"<h2>Starfleet Academy</h2></br><p>Official Diploma</p></br>"}
|
||||
info = {"__Starfleet Academy__\nOfficial Diploma"}
|
||||
|
||||
/obj/item/paper/fluff/holodeck/disclaimer
|
||||
name = "Holodeck Disclaimer"
|
||||
|
||||
@@ -556,3 +556,17 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
//Can the mob see reagents inside of containers?
|
||||
/mob/proc/can_see_reagents()
|
||||
return stat == DEAD || silicon_privileges //Dead guys and silicons can always see reagents
|
||||
|
||||
/mob/proc/is_blind()
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return eye_blind ? TRUE : HAS_TRAIT(src, TRAIT_BLIND)
|
||||
|
||||
/mob/proc/can_read(obj/O)
|
||||
if(is_blind())
|
||||
to_chat(src, "<span class='warning'>As you are trying to read [O], you suddenly feel very stupid!</span>")
|
||||
return
|
||||
if(!is_literate())
|
||||
to_chat(src, "<span class='notice'>You try to read [O], but can't comprehend any of it.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -27,13 +27,11 @@
|
||||
|
||||
// Damaged printer causes the resulting paper to be somewhat harder to read.
|
||||
if(damage > damage_malfunction)
|
||||
P.info = stars(text_to_print, 100-malfunction_probability)
|
||||
P.setText(stars(text_to_print, 100-malfunction_probability))
|
||||
else
|
||||
P.info = text_to_print
|
||||
P.setText(text_to_print)
|
||||
if(paper_title)
|
||||
P.name = paper_title
|
||||
P.update_icon()
|
||||
P.reload_fields()
|
||||
stored_paper--
|
||||
P = null
|
||||
return TRUE
|
||||
@@ -59,4 +57,4 @@
|
||||
icon_state = "printer_mini"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
stored_paper = 5
|
||||
max_paper = 15
|
||||
max_paper = 15
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
*
|
||||
* lipstick wiping is in code/game/objects/items/weapons/cosmetics.dm!
|
||||
*/
|
||||
|
||||
/**
|
||||
** 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
|
||||
@@ -21,19 +25,57 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 50
|
||||
dog_fashion = /datum/dog_fashion/head
|
||||
color = "white"
|
||||
/// What's actually written on the paper.
|
||||
var/info
|
||||
|
||||
var/info //What's actually written on the paper.
|
||||
var/info_links //A different version of the paper which includes html links at fields and EOF
|
||||
var/stamps //The (text for the) stamps on the paper.
|
||||
var/fields = 0 //Amount of user created fields
|
||||
/// The (text for the) stamps on the paper.
|
||||
var/stamps
|
||||
var/list/stamped
|
||||
|
||||
/// This REALLY should be a componenet. Basicly used during, april fools
|
||||
/// to honk at you
|
||||
var/rigged = 0
|
||||
var/spam_flag = 0
|
||||
///
|
||||
var/contact_poison // Reagent ID to transfer on contact
|
||||
var/contact_poison_volume = 0
|
||||
var/datum/oracle_ui/ui = null
|
||||
var/force_stars = FALSE // If we should force the text to get obfuscated with asterisks
|
||||
|
||||
var/ui_x = 600
|
||||
var/ui_y = 800
|
||||
/// When a piece of paper cannot be edited, this makes it mutable
|
||||
var/finalized = FALSE
|
||||
/// We MAY be edited, mabye we are just looking at it or something.
|
||||
var/readonly = FALSE
|
||||
/// Color of the pin that wrote on this paper
|
||||
var/pen_color = "black"
|
||||
|
||||
/**
|
||||
** This proc copies this sheet of paper to a new
|
||||
** sheet, Makes it nice and easy for carbon and
|
||||
** the copyer machine
|
||||
**/
|
||||
/obj/item/paper/proc/copy()
|
||||
var/obj/item/paper/N = new(arglist(args))
|
||||
N.info = info
|
||||
N.pen_color = pen_color
|
||||
N.color = color
|
||||
N.finalized = TRUE
|
||||
N.update_icon_state()
|
||||
N.stamps = stamps
|
||||
N.stamped = stamped.Copy()
|
||||
copy_overlays(N, TRUE)
|
||||
return N
|
||||
|
||||
/**
|
||||
** 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, read_only = TRUE)
|
||||
readonly = read_only
|
||||
info = text
|
||||
update_icon_state()
|
||||
|
||||
/obj/item/paper/pickup(user)
|
||||
if(contact_poison && ishuman(user))
|
||||
@@ -42,42 +84,16 @@
|
||||
if(!istype(G) || G.transfer_prints)
|
||||
H.reagents.add_reagent(contact_poison,contact_poison_volume)
|
||||
contact_poison = null
|
||||
//ui.check_view_all()
|
||||
..()
|
||||
|
||||
/obj/item/paper/dropped(mob/user)
|
||||
//ui.check_view(user)
|
||||
return ..()
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/paper/Initialize()
|
||||
. = ..()
|
||||
pixel_y = rand(-8, 8)
|
||||
pixel_x = rand(-9, 9)
|
||||
//ui = new /datum/oracle_ui(src, 420, 600, get_asset_datum(/datum/asset/spritesheet/simple/paper))
|
||||
//ui.can_resize = FALSE
|
||||
update_icon()
|
||||
updateinfolinks()
|
||||
/*
|
||||
/obj/item/paper/oui_getcontent(mob/target)
|
||||
if(!target.is_literate() || force_stars)
|
||||
force_stars = FALSE
|
||||
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
|
||||
else if(istype(target.get_active_held_item(), /obj/item/pen) | istype(target.get_active_held_item(), /obj/item/toy/crayon))
|
||||
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[info_links]<HR>[stamps]</BODY><div align='right'style='position:fixed;bottom:0;font-style:bold;'><A href='?src=[REF(src)];help=1'>\[?\]</A></div></HTML>"
|
||||
else
|
||||
return "<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>[name]</TITLE></HEAD><BODY>[info]<HR>[stamps]</BODY></HTML>"
|
||||
update_icon_state()
|
||||
|
||||
|
||||
/obj/item/paper/oui_canview(mob/target)
|
||||
if(check_rights_for(target.client, R_FUN)) //Allows admins to view faxes
|
||||
return TRUE
|
||||
if(isAI(target))
|
||||
force_stars = TRUE
|
||||
return TRUE
|
||||
if(iscyborg(target))
|
||||
return get_dist(src, target) < 2
|
||||
return ..()
|
||||
*/
|
||||
/obj/item/paper/update_icon_state()
|
||||
if(resistance_flags & ON_FIRE)
|
||||
icon_state = "paper_onfire"
|
||||
@@ -87,13 +103,10 @@
|
||||
return
|
||||
icon_state = "paper"
|
||||
|
||||
|
||||
/obj/item/paper/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Alt-click to fold it.</span>"
|
||||
|
||||
/obj/item/paper/proc/show_content(mob/user)
|
||||
user.examinate(src)
|
||||
/obj/item/paper/ui_base_html(html)
|
||||
/// This might change in a future PR
|
||||
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/paper)
|
||||
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
|
||||
|
||||
/obj/item/paper/verb/rename()
|
||||
set name = "Rename paper"
|
||||
@@ -113,195 +126,62 @@
|
||||
if((loc == usr && usr.stat == CONSCIOUS))
|
||||
name = "paper[(n_name ? text("- '[n_name]'") : null)]"
|
||||
add_fingerprint(usr)
|
||||
//ui.render_all()
|
||||
|
||||
|
||||
/obj/item/paper/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...</span>")
|
||||
return (BRUTELOSS)
|
||||
|
||||
/// ONLY USED FOR APRIL FOOLS
|
||||
|
||||
/obj/item/paper/proc/reset_spamflag()
|
||||
spam_flag = FALSE
|
||||
|
||||
/obj/item/paper/attack_self(mob/user)
|
||||
show_content(user)
|
||||
readonly = TRUE /// Assume we are just reading it
|
||||
if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
|
||||
if(!spam_flag)
|
||||
spam_flag = TRUE
|
||||
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1)
|
||||
playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE)
|
||||
addtimer(CALLBACK(src, .proc/reset_spamflag), 20)
|
||||
|
||||
/obj/item/paper/attack_ai(mob/living/silicon/ai/user)
|
||||
show_content(user)
|
||||
|
||||
/obj/item/paper/proc/addtofield(id, text, links = 0)
|
||||
var/locid = 0
|
||||
var/laststart = 1
|
||||
var/textindex = 1
|
||||
while(locid < 15) //hey whoever decided a while(1) was a good idea here, i hate you
|
||||
var/istart = 0
|
||||
if(links)
|
||||
istart = findtext(info_links, "<span class=\"paper_field\">", laststart)
|
||||
else
|
||||
istart = findtext(info, "<span class=\"paper_field\">", laststart)
|
||||
|
||||
if(istart == 0)
|
||||
return //No field found with matching id
|
||||
|
||||
if(links)
|
||||
laststart = istart + length(info_links[istart])
|
||||
else
|
||||
laststart = istart + length(info[istart])
|
||||
locid++
|
||||
if(locid == id)
|
||||
var/iend = 1
|
||||
if(links)
|
||||
iend = findtext(info_links, "</span>", istart)
|
||||
else
|
||||
iend = findtext(info, "</span>", istart)
|
||||
|
||||
//textindex = istart+26
|
||||
textindex = iend
|
||||
break
|
||||
|
||||
if(links)
|
||||
var/before = copytext(info_links, 1, textindex)
|
||||
var/after = copytext(info_links, textindex)
|
||||
info_links = before + text + after
|
||||
else
|
||||
var/before = copytext(info, 1, textindex)
|
||||
var/after = copytext(info, textindex)
|
||||
info = before + text + after
|
||||
updateinfolinks()
|
||||
|
||||
|
||||
/obj/item/paper/proc/updateinfolinks()
|
||||
info_links = info
|
||||
for(var/i in 1 to min(fields, 15))
|
||||
addtofield(i, "<font face=\"[PEN_FONT]\"><A href='?src=[REF(src)];write=[i]'>write</A></font>", 1)
|
||||
info_links = info_links + "<font face=\"[PEN_FONT]\"><A href='?src=[REF(src)];write=end'>write</A></font>"
|
||||
//ui.render_all()
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/paper/proc/clearpaper()
|
||||
finalized = FALSE
|
||||
info = null
|
||||
stamps = null
|
||||
LAZYCLEARLIST(stamped)
|
||||
cut_overlays()
|
||||
updateinfolinks()
|
||||
update_icon()
|
||||
update_icon_state()
|
||||
|
||||
|
||||
/obj/item/paper/proc/parsepencode(t, obj/item/pen/P, mob/user, iscrayon = 0)
|
||||
if(length(t) < 1) //No input means nothing needs to be parsed
|
||||
return
|
||||
|
||||
t = parsemarkdown(t, user, iscrayon)
|
||||
|
||||
if(!iscrayon)
|
||||
t = "<font face=\"[P.font]\" color=[P.colour]>[t]</font>"
|
||||
else
|
||||
var/obj/item/toy/crayon/C = P
|
||||
t = "<font face=\"[CRAYON_FONT]\" color=[C.paint_color]><b>[t]</b></font>"
|
||||
|
||||
// Count the fields
|
||||
var/laststart = 1
|
||||
while(fields < 15)
|
||||
var/i = findtext(t, "<span class=\"paper_field\">", laststart)
|
||||
if(i == 0)
|
||||
break
|
||||
laststart = i+1
|
||||
fields++
|
||||
|
||||
return t
|
||||
|
||||
/obj/item/paper/proc/reload_fields() // Useful if you made the paper programicly and want to include fields. Also runs updateinfolinks() for you.
|
||||
fields = 0
|
||||
var/laststart = 1
|
||||
while(fields < 15)
|
||||
var/i = findtext(info, "<span class=\"paper_field\">", laststart)
|
||||
if(i == 0)
|
||||
break
|
||||
laststart = i+1
|
||||
fields++
|
||||
updateinfolinks()
|
||||
|
||||
|
||||
/obj/item/paper/proc/openhelp(mob/user)
|
||||
user << browse({"<HTML><HEAD><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><TITLE>Paper Help</TITLE></HEAD>
|
||||
<BODY>
|
||||
You can use backslash (\\) to escape special characters.<br>
|
||||
<br>
|
||||
<b><center>Crayon&Pen commands</center></b><br>
|
||||
<br>
|
||||
# text : Defines a header.<br>
|
||||
|text| : Centers the text.<br>
|
||||
**text** : Makes the text <b>bold</b>.<br>
|
||||
*text* : Makes the text <i>italic</i>.<br>
|
||||
^text^ : Increases the <font size = \"4\">size</font> of the text.<br>
|
||||
%s : Inserts a signature of your name in a foolproof way.<br>
|
||||
%f : Inserts an invisible field which lets you start type from there. Useful for forms.<br>
|
||||
<br>
|
||||
<b><center>Pen exclusive commands</center></b><br>
|
||||
((text)) : Decreases the <font size = \"1\">size</font> of the text.<br>
|
||||
* item : An unordered list item.<br>
|
||||
* item: An unordered list child item.<br>
|
||||
--- : Adds a horizontal rule.
|
||||
</BODY></HTML>"}, "window=paper_help")
|
||||
|
||||
|
||||
/obj/item/paper/Topic(href, href_list)
|
||||
..()
|
||||
var/literate = usr.is_literate()
|
||||
if(!usr.canUseTopic(src, BE_CLOSE, literate))
|
||||
return
|
||||
|
||||
if(href_list["help"])
|
||||
openhelp(usr)
|
||||
return
|
||||
if(href_list["write"])
|
||||
var/id = href_list["write"]
|
||||
var/t = stripped_multiline_input("Enter what you want to write:", "Write", no_trim=TRUE)
|
||||
if(!t || !usr.canUseTopic(src, BE_CLOSE, literate))
|
||||
return
|
||||
var/obj/item/i = usr.get_active_held_item() //Check to see if he still got that darn pen, also check if he's using a crayon or pen.
|
||||
var/iscrayon = 0
|
||||
if(!istype(i, /obj/item/pen))
|
||||
if(!istype(i, /obj/item/toy/crayon))
|
||||
return
|
||||
iscrayon = 1
|
||||
|
||||
if(!in_range(src, usr) && loc != usr && !istype(loc, /obj/item/clipboard) && loc.loc != usr && usr.get_active_held_item() != i) //Some check to see if he's allowed to write
|
||||
return
|
||||
|
||||
t = parsepencode(t, i, usr, iscrayon) // Encode everything from pencode to html
|
||||
|
||||
if(t != null) //No input from the user means nothing needs to be added
|
||||
if(id!="end")
|
||||
addtofield(text2num(id), t) // He wants to edit a field, let him.
|
||||
else
|
||||
info += t // Oh, he wants to edit to the end of the file, let him.
|
||||
updateinfolinks()
|
||||
show_content(usr)
|
||||
update_icon()
|
||||
/obj/item/paper/can_interact(mob/user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(resistance_flags & ON_FIRE) /// Are we on fire? Hard ot read if so
|
||||
return FALSE
|
||||
if(user.is_blind()) /// Even harder to read if your blind...braile? humm
|
||||
return FALSE
|
||||
return user.can_read(src) // checks if the user can read.
|
||||
|
||||
|
||||
/obj/item/paper/attackby(obj/item/P, mob/living/carbon/human/user, params)
|
||||
..()
|
||||
|
||||
if(resistance_flags & ON_FIRE)
|
||||
return
|
||||
|
||||
if(is_blind(user))
|
||||
return
|
||||
|
||||
readonly = TRUE /// Assume we are just reading it
|
||||
if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
|
||||
if(user.is_literate())
|
||||
show_content(user)
|
||||
if(finalized)
|
||||
to_chat(user, "<span class='warning'>This sheet of paper has already been written too!</span>")
|
||||
return
|
||||
readonly = FALSE /// Nope we are going to write stuff
|
||||
/// should a crayon be in the same subtype as a pen? How about a brush or charcoal?
|
||||
if(istype(P, /obj/item/pen))
|
||||
var/obj/item/pen/PEN = P
|
||||
pen_color = PEN.colour
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You don't know how to read or write.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/toy/crayon/PEN = P
|
||||
pen_color = PEN.crayon_color
|
||||
ui_interact(user)
|
||||
return
|
||||
else if(istype(P, /obj/item/stamp))
|
||||
|
||||
if(!in_range(src, user))
|
||||
@@ -319,8 +199,8 @@
|
||||
add_overlay(stampoverlay)
|
||||
|
||||
to_chat(user, "<span class='notice'>You stamp the paper with your rubber stamp.</span>")
|
||||
//ui.render_all()
|
||||
|
||||
return /// Normaly you just stamp, you don't need to read the thing
|
||||
if(P.get_temperature())
|
||||
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10))
|
||||
user.visible_message("<span class='warning'>[user] accidentally ignites [user.p_them()]self!</span>", \
|
||||
@@ -337,19 +217,62 @@
|
||||
user.visible_message("<span class='danger'>[user] lights [src] ablaze with [P]!</span>", "<span class='danger'>You light [src] on fire!</span>")
|
||||
fire_act()
|
||||
|
||||
|
||||
add_fingerprint(user)
|
||||
. = ..()
|
||||
|
||||
/obj/item/paper/fire_act(exposed_temperature, exposed_volume)
|
||||
..()
|
||||
if(!(resistance_flags & FIRE_PROOF))
|
||||
icon_state = "paper_onfire"
|
||||
add_overlay("paper_onfire_overlay")
|
||||
info = "[stars(info)]"
|
||||
|
||||
|
||||
/obj/item/paper/extinguish()
|
||||
..()
|
||||
update_icon()
|
||||
cut_overlay("paper_onfire_overlay")
|
||||
|
||||
/obj/item/paper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/paper)
|
||||
assets.send(user)
|
||||
/// The x size is because we double the width for the editor
|
||||
ui = new(user, src, ui_key, "PaperSheet", name, 400, 600, master_ui, state)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/item/paper/proc/ui_update()
|
||||
var/datum/tgui/ui = SStgui.try_update_ui(usr, src, "main");
|
||||
if(ui)
|
||||
ui.update()
|
||||
|
||||
/obj/item/paper/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["text"] = info
|
||||
data["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling
|
||||
data["pen_color"] = pen_color
|
||||
data["paper_color"] = color || "white" // color might not be set
|
||||
data["edit_sheet"] = readonly || finalized ? FALSE : TRUE
|
||||
/// data["stamps_info"] = list(stamp_info)
|
||||
data["stamps"] = stamps
|
||||
return data
|
||||
|
||||
|
||||
/obj/item/paper/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("save")
|
||||
var/in_paper = params["text"]
|
||||
if(length(in_paper) > 0 && length(in_paper) < 1000) // Sheet must have less than 1000 charaters
|
||||
info = in_paper
|
||||
finalized = TRUE // once you have writen to a sheet you cannot write again
|
||||
to_chat(usr, "You have finished your paper masterpiece!");
|
||||
ui_update()
|
||||
else
|
||||
to_chat(usr, pick("Writing block strikes again!", "You forgot to write anthing!"))
|
||||
ui_update()
|
||||
update_icon()
|
||||
. = TRUE
|
||||
|
||||
/*
|
||||
* Construction paper
|
||||
@@ -374,9 +297,8 @@
|
||||
icon_state = "scrap"
|
||||
slot_flags = null
|
||||
|
||||
/obj/item/paper/crumpled/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_blocker)
|
||||
/obj/item/paper/crumpled/update_icon_state()
|
||||
return
|
||||
|
||||
/obj/item/paper/crumpled/bloody
|
||||
icon_state = "scrap_bloodied"
|
||||
|
||||
@@ -4,7 +4,49 @@
|
||||
|
||||
/obj/item/paper/fluff/sop
|
||||
name = "paper- 'Standard Operating Procedure'"
|
||||
info = "Alert Levels:<BR>\nBlue- Emergency<BR>\n\t1. Caused by fire<BR>\n\t2. Caused by manual interaction<BR>\n\tAction:<BR>\n\t\tClose all fire doors. These can only be opened by resetting the alarm<BR>\nRed- Ejection/Self Destruct<BR>\n\t1. Caused by module operating computer.<BR>\n\tAction:<BR>\n\t\tAfter the specified time the module will eject completely.<BR>\n<BR>\nEngine Maintenance Instructions:<BR>\n\tShut off ignition systems:<BR>\n\tActivate internal power<BR>\n\tActivate orbital balance matrix<BR>\n\tRemove volatile liquids from area<BR>\n\tWear a fire suit<BR>\n<BR>\n\tAfter<BR>\n\t\tDecontaminate<BR>\n\t\tVisit medical examiner<BR>\n<BR>\nToxin Laboratory Procedure:<BR>\n\tWear a gas mask regardless<BR>\n\tGet an oxygen tank.<BR>\n\tActivate internal atmosphere<BR>\n<BR>\n\tAfter<BR>\n\t\tDecontaminate<BR>\n\t\tVisit medical examiner<BR>\n<BR>\nDisaster Procedure:<BR>\n\tFire:<BR>\n\t\tActivate sector fire alarm.<BR>\n\t\tMove to a safe area.<BR>\n\t\tGet a fire suit<BR>\n\t\tAfter:<BR>\n\t\t\tAssess Damage<BR>\n\t\t\tRepair damages<BR>\n\t\t\tIf needed, Evacuate<BR>\n\tMeteor Shower:<BR>\n\t\tActivate fire alarm<BR>\n\t\tMove to the back of ship<BR>\n\t\tAfter<BR>\n\t\t\tRepair damage<BR>\n\t\t\tIf needed, Evacuate<BR>\n\tAccidental Reentry:<BR>\n\t\tActivate fire alarms in front of ship.<BR>\n\t\tMove volatile matter to a fire proof area!<BR>\n\t\tGet a fire suit.<BR>\n\t\tStay secure until an emergency ship arrives.<BR>\n<BR>\n\t\tIf ship does not arrive-<BR>\n\t\t\tEvacuate to a nearby safe area!"
|
||||
info = {"
|
||||
Alert Levels:
|
||||
* Blue - Emergency
|
||||
* Caused by fire
|
||||
* Caused by manual interaction
|
||||
* Action: Close all fire doors. These can only be opened by resetting the alarm
|
||||
* Red- Ejection/Self Destruct
|
||||
* Caused by module operating computer.
|
||||
* Action: After the specified time the module will eject completely.
|
||||
Engine Maintenance Instructions:
|
||||
1. Shut off ignition systems:
|
||||
2. Activate internal power
|
||||
3. Activate orbital balance matrix
|
||||
4. Remove volatile liquids from area
|
||||
5. Wear a fire suit
|
||||
6. After Decontaminate Visit medical examiner
|
||||
Toxin Laboratory Procedure:
|
||||
1. Wear a gas mask regardless
|
||||
2. Get an oxygen tank.
|
||||
3. Activate internal atmosphere
|
||||
4. After Decontaminate Visit medical examiner
|
||||
Disaster Procedure:
|
||||
Fire:
|
||||
1. Activate sector fire alarm.
|
||||
2. Move to a safe area.
|
||||
3. Get a fire suit
|
||||
* After:
|
||||
1. Assess Damage
|
||||
2. Repair damages
|
||||
3. If needed, Evacuate
|
||||
Meteor Shower:
|
||||
1. Activate fire alarm
|
||||
2. Move to the back of ship
|
||||
* After
|
||||
1. Repair damage
|
||||
2. If needed, Evacuate
|
||||
Accidental Reentry:
|
||||
1. Activate fire alarms in front of ship.
|
||||
2. Move volatile matter to a fire proof area!
|
||||
3. Get a fire suit.
|
||||
4. Stay secure until an emergency ship arrives.
|
||||
5. If ship does not arrive-Evacuate to a nearby safe area!
|
||||
"};
|
||||
|
||||
/obj/item/paper/fluff/shuttles/daniel
|
||||
info = "i love daniel<br>daniel is my best friend<br><br>you are tearing me apart elise"
|
||||
@@ -150,7 +192,7 @@
|
||||
|
||||
/obj/item/paper/fluff/cogstation/mime
|
||||
name = "Au futur Mime"
|
||||
info = "Toutes mes excuses pour toute mauvaise grammaire, je ne suis pas un haut-parleur naturel Fran<61>ais et a d<> utiliser NanoTranslate. Bien que vous puissiez <20>tre m<>content de l<>emplacement de votre bureau, s<>il vous pla<6C>t comprendre que c<><63>tait le seul endroit o<> nous pourrions le mettre sans probl<62>mes de s<>curit<69> et/ou CentClown se plaindre <20> ce sujet. Nous nous excusons <20>galement pour l<>absence d<>une zone de performance d<>di<64>e, mais nous esp<73>rons que vous accorder un acc<63>s <20> l<>entretien compensera. <BR>\n<BR>\n<I>-C. Donnelly<I> <BR>\n<BR>\nAnalyste Architectural"
|
||||
info = "Toutes mes excuses pour toute mauvaise grammaire, je ne suis pas un haut-parleur naturel Fran<61>ais et a d<> utiliser NanoTranslate. Bien que vous puissiez <20>tre m<>content de l<>emplacement de votre bureau, s<>il vous pla<6C>t comprendre que c<><63>tait le seul endroit o<> nous pourrions le mettre sans probl<62>mes de s<>curit<69> et/ou CentClown se plaindre <20> ce sujet. Nous nous excusons <20>galement pour l<>absence d<>une zone de performance d<>di<64>e, mais nous esp<73>rons que vous accorder un acc<63>s <20> l<>entretien compensera. <BR>\n<BR>\n<I>-C. Donnelly<I> <BR>\n<BR>\nAnalyste Architectural"
|
||||
|
||||
/obj/item/paper/fluff/cogstation/bsrb
|
||||
name = "Message from the NTBSRB"
|
||||
|
||||
@@ -85,9 +85,8 @@
|
||||
P = new papertype(src)
|
||||
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
|
||||
if(prob(30))
|
||||
P.info = "<font face=\"[CRAYON_FONT]\" color=\"red\"><b>HONK HONK HONK HONK HONK HONK HONK<br>HOOOOOOOOOOOOOOOOOOOOOONK<br>APRIL FOOLS</b></font>"
|
||||
P.info = "*HONK HONK HONK HONK HONK HONK HONK<br>HOOOOOOOOOOOOOOOOOOOOOONK*\n*APRIL FOOLS*\n"
|
||||
P.rigged = 1
|
||||
P.updateinfolinks()
|
||||
|
||||
P.add_fingerprint(user)
|
||||
P.forceMove(user.loc)
|
||||
|
||||
@@ -122,11 +122,12 @@
|
||||
eyes.applyOrganDamage(rand(6,8))
|
||||
H.DefaultCombatKnockdown(40)
|
||||
H.emote("scream")
|
||||
|
||||
|
||||
/* Starts an infinite loop
|
||||
/obj/item/paper/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Alt-click [src] to fold it into a paper plane.</span>"
|
||||
|
||||
*/
|
||||
/obj/item/paper/AltClick(mob/living/carbon/user, obj/item/I)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user), NO_TK))
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
/obj/machinery/photocopier/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "Photocopier<BR><BR>"
|
||||
var/list/dat = list("Photocopier<BR><BR>")
|
||||
if(copy || photocopy || doccopy || (ass && (ass.loc == src.loc)))
|
||||
dat += "<a href='byond://?src=[REF(src)];remove=1'>Remove Paper</a><BR>"
|
||||
if(toner)
|
||||
@@ -48,7 +48,7 @@
|
||||
dat += "Current toner level: [toner]"
|
||||
if(!toner)
|
||||
dat +="<BR>Please insert a new toner cartridge!"
|
||||
user << browse(dat, "window=copier")
|
||||
user << browse(dat.Join(""), "window=copier")
|
||||
onclose(user, "copier")
|
||||
|
||||
/obj/machinery/photocopier/Topic(href, href_list)
|
||||
@@ -65,29 +65,18 @@
|
||||
if(C)
|
||||
copy_as_paper = 0
|
||||
if(copy_as_paper)
|
||||
var/obj/item/paper/c = new /obj/item/paper (loc)
|
||||
var/obj/item/paper/c
|
||||
if(length(copy.info) > 0) //Only print and add content if the copied doc has words on it
|
||||
c = copy.copy(loc)
|
||||
if(toner > 10) //lots of toner, make it dark
|
||||
c.info = "<font color = #101010>"
|
||||
c.pen_color = "#101010"
|
||||
else //no toner? shitty copies for you!
|
||||
c.info = "<font color = #808080>"
|
||||
var/copied = copy.info
|
||||
copied = replacetext(copied, "<font face=\"[PEN_FONT]\" color=", "<font face=\"[PEN_FONT]\" nocolor=") //state of the art techniques in action
|
||||
copied = replacetext(copied, "<font face=\"[CRAYON_FONT]\" color=", "<font face=\"[CRAYON_FONT]\" nocolor=") //This basically just breaks the existing color tag, which we need to do because the innermost tag takes priority.
|
||||
c.info += copied
|
||||
c.info += "</font>"
|
||||
c.name = copy.name
|
||||
c.fields = copy.fields
|
||||
c.update_icon()
|
||||
c.updateinfolinks()
|
||||
c.stamps = copy.stamps
|
||||
if(copy.stamped)
|
||||
c.stamped = copy.stamped.Copy()
|
||||
c.copy_overlays(copy, TRUE)
|
||||
c.pen_color = "#808080"
|
||||
toner--
|
||||
else
|
||||
c = new(loc) // shoot out blank sheet of paper
|
||||
busy = TRUE
|
||||
sleep(15)
|
||||
busy = FALSE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
else
|
||||
break
|
||||
updateUsrDialog()
|
||||
@@ -96,8 +85,7 @@
|
||||
if(toner >= 5 && !busy && photocopy) //Was set to = 0, but if there was say 3 toner left and this ran, you would get -2 which would be weird for ink
|
||||
new /obj/item/photo (loc, photocopy.picture.Copy(greytoggle == "Greyscale"? TRUE : FALSE))
|
||||
busy = TRUE
|
||||
sleep(15)
|
||||
busy = FALSE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
else
|
||||
break
|
||||
else if(doccopy)
|
||||
@@ -106,40 +94,35 @@
|
||||
new /obj/item/documents/photocopy(loc, doccopy)
|
||||
toner-= 6 // the sprite shows 6 papers, yes I checked
|
||||
busy = TRUE
|
||||
sleep(15)
|
||||
busy = FALSE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
else
|
||||
break
|
||||
updateUsrDialog()
|
||||
else if(ass) //ASS COPY. By Miauw
|
||||
for(var/i = 0, i < copies, i++)
|
||||
var/icon/temp_img
|
||||
if(ishuman(ass) && (ass.get_item_by_slot(SLOT_W_UNIFORM) || ass.get_item_by_slot(SLOT_WEAR_SUIT)))
|
||||
if(ishuman(ass) && (ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) || ass.get_item_by_slot(ITEM_SLOT_OCLOTHING)))
|
||||
to_chat(usr, "<span class='notice'>You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "[ass.p_their()]"] clothes on.</span>" )
|
||||
break
|
||||
else if(toner >= 5 && !busy && check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on.
|
||||
if(isalienadult(ass) || istype(ass, /mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro.
|
||||
temp_img = icon('icons/ass/assalien.png')
|
||||
else if(ishuman(ass)) //Suit checks are in check_ass
|
||||
var/mob/living/carbon/human/H = ass
|
||||
if(H.dna.features["body_model"] == FEMALE)
|
||||
temp_img = icon('icons/ass/assfemale.png')
|
||||
else
|
||||
temp_img = icon('icons/ass/assmale.png')
|
||||
temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png')
|
||||
else if(isdrone(ass)) //Drones are hot
|
||||
temp_img = icon('icons/ass/assdrone.png')
|
||||
else
|
||||
break
|
||||
var/obj/item/photo/p = new /obj/item/photo (loc)
|
||||
p.pixel_x = rand(-10, 10)
|
||||
p.pixel_y = rand(-10, 10)
|
||||
p.picture = new(null, "You see [ass]'s ass on the photo.", temp_img)
|
||||
p.picture.psize_x = 128
|
||||
p.picture.psize_y = 128
|
||||
p.update_icon()
|
||||
toner -= 5
|
||||
busy = TRUE
|
||||
sleep(15)
|
||||
var/obj/item/photo/p = new /obj/item/photo (loc)
|
||||
var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img)
|
||||
p.pixel_x = rand(-10, 10)
|
||||
p.pixel_y = rand(-10, 10)
|
||||
toEmbed.psize_x = 128
|
||||
toEmbed.psize_y = 128
|
||||
p.set_picture(toEmbed, TRUE, TRUE)
|
||||
toner -= 5
|
||||
busy = FALSE
|
||||
else
|
||||
break
|
||||
@@ -179,8 +162,7 @@
|
||||
photo.pixel_y = rand(-10, 10)
|
||||
toner -= 5 //AI prints color pictures only, thus they can do it more efficiently
|
||||
busy = TRUE
|
||||
sleep(15)
|
||||
busy = FALSE
|
||||
addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS)
|
||||
updateUsrDialog()
|
||||
else if(href_list["colortoggle"])
|
||||
if(greytoggle == "Greyscale")
|
||||
@@ -189,9 +171,13 @@
|
||||
greytoggle = "Greyscale"
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/photocopier/proc/reset_busy()
|
||||
busy = FALSE
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/photocopier/proc/do_insertion(obj/item/O, mob/user)
|
||||
O.forceMove(src)
|
||||
to_chat(user, "<span class ='notice'>You insert [O] into [src].</span>")
|
||||
to_chat(user, "<span class='notice'>You insert [O] into [src].</span>")
|
||||
flick("photocopier1", src)
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -256,10 +242,10 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/photocopier/obj_break(damage_flag)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
if(toner > 0)
|
||||
new /obj/effect/decal/cleanable/oil(get_turf(src))
|
||||
toner = 0
|
||||
. = ..()
|
||||
if(. && toner > 0)
|
||||
new /obj/effect/decal/cleanable/oil(get_turf(src))
|
||||
toner = 0
|
||||
|
||||
/obj/machinery/photocopier/MouseDrop_T(mob/target, mob/user)
|
||||
check_ass() //Just to make sure that you can re-drag somebody onto it after they moved off.
|
||||
@@ -267,7 +253,7 @@
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
if(target == user)
|
||||
user.visible_message("[user] starts climbing onto the photocopier!", "<span class='notice'>You start climbing onto the photocopier...</span>")
|
||||
user.visible_message("<span class='notice'>[user] starts climbing onto the photocopier!</span>", "<span class='notice'>You start climbing onto the photocopier...</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] starts putting [target] onto the photocopier!</span>", "<span class='notice'>You start putting [target] onto the photocopier...</span>")
|
||||
|
||||
@@ -276,7 +262,7 @@
|
||||
return
|
||||
|
||||
if(target == user)
|
||||
user.visible_message("[user] climbs onto the photocopier!", "<span class='notice'>You climb onto the photocopier.</span>")
|
||||
user.visible_message("<span class='notice'>[user] climbs onto the photocopier!</span>", "<span class='notice'>You climb onto the photocopier.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] puts [target] onto the photocopier!</span>", "<span class='notice'>You put [target] onto the photocopier.</span>")
|
||||
|
||||
@@ -302,7 +288,7 @@
|
||||
updateUsrDialog()
|
||||
return 0
|
||||
else if(ishuman(ass))
|
||||
if(!ass.get_item_by_slot(SLOT_W_UNIFORM) && !ass.get_item_by_slot(SLOT_WEAR_SUIT))
|
||||
if(!ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) && !ass.get_item_by_slot(ITEM_SLOT_OCLOTHING))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
@@ -394,16 +394,13 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
||||
// Misc
|
||||
|
||||
/obj/item/paper/guides/jobs/engi/gravity_gen
|
||||
name = "paper- 'Generate your own gravity!'"
|
||||
info = {"<h1>Gravity Generator Instructions For Dummies</h1>
|
||||
<p>Surprisingly, gravity isn't that hard to make! All you have to do is inject deadly radioactive minerals into a ball of
|
||||
energy and you have yourself gravity! You can turn the machine on or off when required but you must remember that the generator
|
||||
will EMIT RADIATION when charging or discharging, you can tell it is charging or discharging by the noise it makes, so please WEAR PROTECTIVE CLOTHING.</p>
|
||||
<br>
|
||||
<h3>It blew up!</h3>
|
||||
<p>Don't panic! The gravity generator was designed to be easily repaired. If, somehow, the sturdy framework did not survive then
|
||||
please proceed to panic; otherwise follow these steps.</p><ol>
|
||||
<li>Secure the screws of the framework with a screwdriver.</li>
|
||||
<li>Mend the damaged framework with a welding tool.</li>
|
||||
<li>Add additional plasteel plating.</li>
|
||||
<li>Secure the additional plating with a wrench.</li></ol>"}
|
||||
info = {"
|
||||
# Gravity Generator Instructions For Dummies
|
||||
Surprisingly, gravity isn't that hard to make! All you have to do is inject deadly radioactive minerals into a ball of energy and you have yourself gravity! You can turn the machine on or off when required but you must remember that the generator will EMIT RADIATION when charging or discharging, you can tell it is charging or discharging by the noise it makes, so please WEAR PROTECTIVE CLOTHING.</p>
|
||||
### It blew up!
|
||||
Don't panic! The gravity generator was designed to be easily repaired. If, somehow, the sturdy framework did not survive then please proceed to panic; otherwise follow these steps.
|
||||
1. Secure the screws of the framework with a screwdriver.
|
||||
2. Mend the damaged framework with a welding tool.
|
||||
3. Add additional plasteel plating.
|
||||
4. Secure the additional plating with a wrench.
|
||||
"}
|
||||
|
||||
@@ -481,8 +481,12 @@
|
||||
//
|
||||
|
||||
/obj/item/paper/guides/jobs/engi/solars
|
||||
name = "paper- 'Going green! Setup your own solar array instructions.'"
|
||||
info = "<h1>Welcome</h1><p>At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or plasma! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.</p><p>You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!</p><p>Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the sun's movements and to send commands to the solar panels to change direction with the sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.</p><p>Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.</p><p>That's all to it, be safe, be green!</p>"
|
||||
info = {"
|
||||
# Welcome!
|
||||
At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or plasma! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.
|
||||
You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!</p><p>Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the sun's movements and to send commands to the solar panels to change direction with the sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.
|
||||
Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.</p><p>That's all to it, be safe, be green!
|
||||
"}
|
||||
|
||||
#undef SOLAR_GEN_RATE
|
||||
#undef OCCLUSION_DISTANCE
|
||||
|
||||
@@ -2,4 +2,20 @@
|
||||
|
||||
/obj/item/paper/fluff/ruins/djstation
|
||||
name = "paper - 'DJ Listening Outpost'"
|
||||
info = "<B>Welcome new owner!</B><BR><BR>You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio frequencies. Here is a step by step guide to start listening in on those saucy radio channels:<br><ol><li>Equip yourself with a multitool</li><li>Use the multitool on the relay.</li><li>Turn it on. It has already been configured for you to listen on.</li></ol> Simple as that. Now to listen to the private channels, you'll have to configure the intercoms. They are located on the front desk. Here is a list of frequencies for you to listen on.<br><ul><li>145.9 - Common Channel</li><li>144.7 - Private AI Channel</li><li>135.9 - Security Channel</li><li>135.7 - Engineering Channel</li><li>135.5 - Medical Channel</li><li>135.3 - Command Channel</li><li>135.1 - Science Channel</li><li>134.9 - Service Channel</li><li>134.7 - Supply Channel</li>"
|
||||
info = {"
|
||||
**Welcome new owner!**
|
||||
You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio frequencies. Here is a step by step guide to start listening in on those saucy radio channels:
|
||||
1. Equip yourself with a multitool
|
||||
2. Use the multitool on the relay.
|
||||
3. Turn it on. It has already been configured for you to listen on.
|
||||
Simple as that. Now to listen to the private channels, you'll have to configure the intercoms. They are located on the front desk. Here is a list of frequencies for you to listen on.
|
||||
* 145.9 - Common Channel
|
||||
* 144.7 - Private AI Channel
|
||||
* 135.9 - Security Channel
|
||||
* 135.7 - Engineering Channel
|
||||
* 135.5 - Medical Channel
|
||||
* 135.3 - Command Channel
|
||||
* 135.1 - Science Channel
|
||||
* 134.9 - Service Channel
|
||||
* 134.7 - Supply Channel
|
||||
"}
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
/obj/item/paper/fluff/ruins/thederelict/syndie_mission
|
||||
name = "Mission Objectives"
|
||||
info = "The Syndicate have cunningly disguised a Syndicate Uplink as your PDA. Simply enter the code \"678 Bravo\" into the ringtone select to unlock its hidden features. <br><br><b>Objective #1</b>. Kill the God damn AI in a fire blast that it rocks the station. <b>Success!</b> <br><b>Objective #2</b>. Escape alive. <b>Failed.</b>"
|
||||
info = "The Syndicate have cunningly disguised a Syndicate Uplink as your PDA. Simply enter the code \"678 Bravo\" into the ringtone select to unlock its hidden features.\n \n__Objective #1__. Kill the God damn AI in a fire blast that it rocks the station. __Success!__ \n \n__Objective #2__. Escape alive. __Failed.__"
|
||||
|
||||
/obj/item/paper/fluff/ruins/thederelict/nukie_objectives
|
||||
name = "Objectives of a Nuclear Operative"
|
||||
info = "<b>Objective #1</b>: Destroy the station with a nuclear device."
|
||||
info = "__Objective #1__: Destroy the station with a nuclear device."
|
||||
|
||||
/obj/item/paper/crumpled/bloody/ruins/thederelict/unfinished
|
||||
name = "unfinished paper scrap"
|
||||
desc = "Looks like someone started shakily writing a will in space common, but were interrupted by something bloody..."
|
||||
info = "I, Victor Belyakov, do hereby leave my _- "
|
||||
info = "__Objectives #1__: Find out what is hidden in Kosmicheskaya Stantsiya 13s Vault"
|
||||
|
||||
|
||||
/// Vault controller for use on the derelict/KS13.
|
||||
|
||||
@@ -474,29 +474,29 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
|
||||
/obj/item/paper/crumpled/docslogs/Initialize()
|
||||
. = ..()
|
||||
GLOB.hhmysteryRoomNumber = rand(1, SHORT_REAL_LIMIT)
|
||||
info = {"<h4><center>Research Logs</center></h4>
|
||||
I might just be onto something here!<br>
|
||||
The strange space-warping properties of bluespace have been known about for awhile now, but I might be on the verge of discovering a new way of harnessing it.<br>
|
||||
It's too soon to say for sure, but this might be the start of something quite important!<br>
|
||||
I'll be sure to log any major future breakthroughs. This might be a lot more than I can manage on my own, perhaps I should hire that secretary after all...<br>
|
||||
<h4>Breakthrough!</h4>
|
||||
I can't believe it, but I did it! Just when I was certain it couldn't be done, I made the final necessary breakthrough.<br>
|
||||
Exploiting the effects of space dilation caused by specific bluespace structures combined with a precise use of geometric calculus, I've discovered a way to correlate an infinite amount of space within a finite area!<br>
|
||||
While the potential applications are endless, I utilized it in quite a nifty way so far by designing a system that recursively constructs subspace rooms and spatially links them to any of the infinite infinitesimally distinct points on the spheres surface.<br>
|
||||
I call it: Hilbert's Hotel!<br>
|
||||
<h4>Goodbye</h4>
|
||||
I can't take this anymore. I know what happens next, and the fear of what is coming leaves me unable to continue working.<br>
|
||||
Any fool in my field has heard the stories. It's not that I didn't believe them, it's just... I guess I underestimated the importance of my own research...<br>
|
||||
Robert has reported a further increase in frequency of the strange, prying visitors who ask questions they have no business asking. I've requested him to keep everything on strict lockdown and have permanently dismissed all other assistants.<br>
|
||||
I've also instructed him to use the encryption method we discussed for any important quantitative data. The poor lad... I don't think he truly understands what he's gotten himself into...<br>
|
||||
It's clear what happens now. One day they'll show up uninvited, and claim my research as their own, leaving me as nothing more than a bullet ridden corpse floating in space.<br>
|
||||
I can't stick around to the let that happen.<br>
|
||||
I'm escaping into the very thing that brought all this trouble to my doorstep in the first place - my hotel.<br>
|
||||
I'll be in <u>[uppertext(num2hex(GLOB.hhmysteryRoomNumber, 0))]</u> (That will make sense to anyone who should know)<br>
|
||||
I'm sorry that I must go like this. Maybe one day things will be different and it will be safe to return... maybe...<br>
|
||||
Goodbye<br>
|
||||
<br>
|
||||
<i>Doctor Hilbert</i>"}
|
||||
info = {"
|
||||
### Research Logs
|
||||
I might just be onto something here!
|
||||
The strange space-warping properties of bluespace have been known about for awhile now, but I might be on the verge of discovering a new way of harnessing it.
|
||||
It's too soon to say for sure, but this might be the start of something quite important!
|
||||
I'll be sure to log any major future breakthroughs. This might be a lot more than I can manage on my own, perhaps I should hire that secretary after all...
|
||||
### Breakthrough!
|
||||
I can't believe it, but I did it! Just when I was certain it couldn't be done, I made the final necessary breakthrough.
|
||||
Exploiting the effects of space dilation caused by specific bluespace structures combined with a precise use of geometric calculus, I've discovered a way to correlate an infinite amount of space within a finite area!
|
||||
While the potential applications are endless, I utilized it in quite a nifty way so far by designing a system that recursively constructs subspace rooms and spatially links them to any of the infinite infinitesimally distinct points on the spheres surface.
|
||||
I call it: Hilbert's Hotel!
|
||||
<h4>Goodbye</h4>
|
||||
I can't take this anymore. I know what happens next, and the fear of what is coming leaves me unable to continue working.
|
||||
Any fool in my field has heard the stories. It's not that I didn't believe them, it's just... I guess I underestimated the importance of my own research...
|
||||
Robert has reported a further increase in frequency of the strange, prying visitors who ask questions they have no business asking. I've requested him to keep everything on strict lockdown and have permanently dismissed all other assistants.
|
||||
I've also instructed him to use the encryption method we discussed for any important quantitative data. The poor lad... I don't think he truly understands what he's gotten himself into...
|
||||
It's clear what happens now. One day they'll show up uninvited, and claim my research as their own, leaving me as nothing more than a bullet ridden corpse floating in space.
|
||||
I can't stick around to the let that happen.
|
||||
I'm escaping into the very thing that brought all this trouble to my doorstep in the first place - my hotel.
|
||||
I'll be in <u>[uppertext(num2hex(GLOB.hhmysteryRoomNumber, 0))]</u> (That will make sense to anyone who should know)
|
||||
I'm sorry that I must go like this. Maybe one day things will be different and it will be safe to return... maybe...
|
||||
Goodbye
|
||||
_Doctor Hilbert_"}
|
||||
|
||||
/obj/item/paper/crumpled/robertsworkjournal
|
||||
name = "Work Journal"
|
||||
@@ -526,16 +526,15 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
|
||||
|
||||
/obj/item/paper/crumpled/bloody/docsdeathnote
|
||||
name = "note"
|
||||
info = {"This is it isn't it?<br>
|
||||
No one's coming to help, that much has become clear.<br>
|
||||
Sure, it's lonely, but do I have much choice? At least I brought the analyzer with me, they shouldn't be able to find me without it.<br>
|
||||
Who knows who's waiting for me out there. Its either die out there in their hands, or die a slower, slightly more comfortable death in here.<br>
|
||||
Everyday I can feel myself slipping away more and more, both physically and mentally. Who knows what happens now...<br>
|
||||
Heh, so it's true then, this must be the inescapable path of all great minds... so be it then.<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<i>Choose a room, and enter the sphere<br>
|
||||
Lay your head to rest, it soon becomes clear<br>
|
||||
There's always more room around every bend<br>
|
||||
Not all that's countable has an end...<i>"}
|
||||
info = {"
|
||||
This is it isn't it?
|
||||
No one's coming to help, that much has become clear.
|
||||
Sure, it's lonely, but do I have much choice? At least I brought the analyzer with me, they shouldn't be able to find me without it.
|
||||
Who knows who's waiting for me out there. Its either die out there in their hands, or die a slower, slightly more comfortable death in here.
|
||||
Everyday I can feel myself slipping away more and more, both physically and mentally. Who knows what happens now...
|
||||
Heh, so it's true then, this must be the inescapable path of all great minds... so be it then.
|
||||
_Choose a room, and enter the sphere
|
||||
Lay your head to rest, it soon becomes clear
|
||||
There's always more room around every bend
|
||||
Not all that's countable has an end..._
|
||||
"}
|
||||
|
||||
@@ -38,8 +38,15 @@
|
||||
|
||||
/obj/item/paper/fluff/ruins/oldstation/protoinv
|
||||
name = "Laboratory Inventory"
|
||||
info = "<b>*Inventory*</b><br><br>(1) Prototype Hardsuit<br><br>(1)Health Analyser<br><br>(1)Prototype Energy Gun<br><br>(1)Singularity Generation Disk<br><br><b>DO NOT REMOVE WITHOUT \
|
||||
THE CAPTAIN AND RESEARCH DIRECTOR'S AUTHORISATION</b>"
|
||||
info = {"
|
||||
**Inventory**
|
||||
* (1) Prototype Hardsuit
|
||||
* (1)Health Analyser
|
||||
* (1)Prototype Energy Gun
|
||||
* (1)Singularity Generation Disk
|
||||
__DO NOT REMOVE WITHOUT HE CAPTAIN AND RESEARCH DIRECTOR'S AUTHORISATION__
|
||||
"}
|
||||
|
||||
|
||||
/obj/item/paper/fluff/ruins/oldstation/report
|
||||
name = "Crew Reawakening Report"
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/////////// originalcontent items
|
||||
|
||||
/obj/item/paper/crumpled/ruins/originalcontent
|
||||
desc = "<i>Various scrawled out drawings and sketches reside on the paper, apparently he didn't much care for these drawings.</i>"
|
||||
desc = "_Various scrawled out drawings and sketches reside on the paper, apparently he didn't much care for these drawings._"
|
||||
|
||||
/obj/item/paper/pamphlet/ruin/originalcontent
|
||||
icon = 'icons/obj/fluff.dmi'
|
||||
|
||||
/obj/item/paper/pamphlet/ruin/originalcontent/stickman
|
||||
name = "Painting - 'BANG'"
|
||||
info = "<i>This picture depicts a crudely-drawn stickman firing a crudely-drawn gun.</i>"
|
||||
info = "_This picture depicts a crudely-drawn stickman firing a crudely-drawn gun._"
|
||||
icon_state = "painting4"
|
||||
|
||||
/obj/item/paper/pamphlet/ruin/originalcontent/treeside
|
||||
name = "Painting - 'Treeside'"
|
||||
info = "<i>This picture depicts a sunny day on a lush hillside, set under a shaded tree.</i>"
|
||||
info = "_This picture depicts a sunny day on a lush hillside, set under a shaded tree._"
|
||||
icon_state = "painting1"
|
||||
|
||||
/obj/item/paper/pamphlet/ruin/originalcontent/pennywise
|
||||
name = "Painting - 'Pennywise'"
|
||||
info = "<i>This picture depicts a smiling clown. Something doesn't feel right about this..</i>"
|
||||
info = "_This picture depicts a smiling clown. Something doesn't feel right about this.._"
|
||||
icon_state = "painting3"
|
||||
|
||||
/obj/item/paper/pamphlet/ruin/originalcontent/yelling
|
||||
name = "Painting - 'Hands-On-Face'"
|
||||
info = "<i>This picture depicts a man yelling on a bridge for no apparent reason.</i>"
|
||||
info = "_This picture depicts a man yelling on a bridge for no apparent reason._"
|
||||
icon_state = "painting2"
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
|
||||
/obj/item/paper/fluff/ruins/spacehotel/notice
|
||||
name = "!NOTICE!"
|
||||
info = "<bold>!NOTICE!</bold><br><br><center>We are expecting arriving guests soon from a nearby station! Stay sharp and make sure guests enjoy their time spent here. Don't think you can sneak off while they're here, either.</center>"
|
||||
info = "__!NOTICE!__\n \nWe are expecting arriving guests soon from a nearby station! Stay sharp and make sure guests enjoy their time spent here. Don't think you can sneak off while they're here, either."
|
||||
|
||||
/obj/item/paper/pamphlet/ruin/spacehotel
|
||||
name = "hotel pamphlet"
|
||||
info = "<center><b>The Twin Nexus Hotel</center></b><br><center><i>A place of Sanctuary</i></center><br><br><center>Welcome to The Twin-Nexus Hotel, \[insert name here]! The loyal staff stride to their best effort to cater for the best possible experience for all space(wo)men! If you have any questions or comments, please ask one of our on-board staff for more information.</center>"
|
||||
|
||||
info = "__The Twin Nexus Hotel__\n*A place of Sanctuary*\n \nWelcome to The Twin-Nexus Hotel, \[insert name here]! The loyal staff strive to their best effort to cater for the best possible experience for all space(wo)men! If you have any questions or comments, please ask one of our on-board staff for more information."
|
||||
|
||||
|
||||
188
tgui/packages/tgui/components/TextArea.js
Normal file
188
tgui/packages/tgui/components/TextArea.js
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Aleksej Komarov
|
||||
* @author Original Aleksej Komarov
|
||||
* @author Changes Warlockd (https://github.com/warlockd)
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
|
||||
import { classes, isFalsy } from 'common/react';
|
||||
import { Component, createRef } from 'inferno';
|
||||
import { Box } from './Box';
|
||||
|
||||
|
||||
const toInputValue = value => {
|
||||
if (isFalsy(value)) {
|
||||
return '';
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
export class TextArea extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.textareaRef = createRef();
|
||||
this.fillerRef = createRef();
|
||||
this.state = {
|
||||
editing: false,
|
||||
};
|
||||
const {
|
||||
dontUseTabForIndent = false,
|
||||
} = props;
|
||||
// found this hack that expands the text area without
|
||||
// having to hard set rows all the time
|
||||
// there has GOT to be a better way though
|
||||
this.autoresize = () => {
|
||||
if (this.fillerRef && this.textareaRef) {
|
||||
// this.fillerRef.current.innerHTML =
|
||||
// this.textareaRef.current.value.replace(/\n/g, '<br/>');
|
||||
}
|
||||
};
|
||||
this.handleOnInput = e => {
|
||||
const { editing } = this.state;
|
||||
const { onInput } = this.props;
|
||||
if (!editing) {
|
||||
this.setEditing(true);
|
||||
}
|
||||
if (onInput) {
|
||||
onInput(e, e.target.value);
|
||||
}
|
||||
this.autoresize();
|
||||
};
|
||||
this.handleOnChange = e => {
|
||||
const { editing } = this.state;
|
||||
const { onChange } = this.props;
|
||||
if (editing) {
|
||||
this.setEditing(false);
|
||||
}
|
||||
if (onChange) {
|
||||
onChange(e, e.target.value);
|
||||
}
|
||||
this.autoresize();
|
||||
};
|
||||
this.handleKeyPress = e => {
|
||||
const { editing } = this.state;
|
||||
const { onKeyPress } = this.props;
|
||||
if (!editing) {
|
||||
this.setEditing(true);
|
||||
}
|
||||
if (onKeyPress) {
|
||||
onKeyPress(e, e.target.value);
|
||||
}
|
||||
this.autoresize();
|
||||
};
|
||||
this.handleKeyDown = e => {
|
||||
const { editing } = this.state;
|
||||
const { onKeyDown } = this.props;
|
||||
if (!editing) {
|
||||
this.setEditing(true);
|
||||
}
|
||||
if (!dontUseTabForIndent) {
|
||||
const keyCode = e.keyCode || e.which;
|
||||
if (keyCode === 9) {
|
||||
e.preventDefault();
|
||||
const s = e.target.selectionStart;
|
||||
e.target.value
|
||||
= e.target.value.substring(0, e.target.selectionStart)
|
||||
+ "\t"
|
||||
+ e.target.value.substring(e.target.selectionEnd);
|
||||
e.target.selectionEnd = s +1;
|
||||
}
|
||||
}
|
||||
|
||||
if (onKeyDown) {
|
||||
onKeyDown(e, e.target.value);
|
||||
}
|
||||
this.autoresize();
|
||||
};
|
||||
this.handleFocus = e => {
|
||||
const { editing } = this.state;
|
||||
if (!editing) {
|
||||
this.setEditing(true);
|
||||
}
|
||||
};
|
||||
this.handleBlur = e => {
|
||||
const { editing } = this.state;
|
||||
const { onChange } = this.props;
|
||||
if (editing) {
|
||||
this.setEditing(false);
|
||||
if (onChange) {
|
||||
onChange(e, e.target.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const nextValue = this.props.value;
|
||||
const input = this.textareaRef.current;
|
||||
if (input) {
|
||||
input.value = toInputValue(nextValue);
|
||||
this.autoresize();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { editing } = this.state;
|
||||
const prevValue = prevProps.value;
|
||||
const nextValue = this.props.value;
|
||||
const input = this.textareaRef.current;
|
||||
if (input && !editing && prevValue !== nextValue) {
|
||||
input.value = toInputValue(nextValue);
|
||||
this.autoresize();
|
||||
}
|
||||
}
|
||||
|
||||
setEditing(editing) {
|
||||
this.setState({ editing });
|
||||
}
|
||||
getValue() {
|
||||
return this.textareaRef.current && this.textareaRef.current.value;
|
||||
}
|
||||
render() {
|
||||
const { props } = this;
|
||||
// Input only props
|
||||
const {
|
||||
onChange,
|
||||
onKeyDown,
|
||||
onKeyPress,
|
||||
onInput,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onEnter,
|
||||
value,
|
||||
placeholder,
|
||||
...boxProps
|
||||
} = this.props;
|
||||
// Box props
|
||||
const {
|
||||
className,
|
||||
fluid,
|
||||
...rest
|
||||
} = boxProps;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'TextArea',
|
||||
fluid && 'TextArea--fluid',
|
||||
className,
|
||||
|
||||
])}
|
||||
{...rest}>
|
||||
|
||||
<textarea
|
||||
value={value}
|
||||
ref={this.textareaRef}
|
||||
className="TextArea__textarea"
|
||||
placeholder={placeholder}
|
||||
onChange={this.handleOnChange}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onKeyPress={this.handleKeyPress}
|
||||
onInput={this.handleOnInput}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -24,3 +24,4 @@ export { Slider } from './Slider';
|
||||
export { Table } from './Table';
|
||||
export { Tabs } from './Tabs';
|
||||
export { Tooltip } from './Tooltip';
|
||||
export { TextArea } from './TextArea';
|
||||
|
||||
@@ -18,6 +18,7 @@ import './styles/themes/hackerman.scss';
|
||||
import './styles/themes/retro.scss';
|
||||
import './styles/themes/syndicate.scss';
|
||||
import './styles/themes/clockcult.scss';
|
||||
import './styles/themes/paper.scss';
|
||||
|
||||
import { loadCSS } from 'fg-loadcss';
|
||||
import { render } from 'inferno';
|
||||
|
||||
153
tgui/packages/tgui/interfaces/PaperSheet.js
Normal file
153
tgui/packages/tgui/interfaces/PaperSheet.js
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 WarlockD (https://github.com/warlockd)
|
||||
* @author Original WarlockD (https://github.com/warlockd)
|
||||
* @author Changes stylemistake
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Tabs, Box, Flex, Button, TextArea } from '../components';
|
||||
import { useBackend, useSharedState, useLocalState } from '../backend';
|
||||
import { Window } from '../layouts';
|
||||
// import marked from 'marked';
|
||||
import marked from 'marked';
|
||||
import DOMPurify from 'dompurify';
|
||||
// There is a sanatize option in marked but they say its deprecated.
|
||||
// Might as well use a proper one then
|
||||
|
||||
import { createLogger } from '../logging';
|
||||
import { Fragment } from 'inferno';
|
||||
|
||||
const logger = createLogger('PaperSheet');
|
||||
|
||||
const run_marked_default = value => {
|
||||
const sanitizer = DOMPurify.sanitize;
|
||||
// too much?
|
||||
// return sanitizer(marked(sanitizer(value),
|
||||
// { breaks: true, smartypants: true });
|
||||
return sanitizer(marked(value,
|
||||
{ breaks: true, smartypants: true }));
|
||||
};
|
||||
|
||||
const PaperSheetView = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const {
|
||||
paper_color = "white",
|
||||
pen_color = "black",
|
||||
text = '',
|
||||
} = data;
|
||||
const {
|
||||
value = text || '',
|
||||
...rest
|
||||
} = props;
|
||||
// We use this for caching so we don't keep refreshing it each time
|
||||
const [marked_text, setMarkedText] = useLocalState(context, 'marked_text',
|
||||
{ __html: run_marked_default(value) });
|
||||
return (
|
||||
<Box
|
||||
backgroundColor={paper_color}
|
||||
color={pen_color}
|
||||
{...rest}
|
||||
dangerouslySetInnerHTML={marked_text} />
|
||||
);
|
||||
};
|
||||
|
||||
const PaperSheetEdit = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const [text, setText] = useLocalState(context, 'text', data.text || '');
|
||||
const [marked_text, setMarkedText] = useLocalState(context, 'marked_text',
|
||||
{ __html: run_marked_default(text) });
|
||||
const [
|
||||
previewSelected,
|
||||
setPreviewSelected,
|
||||
] = useLocalState(context, 'preview', "Preview");
|
||||
const {
|
||||
paper_color = "white",
|
||||
pen_color = "black",
|
||||
} = data;
|
||||
const onInputHandler = (e, value) => {
|
||||
if (value.length < 1000) {
|
||||
setText(value);
|
||||
setMarkedText({ __html: run_marked_default(value) });
|
||||
} else {
|
||||
setText(value.substr(1000));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="column">
|
||||
<Flex.Item>
|
||||
<Tabs>
|
||||
<Tabs.Tab
|
||||
key="marked_edit"
|
||||
textColor={'black'}
|
||||
backgroundColor={previewSelected === "Edit" ? "grey" : "white"}
|
||||
selected={previewSelected === "Edit"}
|
||||
onClick={() => setPreviewSelected("Edit")}>
|
||||
Edit
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
key="marked_preview"
|
||||
textColor={'black'}
|
||||
backgroundColor={previewSelected === "Preview" ? "grey" : "white"}
|
||||
selected={previewSelected === "Preview"}
|
||||
onClick={() => setPreviewSelected("Preview")}>
|
||||
Preview
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
key="marked_done"
|
||||
textColor={'black'}
|
||||
backgroundColor={previewSelected === "confirm"
|
||||
? "red"
|
||||
: previewSelected === "save"
|
||||
? "grey"
|
||||
: "white"}
|
||||
selected={previewSelected === "confirm"
|
||||
|| previewSelected === "save"}
|
||||
onClick={() => {
|
||||
if (previewSelected === "confirm") {
|
||||
act('save', { text });
|
||||
} else {
|
||||
setPreviewSelected("confirm");
|
||||
}
|
||||
}}>
|
||||
{ previewSelected === "confirm" ? "confirm" : "save" }
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
</Flex.Item>
|
||||
<Flex.Item
|
||||
grow={1}
|
||||
basis={1}>
|
||||
{previewSelected === "Edit" && (
|
||||
<TextArea
|
||||
value={text}
|
||||
backgroundColor="white"
|
||||
textColor="black"
|
||||
height={(window.innerHeight - 80)+ "px"}
|
||||
onInput={onInputHandler} />
|
||||
) || (
|
||||
<PaperSheetView />
|
||||
)}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export const PaperSheet = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const {
|
||||
edit_sheet,
|
||||
} = data;
|
||||
return (
|
||||
<Window resizable theme="paper">
|
||||
<Window.Content scrollable>
|
||||
{edit_sheet && (
|
||||
<PaperSheetEdit />
|
||||
) || (
|
||||
<PaperSheetView fillPositionedParent />
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -26,6 +26,8 @@
|
||||
"webpack": "^4.40.2",
|
||||
"webpack-build-notifier": "^2.0.0",
|
||||
"webpack-bundle-analyzer": "^3.5.1",
|
||||
"webpack-cli": "^3.3.9"
|
||||
"webpack-cli": "^3.3.9",
|
||||
"marked": "^1.0.0",
|
||||
"dompurify": "^2.0.11"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
96
tgui/packages/tgui/styles/components/TextArea.scss
Normal file
96
tgui/packages/tgui/styles/components/TextArea.scss
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Aleksej Komarov
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
@use '../base.scss';
|
||||
@use '../functions.scss' as *;
|
||||
|
||||
$border-color: #88bfff !default;
|
||||
$border-radius: base.$border-radius !default;
|
||||
|
||||
.TextArea {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
height: "100%";
|
||||
border: 1px solid $border-color;
|
||||
border: 1px solid rgba($border-color, 0.75);
|
||||
border-radius: $border-radius;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
margin-right: 2px;
|
||||
line-height: 17px;
|
||||
overflow: visible;
|
||||
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
||||
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
||||
box-sizing: border-box; /* Opera/IE 8+ */
|
||||
width:100%;
|
||||
|
||||
}
|
||||
|
||||
.TextArea_filler {
|
||||
word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
|
||||
box-sizing: border-box;
|
||||
padding: 2px;
|
||||
width: 100%;
|
||||
|
||||
padding-bottom: 1.5em; /* A bit more than one additional line of text. */
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.TextArea--fluid {
|
||||
display: block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.TextArea__baseline {
|
||||
display: inline-block;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.TextArea__textarea {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 12px;
|
||||
line-height: 17px;
|
||||
height: 17px;
|
||||
margin: 0;
|
||||
padding: 0 6px;
|
||||
font-family: Verdana, sans-serif;
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
color: inherit;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
|
||||
/* Cut and paste to auto resize the textarea */
|
||||
word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
|
||||
-moz-box-sizing: border-box; /* Firefox, other Gecko */
|
||||
box-sizing: border-box; /* Opera/IE 8+ */
|
||||
|
||||
padding: 2px;
|
||||
width: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
|
||||
&:-ms-input-placeholder {
|
||||
font-style: italic;
|
||||
color: #777;
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@
|
||||
@include meta.load-css('./components/Slider.scss');
|
||||
@include meta.load-css('./components/Table.scss');
|
||||
@include meta.load-css('./components/Tabs.scss');
|
||||
@include meta.load-css('./components/TextArea.scss');
|
||||
@include meta.load-css('./components/Tooltip.scss');
|
||||
|
||||
// Interfaces
|
||||
|
||||
60
tgui/packages/tgui/styles/themes/paper.scss
Normal file
60
tgui/packages/tgui/styles/themes/paper.scss
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file
|
||||
* @copyright 2020 Paul Bruner
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
@use 'sass:color';
|
||||
@use 'sass:meta';
|
||||
|
||||
@use '../colors.scss' with (
|
||||
$primary: #000000,
|
||||
$fg-map-keys: (),
|
||||
$bg-map-keys: (),
|
||||
);
|
||||
@use '../base.scss' with (
|
||||
$color-fg: rgb(0,0,0),
|
||||
$color-bg: rgb(255, 255, 255),
|
||||
$color-bg-grad-spread: 0%,
|
||||
$border-radius: 0px,
|
||||
);
|
||||
|
||||
// A fat warning to anyone who wants to use this: this only half works.
|
||||
// It was made almost purely for the nuke ui, and requires a good amount of manual hacks to get it working as intended.
|
||||
.theme-paper {
|
||||
// Atomic classes
|
||||
@include meta.load-css('../atomic/color.scss');
|
||||
|
||||
// Components
|
||||
@include meta.load-css('../components/Tabs.scss');
|
||||
|
||||
|
||||
@include meta.load-css('../components/Button.scss', $with: (
|
||||
'color-default': #E8E4C9,
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #9d0808,
|
||||
'color-caution': #be6209,
|
||||
'color-danger': #9a9d00,
|
||||
));
|
||||
// Layouts
|
||||
@include meta.load-css('../layouts/Layout.scss');
|
||||
|
||||
@include meta.load-css('../layouts/Window.scss');
|
||||
|
||||
@include meta.load-css('../layouts/TitleBar.scss', $with: (
|
||||
'color-background': #ffffff,
|
||||
));
|
||||
|
||||
.Layout__content {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-family: Consolas,"courier new";
|
||||
color: black;
|
||||
background-color: #f1f1f1;
|
||||
padding: 2px;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2147,6 +2147,11 @@ domelementtype@1:
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
|
||||
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
|
||||
|
||||
dompurify@^2.0.11:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.11.tgz#cd47935774230c5e478b183a572e726300b3891d"
|
||||
integrity sha512-qVoGPjIW9IqxRij7klDQQ2j6nSe4UNWANBhZNLnsS7ScTtLb+3YdxkRY8brNTpkUiTtcXsCJO+jS0UCDfenLuA==
|
||||
|
||||
domelementtype@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
|
||||
@@ -3782,6 +3787,11 @@ map-visit@^1.0.0:
|
||||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
marked@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-1.1.0.tgz#62504ad4d11550c942935ccc5e39d64e5a4c4e50"
|
||||
integrity sha512-EkE7RW6KcXfMHy2PA7Jg0YJE1l8UPEZE8k45tylzmZM30/r1M1MUXWQfJlrSbsTeh7m/XTwHbWUENvAJZpp1YA==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
|
||||
Reference in New Issue
Block a user