Files
Bubberstation/code/modules/library/soapstone.dm
SkyratBot a66483eba6 [MIRROR] Soapstone & engraved message fixes (#6798)
* Fix soapstone and engraved messages (#60055)

This PR fixes and improves a few things regarding soapstones and engraved messages:

- Observers can now interact with the engraved messages from any distance instead of having to be next to them to rate them, which was rather unintuitive and unnecessary. This also solves problems where admin observers were unable to delete them without being next to them or activating AI interact mode.
- Fixed a case where you could make more engraved messages than your soapstone had uses by queing them fast enough.
- Cleaned up engraved message UI code a little bit - removed an unnecessary section and replaced deprecated <Grid> with <Stack>. Looks practically the same.
- Minor code improvements.

* Soapstone & engraved message fixes

Co-authored-by: Arkatos1 <43862960+Arkatos1@users.noreply.github.com>
2021-07-09 01:22:17 +01:00

291 lines
8.2 KiB
Plaintext

/obj/item/soapstone
name = "soapstone"
desc = "Leave informative messages for the crew, including the crew of future shifts!\nEven if out of uses, it can still be used to remove messages.\n(Not suitable for engraving on shuttles, off station or on cats. Side effects may include prompt beatings, psychotic clown incursions, and/or orbital bombardment.)"
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "soapstone"
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_TINY
var/tool_speed = 50
var/remaining_uses = 3
/obj/item/soapstone/Initialize(mapload)
. = ..()
check_name()
/obj/item/soapstone/examine(mob/user)
. = ..()
if(remaining_uses != -1)
. += "It has [remaining_uses] uses left."
/obj/item/soapstone/afterattack(atom/target, mob/user, proximity)
. = ..()
var/turf/T = get_turf(target)
if(!proximity)
return
var/obj/structure/chisel_message/existing_message = locate() in T
if(!remaining_uses && !existing_message)
to_chat(user, span_warning("[src] is too worn out to use."))
return
if(!good_chisel_message_location(T))
to_chat(user, span_warning("It's not appropriate to engrave on [T]."))
return
if(existing_message)
user.visible_message(span_notice("[user] starts erasing [existing_message]."), span_notice("You start erasing [existing_message]."), span_hear("You hear a chipping sound."))
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
if(do_after(user, tool_speed, target = existing_message))
user.visible_message(span_notice("[user] erases [existing_message]."), span_notice("You erase [existing_message][existing_message.creator_key == user.ckey ? ", refunding a use" : ""]."))
existing_message.persists = FALSE
qdel(existing_message)
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
if(existing_message.creator_key == user.ckey)
refund_use()
return
var/message = stripped_input(user, "What would you like to engrave?", "Leave a message")
if(!message)
to_chat(user, span_notice("You decide not to engrave anything."))
return
if(!target.Adjacent(user) && locate(/obj/structure/chisel_message) in T)
to_chat(user, span_warning("Someone wrote here before you chose! Find another spot."))
return
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
user.visible_message(span_notice("[user] starts engraving a message into [T]..."), span_notice("You start engraving a message into [T]..."), span_hear("You hear a chipping sound."))
if(can_use() && do_after(user, tool_speed, target = T) && can_use()) //This looks messy but it's actually really clever!
if(!locate(/obj/structure/chisel_message) in T)
user.visible_message(span_notice("[user] leaves a message for future spacemen!"), span_notice("You engrave a message into [T]!"), span_hear("You hear a chipping sound."))
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
var/obj/structure/chisel_message/M = new(T)
M.register(user, message)
remove_use()
/obj/item/soapstone/proc/can_use()
return remaining_uses == -1 || remaining_uses > 0
/obj/item/soapstone/proc/remove_use()
if(remaining_uses <= 0)
return
remaining_uses--
check_name()
/obj/item/soapstone/proc/refund_use()
if(remaining_uses == -1)
return
remaining_uses++
check_name()
/obj/item/soapstone/proc/check_name()
if(remaining_uses)
// This will mess up RPG loot names, but w/e
name = initial(name)
else
name = "dull [initial(name)]"
/* Persistent engraved messages, etched onto the station turfs to serve
as instructions and/or memes for the next generation of spessmen.
Limited in location to station_z only. Can be smashed out or exploded,
but only permanently removed with the curator's soapstone.
*/
/obj/item/soapstone/infinite
remaining_uses = -1
/obj/item/soapstone/empty
remaining_uses = 0
/proc/good_chisel_message_location(turf/T)
if(!T)
. = FALSE
else if(!(isfloorturf(T) || iswallturf(T)))
. = FALSE
else
. = TRUE
/obj/structure/chisel_message
name = "engraved message"
desc = "A message from a past traveler."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "soapstone_message"
layer = LATTICE_LAYER
density = FALSE
anchored = TRUE
max_integrity = 30
var/hidden_message
var/creator_key
var/creator_name
var/realdate
var/map
var/persists = TRUE
var/list/like_keys = list()
var/list/dislike_keys = list()
var/turf/original_turf
/// Total vote count at or below which we won't persist.
var/delete_at = -5
/obj/structure/chisel_message/Initialize(mapload)
. = ..()
SSpersistence.chisel_messages += src
var/turf/T = get_turf(src)
original_turf = T
if(!good_chisel_message_location(T))
persists = FALSE
return INITIALIZE_HINT_QDEL
if(like_keys.len - dislike_keys.len <= delete_at)
persists = FALSE
/obj/structure/chisel_message/proc/register(mob/user, newmessage)
hidden_message = newmessage
creator_name = user.real_name
creator_key = user.ckey
realdate = world.realtime
map = SSmapping.config.map_name
update_appearance()
/obj/structure/chisel_message/update_icon()
. = ..()
var/hash = md5(hidden_message)
var/newcolor = copytext_char(hash, 1, 7)
add_atom_colour("#[newcolor]", FIXED_COLOUR_PRIORITY)
set_light_color("#[newcolor]")
set_light(1)
/obj/structure/chisel_message/proc/pack()
var/list/data = list()
data["hidden_message"] = hidden_message
data["creator_name"] = creator_name
data["creator_key"] = creator_key
data["realdate"] = realdate
data["map"] = SSmapping.config.map_name
data["x"] = original_turf.x
data["y"] = original_turf.y
data["z"] = original_turf.z
data["like_keys"] = like_keys
data["dislike_keys"] = dislike_keys
return data
/obj/structure/chisel_message/proc/unpack(list/data)
if(!islist(data))
return
hidden_message = data["hidden_message"]
creator_name = data["creator_name"]
creator_key = data["creator_key"]
realdate = data["realdate"]
like_keys = data["like_keys"]
if(!like_keys)
like_keys = list()
dislike_keys = data["dislike_keys"]
if(!dislike_keys)
dislike_keys = list()
var/x = data["x"]
var/y = data["y"]
var/z = data["z"]
var/turf/newloc = locate(x, y, z)
if(isturf(newloc))
forceMove(newloc)
update_appearance()
/obj/structure/chisel_message/examine(mob/user)
. = ..()
ui_interact(user)
/obj/structure/chisel_message/Destroy()
if(persists)
SSpersistence.SaveChiselMessage(src)
SSpersistence.chisel_messages -= src
return ..()
/obj/structure/chisel_message/interact()
return
/obj/structure/chisel_message/ui_status(mob/user)
if(isobserver(user)) // ignore proximity restrictions if we're an observer
return UI_INTERACTIVE
return ..()
/obj/structure/chisel_message/ui_state(mob/user)
return GLOB.always_state
/obj/structure/chisel_message/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "EngravedMessage", name)
ui.open()
/obj/structure/chisel_message/ui_data(mob/user)
var/list/data = list()
data["hidden_message"] = hidden_message
data["realdate"] = SQLtime(realdate)
data["num_likes"] = like_keys.len
data["num_dislikes"] = dislike_keys.len
data["is_creator"] = user.ckey == creator_key
data["has_liked"] = (user.ckey in like_keys)
data["has_disliked"] = (user.ckey in dislike_keys)
if(check_rights_for(user.client, R_ADMIN))
data["admin_mode"] = TRUE
data["creator_key"] = creator_key
data["creator_name"] = creator_name
else
data["admin_mode"] = FALSE
data["creator_key"] = null
data["creator_name"] = null
return data
/obj/structure/chisel_message/ui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
var/mob/user = usr
var/is_admin = check_rights_for(user.client, R_ADMIN)
var/is_creator = user.ckey == creator_key
var/has_liked = (user.ckey in like_keys)
var/has_disliked = (user.ckey in dislike_keys)
switch(action)
if("like")
if(is_creator)
return
if(has_disliked)
dislike_keys -= user.ckey
like_keys |= user.ckey
. = TRUE
if("dislike")
if(is_creator)
return
if(has_liked)
like_keys -= user.ckey
dislike_keys |= user.ckey
. = TRUE
if("neutral")
if(is_creator)
return
dislike_keys -= user.ckey
like_keys -= user.ckey
. = TRUE
if("delete")
if(!is_admin)
return
var/confirm = tgui_alert(user, "Confirm deletion of engraved message?", "Confirm Deletion", list("Yes", "No"))
if(confirm == "Yes")
persists = FALSE
qdel(src)
return
persists = like_keys.len - dislike_keys.len > delete_at