Skip to content

Commit

Permalink
[MIRROR] Newspapers now use TGUI (#614)
Browse files Browse the repository at this point in the history
* Newspapers now use TGUI (#80991)

## About The Pull Request

Newspapers work as a static newscaster that is not affected by things
like D-notices and changing wanted issues after its been printed. It
doesn't store comments or get any updates after its been printed.
You can also scribble on the paper to leave notes on a specific page,
which is a feature I have never seen in my life but it is still here I
guess.

Minor things I've added:
- Sound effect when printing the newspaper in the first place
- 2 second do-after when scribbling just for some player feedback and
consistency
- Balloon alerts
- Context tips for scribbling and burning

I also fixed an issue with wanted issues on newscasters when there isn't
an image.
As a minor note, I replaced the instances of ``content`` in Buttons I
saw in newscaster's UI because it's marked as deprecated.

Too lazy to take a video sorry


![image](https://github.com/tgstation/tgstation/assets/53777086/6944965e-e949-4c22-a6a2-1dbe2f2d09c4)

![image](https://github.com/tgstation/tgstation/assets/53777086/5af44877-6170-424d-9766-46d1ad9f77be)

![image](https://github.com/tgstation/tgstation/assets/53777086/5c5cdfc5-541a-417e-a60d-9522227d0687)

## Why It's Good For The Game

Fixes an issue with newscasters and makes newspapers use a nice TGUI
that feels more responsive than before.
Helps further https://hackmd.io/XLt5MoRvRxuhFbwtk4VAUA even more.

## Changelog

:cl:
refactor: Newspapers now use TGUI.
fix: Fixed the newscaster's wanted section showing a non-existent photo.
/:cl:

* Newspapers now use TGUI

---------

Co-authored-by: John Willard <[email protected]>
  • Loading branch information
2 people authored and FFMirrorBot committed Jan 25, 2024
1 parent c18c4c3 commit 094f561
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 231 deletions.
24 changes: 9 additions & 15 deletions code/game/machinery/newscaster/newscaster_machine.dm
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
data["crime_description"] = crime_description
var/list/wanted_info = list()
if(GLOB.news_network.wanted_issue)
if(GLOB.news_network.wanted_issue.img)
var/has_wanted_issue = !isnull(GLOB.news_network.wanted_issue.img)
if(has_wanted_issue)
user << browse_rsc(GLOB.news_network.wanted_issue.img, "wanted_photo.png")
wanted_info = list(list(
"active" = GLOB.news_network.wanted_issue.active,
"criminal" = GLOB.news_network.wanted_issue.criminal,
"crime" = GLOB.news_network.wanted_issue.body,
"author" = GLOB.news_network.wanted_issue.scanned_user,
"image" = "wanted_photo.png"
"image" = (has_wanted_issue ? "wanted_photo.png" : null)
))

//Code breaking down the channels that have been made on-station thus far. ha
Expand Down Expand Up @@ -431,7 +432,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
return TRUE

if("printNewspaper")
print_paper()
print_paper(usr)
return TRUE

if("createBounty")
Expand Down Expand Up @@ -600,22 +601,14 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
* This takes all current feed stories and messages, and prints them onto a newspaper, after checking that the newscaster has been loaded with paper.
* The newscaster then prints the paper to the floor.
*/
/obj/machinery/newscaster/proc/print_paper()
/obj/machinery/newscaster/proc/print_paper(mob/user)
if(paper_remaining <= 0)
balloon_alert_to_viewers("out of paper!")
return TRUE
SSblackbox.record_feedback("amount", "newspapers_printed", 1)
var/obj/item/newspaper/new_newspaper = new /obj/item/newspaper
for(var/datum/feed_channel/iterated_feed_channel in GLOB.news_network.network_channels)
new_newspaper.news_content += iterated_feed_channel
if(GLOB.news_network.wanted_issue.active)
new_newspaper.wantedAuthor = GLOB.news_network.wanted_issue.scanned_user
new_newspaper.wantedCriminal = GLOB.news_network.wanted_issue.criminal
new_newspaper.wantedBody = GLOB.news_network.wanted_issue.body
if(GLOB.news_network.wanted_issue.img)
new_newspaper.wantedPhoto = GLOB.news_network.wanted_issue.img
new_newspaper.forceMove(drop_location())
new_newspaper.creation_time = GLOB.news_network.last_action
var/obj/item/newspaper/new_newspaper = new(loc)
playsound(loc, SFX_PAGE_TURN, 50, TRUE)
try_put_in_hand(new_newspaper, user)
paper_remaining--

/**
Expand Down Expand Up @@ -677,6 +670,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30)
new_feed_comment.author = newscaster_username
new_feed_comment.body = comment_text
new_feed_comment.time_stamp = station_time_timestamp()
GLOB.news_network.last_action ++
current_message.comments += new_feed_comment
usr.log_message("(as [newscaster_username]) commented on message [current_message.return_body(-1)] -- [current_message.body]", LOG_COMMENT)
creating_comment = FALSE
Expand Down
295 changes: 152 additions & 143 deletions code/game/machinery/newscaster/newspaper.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Newspapers
* A static version of the newscaster, that won't update as new stories are added.
* Can be scribbed upon to add extra text for future readers.
*/
/obj/item/newspaper
name = "newspaper"
desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations."
Expand All @@ -10,167 +15,171 @@
attack_verb_continuous = list("baps")
attack_verb_simple = list("bap")
resistance_flags = FLAMMABLE
var/screen = 0
var/pages = 0
var/curr_page = 0

///List of news feeed channels the newspaper can see.
var/list/datum/feed_channel/news_content = list()
var/scribble=""
var/scribble_page = null
var/wantedAuthor
var/wantedCriminal
var/wantedBody
var/wantedPhoto
///The time the newspaper was made in terms of newscaster's last action, used to tell the newspaper whether a story should be in it.
var/creation_time
///The page in the newspaper currently being read. 0 is the title screen while the last is the security screen.
var/current_page = 0
///The currently scribbled text written in scribble_page
var/scribble_text
///The page with something scribbled on it, can only have one at a time.
var/scribble_page

///Stored information of the wanted criminal's name, if one existed at the time of creation.
var/saved_wanted_criminal
///Stored information of the wanted criminal's description, if one existed at the time of creation.
var/saved_wanted_body
///Stored icon of the wanted criminal, if one existed at the time of creation.
var/icon/saved_wanted_icon

/obj/item/newspaper/Initialize(mapload)
. = ..()
register_context()
creation_time = GLOB.news_network.last_action
for(var/datum/feed_channel/iterated_feed_channel in GLOB.news_network.network_channels)
news_content += iterated_feed_channel

if(!GLOB.news_network.wanted_issue.active)
return
saved_wanted_criminal = GLOB.news_network.wanted_issue.criminal
saved_wanted_body = GLOB.news_network.wanted_issue.body
if(GLOB.news_network.wanted_issue.img)
saved_wanted_icon = GLOB.news_network.wanted_issue.img

/obj/item/newspaper/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
if(held_item)
if(istype(held_item, /obj/item/pen))
context[SCREENTIP_CONTEXT_LMB] = "Scribble"
return CONTEXTUAL_SCREENTIP_SET
if(held_item.get_temperature())
context[SCREENTIP_CONTEXT_LMB] = "Burn"
return CONTEXTUAL_SCREENTIP_SET

/obj/item/newspaper/suicide_act(mob/living/user)
user.visible_message(span_suicide("[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... until [user.p_their()] eyes light up with realization!"))
user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF", forced="newspaper suicide")
var/mob/living/carbon/human/H = user
var/obj/W = new /obj/item/reagent_containers/cup/glass/bottle/whiskey(H.loc)
playsound(H.loc, 'sound/items/drink.ogg', rand(10,50), TRUE)
W.reagents.trans_to(H, W.reagents.total_volume, transferred_by = user)
user.visible_message(span_suicide("[user] downs the contents of [W.name] in one gulp! Shoulda stuck to sudoku!"))
user.visible_message(span_suicide(\
"[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... \
until [user.p_their()] eyes light up with realization!"\
))
user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF", forced = "newspaper suicide")
var/obj/item/reagent_containers/cup/glass/bottle/whiskey/last_drink = new(user.loc)
playsound(user, 'sound/items/drink.ogg', vol = rand(10, 50), vary = TRUE)
last_drink.reagents.trans_to(user, last_drink.reagents.total_volume, transferred_by = user)
user.visible_message(span_suicide("[user] downs the contents of [last_drink.name] in one gulp! Shoulda stuck to sudoku!"))
return TOXLOSS

/obj/item/newspaper/attack_self(mob/user)
if(!istype(user) || !user.can_read(src))
/obj/item/newspaper/attackby(obj/item/attacking_item, mob/user, params)
if(burn_paper_product_attackby_check(attacking_item, user))
SStgui.close_uis(src)
return
var/dat
pages = 0
switch(screen)
if(0) //Cover
dat+="<DIV ALIGN='center'><B><FONT SIZE=6>The Griffon</FONT></B></div>"
dat+="<DIV ALIGN='center'><FONT SIZE=2>Nanotrasen-standard newspaper, for use on Nanotrasen? Space Facilities</FONT></div><HR>"
if(!length(news_content))
if(wantedAuthor)
dat+="Contents:<BR><ul><B><FONT COLOR='red'>**</FONT>Important Security Announcement<FONT COLOR='red'>**</FONT></B> <FONT SIZE=2>\[page [pages+2]\]</FONT><BR></ul>"
else
dat+="<I>Other than the title, the rest of the newspaper is unprinted...</I>"
else
dat+="Contents:<BR><ul>"
for(var/datum/feed_channel/NP in news_content)
pages++
if(wantedAuthor)
dat+="<B><FONT COLOR='red'>**</FONT>Important Security Announcement<FONT COLOR='red'>**</FONT></B> <FONT SIZE=2>\[page [pages+2]\]</FONT><BR>"
var/temp_page=0
for(var/datum/feed_channel/NP in news_content)
temp_page++
dat+="<B>[NP.channel_name]</B> <FONT SIZE=2>\[page [temp_page+1]\]</FONT><BR>"
dat+="</ul>"
if(scribble_page == curr_page)
dat+="<BR><I>There is a small scribble near the end of this page... It reads: \"[scribble]\"</I>"
dat+= "<HR><DIV STYLE='float:right;'><A href='?src=[REF(src)];next_page=1'>Next Page</A></DIV> <div style='float:left;'><A href='?src=[REF(user)];mach_close=newspaper_main'>Done reading</A></DIV>"
if(1) // X channel pages inbetween.
for(var/datum/feed_channel/NP in news_content)
pages++
var/datum/feed_channel/C = news_content[curr_page]
dat += "<FONT SIZE=4><B>[C.channel_name]</B></FONT><FONT SIZE=1> \[created by: <FONT COLOR='maroon'>[C.return_author(notContent(C.author_censor_time))]</FONT>\]</FONT><BR><BR>"
if(notContent(C.D_class_censor_time))
dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a <B><FONT COLOR='red'>D-Notice</B></FONT>. Its contents were not transferred to the newspaper at the time of printing."
else
if(!length(C.messages))
dat+="No Feed stories stem from this channel..."
else
var/i = 0
for(var/datum/feed_message/MESSAGE in C.messages)
if(MESSAGE.creation_time > creation_time)
if(i == 0)
dat+="No Feed stories stem from this channel..."
break
if(i == 0)
dat+="<ul>"
i++
dat+="-[MESSAGE.return_body(notContent(MESSAGE.body_censor_time))] <BR>"
if(MESSAGE.img)
user << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
dat+="<img src='tmp_photo[i].png' width = '180'><BR>"
dat+="<FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.return_author(notContent(MESSAGE.author_censor_time))]</FONT>\]</FONT><BR><BR>"
dat+="</ul>"
if(scribble_page == curr_page)
dat+="<BR><I>There is a small scribble near the end of this page... It reads: \"[scribble]\"</I>"
dat+= "<BR><HR><DIV STYLE='float:left;'><A href='?src=[REF(src)];prev_page=1'>Previous Page</A></DIV> <DIV STYLE='float:right;'><A href='?src=[REF(src)];next_page=1'>Next Page</A></DIV>"
if(2) //Last page
for(var/datum/feed_channel/NP in news_content)
pages++
if(wantedAuthor != null)
dat+="<DIV STYLE='float:center;'><FONT SIZE=4><B>Wanted Issue:</B></FONT SIZE></DIV><BR><BR>"
dat+="<B>Criminal name</B>: <FONT COLOR='maroon'>[wantedCriminal]</FONT><BR>"
dat+="<B>Description</B>: [wantedBody]<BR>"
dat+="<B>Photo:</B>: "
if(wantedPhoto)
user << browse_rsc(wantedPhoto, "tmp_photow.png")
dat+="<BR><img src='tmp_photow.png' width = '180'>"
else
dat+="None"
else
dat+="<I>Apart from some uninteresting classified ads, there's nothing on this page...</I>"
if(scribble_page == curr_page)
dat+="<BR><I>There is a small scribble near the end of this page... It reads: \"[scribble]\"</I>"
dat+= "<HR><DIV STYLE='float:left;'><A href='?src=[REF(src)];prev_page=1'>Previous Page</A></DIV>"
dat+="<BR><HR><div align='center'>[curr_page+1]</div>"
user << browse(dat, "window=newspaper_main;size=300x400")
onclose(user, "newspaper_main")

/obj/item/newspaper/proc/notContent(list/L)
if(!L.len)
if(!user.can_write(attacking_item))
return ..()
if(scribble_page == current_page)
user.balloon_alert(user, "already scribbled!")
return
var/new_scribble_text = tgui_input_text(user, "What do you want to scribble?", "Write something")
if(isnull(new_scribble_text))
return
add_fingerprint(user)
user.balloon_alert(user, "scribbling...")
if(!do_after(user, 2 SECONDS, src))
return
user.balloon_alert(user, "scribbled!")
scribble_page = current_page
scribble_text = new_scribble_text

///Checks the creation time of the newspaper and compares it to list to see if the list is meant to be censored at the time of printing.
/obj/item/newspaper/proc/censored_check(list/times_censored)
if(!times_censored.len)
return FALSE
for(var/i=L.len;i>0;i--)
var/num = abs(L[i])
for(var/i = times_censored.len; i > 0; i--)
var/num = abs(times_censored[i])
if(creation_time <= num)
continue
else
if(L[i] > 0)
if(times_censored[i] > 0)
return TRUE
else
return FALSE
return FALSE

/obj/item/newspaper/Topic(href, href_list)
var/mob/living/U = usr
..()
if((src in U.contents) || (isturf(loc) && in_range(src, U)))
U.set_machine(src)
if(href_list["next_page"])
if(curr_page == pages+1)
return //Don't need that at all, but anyway.
if(curr_page == pages) //We're at the middle, get to the end
screen = 2
else
if(curr_page == 0) //We're at the start, get to the middle
screen=1
curr_page++
playsound(loc, SFX_PAGE_TURN, 50, TRUE)
else if(href_list["prev_page"])
if(curr_page == 0)
return
if(curr_page == 1)
screen = 0
else
if(curr_page == pages+1) //we're at the end, let's go back to the middle.
screen = 1
curr_page--
playsound(loc, SFX_PAGE_TURN, 50, TRUE)
if(ismob(loc))
attack_self(loc)
/obj/item/newspaper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Newspaper", name)
ui.open()

/obj/item/newspaper/attackby(obj/item/W, mob/living/user, params)
if(burn_paper_product_attackby_check(W, user))
/obj/item/newspaper/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return

if(istype(W, /obj/item/pen))
if(!user.can_write(W))
return
if(scribble_page == curr_page)
to_chat(user, span_warning("There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?"))
switch(action)
if("next_page")
//We're at the very end, nowhere else to go.
if(current_page == news_content.len + 1)
return TRUE
current_page++
if("prev_page")
//We haven't started yet, nowhere else to go.
if(!current_page)
return TRUE
current_page--
else
var/s = tgui_input_text(user, "Write something", "Newspaper")
if (!s)
return
if(!user.can_perform_action(src))
return
scribble_page = curr_page
scribble = s
attack_self(user)
add_fingerprint(user)
else
return ..()
return TRUE
SStgui.update_uis(src)
playsound(src, SFX_PAGE_TURN, 50, TRUE)
return TRUE

/obj/item/newspaper/ui_static_data(mob/user)
var/list/data = list()
data["channels"] = list()
for(var/datum/feed_channel/news_channels as anything in news_content)
data["channels"] += list(list(
"name" = news_channels.channel_name,
"page_number" = news_content.Find(news_channels),
))
return data

/obj/item/newspaper/ui_data(mob/user)
var/list/data = list()
data["current_page"] = current_page
data["scribble_message"] = (scribble_page == current_page) ? scribble_text : null
if(saved_wanted_icon)
user << browse_rsc(saved_wanted_icon, "wanted_photo.png")
data["wanted_criminal"] = saved_wanted_criminal
data["wanted_body"] = saved_wanted_body
data["wanted_photo"] = (saved_wanted_icon ? "wanted_photo.png" : null)

var/list/channel_data = list()
if(!current_page || (current_page == news_content.len + 1))
channel_data["channel_name"] = null
channel_data["author_name"] = null
channel_data["is_censored"] = null
channel_data["channel_messages"] = list()
data["channel_data"] = list(channel_data)
return data
var/datum/feed_channel/current_channel = news_content[current_page]
if(istype(current_channel))
channel_data["channel_name"] = current_channel.channel_name
channel_data["author_name"] = current_channel.return_author(censored_check(current_channel.author_censor_time))
channel_data["is_censored"] = censored_check(current_channel.D_class_censor_time)
channel_data["channel_messages"] = list()
for(var/datum/feed_message/feed_messages as anything in current_channel.messages)
if(feed_messages.creation_time > creation_time)
data["channel_has_messages"] = FALSE
break
data["channel_has_messages"] = TRUE
var/has_image = FALSE
if(feed_messages.img)
has_image = TRUE
user << browse_rsc(feed_messages.img, "tmp_photo[feed_messages.message_ID].png")
channel_data["channel_messages"] += list(list(
"message" = "-[feed_messages.return_body(censored_check(feed_messages.body_censor_time))]",
"photo" = (has_image ? "tmp_photo[feed_messages.message_ID].png" : null),
"author" = feed_messages.return_author(censored_check(feed_messages.author_censor_time)),
))
data["channel_data"] = list(channel_data)
return data
Loading

0 comments on commit 094f561

Please sign in to comment.