diff --git a/aurorastation.dme b/aurorastation.dme
index bee49b72379..49fece370da 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -2505,6 +2505,7 @@
#include "code\modules\paperwork\filingcabinet.dm"
#include "code\modules\paperwork\folders.dm"
#include "code\modules\paperwork\handlabeler.dm"
+#include "code\modules\paperwork\journal.dm"
#include "code\modules\paperwork\paper.dm"
#include "code\modules\paperwork\paper_bundle.dm"
#include "code\modules\paperwork\paperbin.dm"
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index acd519450f8..b42f9831c3d 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -2126,3 +2126,11 @@ All custom items with worn sprites must follow the contained sprite system: http
icon_state = "pax_bag"
item_state = "pax_bag"
contained_sprite = TRUE
+
+/obj/item/journal/fluff/kathira // Blue Leather-Bound Journal - Kathira El-Hashem - TheGreyWolf
+ name = "blue leather-bound journal"
+ desc = "A blue journal emblazoned with the New Kingdom of Adhomai's flag across the cover."
+ closed_desc = " The pages within are a mix of clearly indexed case files, and study notes alongside less clearly indexed pages that appears to be fragmented thoughts, not unlike a diary. The very first page of the journal reads “dedicated to Qirandri Mrorirhaldarr” and is signed “Mrradar Sanufar” underneath."
+ icon = 'icons/obj/custom_items/kathira_journal.dmi'
+ icon_state = "kath_journal"
+ item_state = "kath_journal"
\ No newline at end of file
diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index 0db871e2e29..71189775ee7 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -7,6 +7,8 @@
drop_sound = 'sound/items/drop/paper.ogg'
pickup_sound = 'sound/items/pickup/paper.ogg'
+ var/can_write = FALSE
+
/obj/item/folder/blue
desc = "A blue folder."
icon_state = "folder_blue"
@@ -52,7 +54,7 @@
var/dat = "
[name]"
for(var/obj/item/paper/P in src)
- dat += "Remove Rename - [P.name]
"
+ dat += "[can_write ? "Write " : ""]Remove Rename - [P.name]
"
for(var/obj/item/photo/Ph in src)
dat += "Remove Rename - [Ph.name]
"
for(var/obj/item/paper_bundle/Pb in src)
@@ -69,14 +71,19 @@
if((usr.stat || usr.restrained()))
return
- if(src.loc == usr)
+ if(loc_check(usr))
if(href_list["remove"])
var/obj/item/P = locate(href_list["remove"])
if(P && (P.loc == src) && istype(P))
P.forceMove(usr.loc)
usr.put_in_hands(P)
-
+ handle_post_remove()
+ else if(href_list["write"])
+ var/obj/item/paper/P = locate(href_list["write"])
+ var/obj/item/I = usr.get_inactive_hand()
+ if(P && I && (P.loc == src) && istype(P) && I.ispen())
+ P.attackby(I, usr)
else if(href_list["read"])
var/obj/item/paper/P = locate(href_list["read"])
if(P && (P.loc == src) && istype(P))
@@ -111,6 +118,14 @@
update_icon()
return
+/obj/item/folder/proc/loc_check(var/atom/A)
+ if(loc == A)
+ return TRUE
+ return FALSE
+
+/obj/item/folder/proc/handle_post_remove()
+ return
+
/obj/item/folder/blue/nka/Initialize()
. = ..()
for (var/I = 1 to 5)
@@ -119,4 +134,17 @@
/obj/item/folder/filled/Initialize()
. = ..()
for (var/I = 1 to 10)
- new /obj/item/paper(src)
\ No newline at end of file
+ new /obj/item/paper(src)
+
+/obj/item/folder/embedded
+ name = "index"
+ can_write = TRUE
+
+/obj/item/folder/embedded/loc_check(var/atom/A)
+ if(loc.loc == A)
+ return TRUE
+ return FALSE
+
+/obj/item/folder/embedded/handle_post_remove()
+ if(!length(contents))
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/paperwork/journal.dm b/code/modules/paperwork/journal.dm
new file mode 100644
index 00000000000..e0e5945f0fe
--- /dev/null
+++ b/code/modules/paperwork/journal.dm
@@ -0,0 +1,96 @@
+/obj/item/journal
+ name = "journal"
+ desc = "A journal, kind of like a folder, but bigger! And personal."
+ var/closed_desc
+ desc_info = "Ctrl-click this while it's on your person to open this journal."
+ icon = 'icons/obj/contained_items/misc/journal.dmi'
+ icon_state = "journal"
+ item_state = "journal"
+ contained_sprite = TRUE
+ update_icon_on_init = TRUE
+ throw_speed = 1
+ throw_range = 5
+ w_class = ITEMSIZE_NORMAL
+ attack_verb = list("bashed", "whacked", "educated")
+ drop_sound = 'sound/items/drop/book.ogg'
+ pickup_sound = 'sound/items/pickup/book.ogg'
+
+ var/static/list/insertables = list(/obj/item/paper, /obj/item/photo, /obj/item/paper_bundle, /obj/item/sample)
+
+ var/open = FALSE
+ var/list/indices
+
+/obj/item/journal/Destroy()
+ for(var/obj/item/folder/embedded/E as anything in indices)
+ qdel(E)
+ return ..()
+
+/obj/item/journal/update_icon()
+ if(!open)
+ icon_state = "[initial(icon_state)]_closed"
+ else if(LAZYLEN(indices))
+ icon_state = "[initial(icon_state)]_writing"
+ else
+ icon_state = initial(icon_state)
+
+ if(closed_desc)
+ desc = open ? initial(desc) + closed_desc : initial(desc)
+
+/obj/item/journal/CtrlClick(mob/user)
+ if(loc == user)
+ open = !open
+ to_chat(user, SPAN_NOTICE("You [open ? "open" : "close"] \the [src]."))
+ update_icon()
+ return
+ return ..()
+
+/obj/item/journal/attack_self(mob/user)
+ if(!open)
+ to_chat(user, SPAN_WARNING("You can't look inside \the [src] while it's closed."))
+ return
+ if(!LAZYLEN(indices))
+ to_chat(user, SPAN_WARNING("\The [src] doesn't have anything inside!"))
+ return
+ var/selected_folder = input(user, "Select an index to view.", "Index View") as null|anything in indices
+ if(isnull(selected_folder))
+ return
+ var/obj/item/folder/embedded/E = indices[selected_folder]
+ E.attack_self(user)
+
+/obj/item/journal/attackby(obj/item/I, mob/user)
+ if(is_type_in_list(I, insertables))
+ if(!open)
+ to_chat(user, SPAN_WARNING("You can't put anything into \the [src] while it's closed."))
+ return
+ var/obj/item/folder/embedded/E
+ var/list/options = LAZYLEN(indices) ? indices + "New Index" : list("New Index")
+ var/selected_folder = input(user, "Select an index to insert this into.", "Index Selection") as null|anything in options
+ if(isnull(selected_folder))
+ return
+ if(selected_folder == "New Index")
+ E = generate_index(user)
+ else
+ E = indices[selected_folder]
+ if(!E)
+ return
+ user.drop_from_inventory(I, E)
+ to_chat(user, SPAN_NOTICE("You put \the [I] into \the [E]."))
+ update_icon()
+ return
+
+/obj/item/journal/proc/generate_index(var/mob/user)
+ var/obj/item/folder/embedded/E = new /obj/item/folder/embedded(src)
+ var/index_name = sanitize(input(user, "Enter the index' name.", "Index Name") as text|null)
+ if(!index_name)
+ qdel(E)
+ return null
+ if(index_name == "New Index" || LAZYISIN(indices, index_name))
+ index_name = "Index ([length(indices) + 1])"
+ E.name = index_name
+ LAZYSET(indices, E.name, E)
+ destroyed_event.register(E, src, .proc/remove_index)
+ return E
+
+/obj/item/journal/proc/remove_index(var/obj/item/folder/embedded/E)
+ LAZYREMOVE(indices, E.name)
+ update_icon()
\ No newline at end of file
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 101c6603526..cd3770a092a 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -433,6 +433,8 @@
return
var/obj/item/i = usr.get_active_hand() // Check to see if he still got that darn pen, also check if he's using a crayon or pen.
+ if(!i || !i.ispen())
+ i = usr.get_inactive_hand()
var/obj/item/clipboard/c
var/iscrayon = FALSE
var/isfountain = FALSE
@@ -463,8 +465,7 @@
else
isfountain = FALSE
- // if paper is not in usr, then it must be near them, or in a clipboard or folder, which must be in or near usr
- if(src.loc != usr && !src.Adjacent(usr) && !((istype(src.loc, /obj/item/clipboard) || istype(src.loc, /obj/item/folder)) && (src.loc.loc == usr || src.loc.Adjacent(usr)) ) )
+ if(!write_check(usr))
return
var/last_fields_value = fields
@@ -495,6 +496,19 @@
if(c)
c.update_icon()
+/obj/item/paper/proc/write_check(var/mob/user)
+ . = TRUE
+ // if paper is not in usr, then it must be near them, or in a clipboard or folder, which must be in or near usr
+ if(loc != user && !Adjacent(user))
+ . = FALSE
+ if(!. && istype(loc, /obj/item/clipboard))
+ var/obj/item/clipboard/C = loc
+ if(C.loc == user || C.Adjacent(user))
+ . = TRUE
+ if(!. && istype(loc, /obj/item/folder))
+ var/obj/item/folder/F = loc
+ if(F.loc_check(user) || F.Adjacent(user))
+ . = TRUE
/obj/item/paper/attackby(var/obj/item/P, mob/user)
..()
diff --git a/icons/obj/contained_items/misc/journal.dmi b/icons/obj/contained_items/misc/journal.dmi
new file mode 100644
index 00000000000..d3d173a046d
Binary files /dev/null and b/icons/obj/contained_items/misc/journal.dmi differ
diff --git a/icons/obj/custom_items/kathira_journal.dmi b/icons/obj/custom_items/kathira_journal.dmi
new file mode 100644
index 00000000000..f9687d0c8b0
Binary files /dev/null and b/icons/obj/custom_items/kathira_journal.dmi differ