diff --git a/code/modules/newscaster/datums.dm b/code/modules/newscaster/datums.dm index 9bb660d2a02..9d5860897b6 100644 --- a/code/modules/newscaster/datums.dm +++ b/code/modules/newscaster/datums.dm @@ -9,7 +9,7 @@ var/datum/feed_message/wanted_issue /** - * Returns the [/datum/get_channel_by_name] with the given name, or null if not found. + * Returns the [/datum/feed_channel] with the given name, or null if not found. * * Arguments: * * name - The name @@ -20,6 +20,18 @@ if(FC.channel_name == name) return FC +/** + * Returns the [/datum/feed_channel] with the given author, or null if not found. + * + * Arguments: + * * author - The author + */ +/datum/feed_network/proc/get_channel_by_author(author) + for(var/fc in channels) + var/datum/feed_channel/FC = fc + if(FC.author == author) + return FC + /** * Returns the [/datum/feed_channel] at the given index, or null if not found. * @@ -31,6 +43,7 @@ return return channels[idx] + /** * # Feed Message * @@ -94,6 +107,8 @@ var/is_public = FALSE /// Whether the channel is frozen or not. var/frozen = FALSE + /// Whether the channel is censored or not. + var/censored = FALSE /// Whether the channel is admin-locked. var/admin_locked = FALSE @@ -133,6 +148,7 @@ messages = list() is_public = FALSE frozen = FALSE + censored = FALSE admin_locked = FALSE /** diff --git a/code/modules/newscaster/newscaster.dm b/code/modules/newscaster/obj/newscaster.dm similarity index 68% rename from code/modules/newscaster/newscaster.dm rename to code/modules/newscaster/obj/newscaster.dm index ca5d4ec1d02..f94e6fecd3e 100644 --- a/code/modules/newscaster/newscaster.dm +++ b/code/modules/newscaster/obj/newscaster.dm @@ -6,6 +6,14 @@ #define WANTED_NOTICE_DESC_MAX_LENGTH 512 #define STORIES_PER_LOAD 9999 // TODO during QP... +/** + * # Newscaster + * + * For all of the crew's news need. Includes reading, submitting and printing stories. + * + * Includes a security variant which can be used to issue wanted notices, censor channels and stories. + * Allows full access when aghosting. + */ /obj/machinery/newscaster name = "newscaster" desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!" @@ -35,25 +43,10 @@ var/is_silent = FALSE /// The current temporary notice. var/temp_notice - /// Jobs that shouldn't be advertised if a position is available. - var/list/jobblacklist = list( - /datum/job/ai, - /datum/job/cyborg, - /datum/job/captain, - /datum/job/judge, - /datum/job/blueshield, - /datum/job/nanotrasenrep, - /datum/job/pilot, - /datum/job/brigdoc, - /datum/job/mechanic, - /datum/job/barber, - /datum/job/chaplain, - /datum/job/ntnavyofficer, - /datum/job/ntspecops, - /datum/job/civilian, - /datum/job/syndicateofficer) - /// Redacted text - var/static/REDACTED = "\[REDACTED\]" + /// Whether the newscaster is currently printing a newspaper or not. + var/is_printing = FALSE + /// Static list of jobs that shouldn't be advertised if a position is available. + var/static/list/jobblacklist /// Static, lazy list containing a user's last view time per channel. var/static/last_views @@ -63,7 +56,7 @@ /obj/machinery/newscaster/New() GLOB.allNewscasters += src - unit_number = GLOB.allNewscasters.len + unit_number = length(GLOB.allNewscasters) update_icon() //for any custom ones on the map... if(!last_views) last_views = list() @@ -72,6 +65,24 @@ /obj/machinery/newscaster/Initialize(mapload) . = ..() + if(!jobblacklist) + jobblacklist = list( + /datum/job/ai, + /datum/job/cyborg, + /datum/job/captain, + /datum/job/judge, + /datum/job/blueshield, + /datum/job/nanotrasenrep, + /datum/job/pilot, + /datum/job/brigdoc, + /datum/job/mechanic, + /datum/job/barber, + /datum/job/chaplain, + /datum/job/ntnavyofficer, + /datum/job/ntspecops, + /datum/job/civilian, + /datum/job/syndicateofficer + ) /obj/machinery/newscaster/Destroy() GLOB.allNewscasters -= src @@ -107,6 +118,53 @@ . = ..() update_icon() +/obj/machinery/newscaster/wrench_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + to_chat(user, "Now [anchored ? "un" : ""]securing [name]") + if(!I.use_tool(src, user, 60, volume = I.tool_volume)) + return + playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) + if(stat & BROKEN) + to_chat(user, "The broken remains of [src] fall on the ground.") + new /obj/item/stack/sheet/metal(loc, 5) + new /obj/item/shard(loc) + new /obj/item/shard(loc) + else + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + new /obj/item/mounted/frame/newscaster_frame(loc) + qdel(src) + +/obj/machinery/newscaster/welder_act(mob/user, obj/item/I) + . = TRUE + if(!I.tool_use_check(user, 0)) + return + default_welder_repair(user, I) + +/obj/machinery/newscaster/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(stat & BROKEN) + playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, TRUE) + else + playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE) + if(BURN) + playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) + +/obj/machinery/newscaster/deconstruct(disassembled = TRUE) + if(!(flags & NODECONSTRUCT)) + new /obj/item/stack/sheet/metal(loc, 2) + new /obj/item/shard(loc) + new /obj/item/shard(loc) + qdel(src) + +/obj/machinery/newscaster/obj_break() + if(!(stat & BROKEN) && !(flags & NODECONSTRUCT)) + stat |= BROKEN + playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE) + update_icon() + /obj/machinery/newscaster/attack_ghost(mob/user) tgui_interact(user) @@ -117,7 +175,7 @@ /obj/machinery/newscaster/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) if(can_scan(user)) - scanned_user = get_scanned_user(user) + scanned_user = get_scanned_user(user)["name"] ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "Newscaster", name, 800, 600) @@ -130,6 +188,7 @@ data["is_security"] = is_security data["is_admin"] = user.can_admin_interact() data["is_silent"] = is_silent + data["is_printing"] = is_printing data["screen"] = screen data["modal"] = tgui_modal_data(src) if(data["modal"] && !isnull(data["modal"]["args"]["is_admin"])) @@ -141,7 +200,7 @@ data["wanted"] = get_message_data(GLOB.news_network.wanted_issue, user)[1] data["world_time"] = world.time - var/user_name = get_scanned_user(usr) + var/user_name = get_scanned_user(user)["name"] switch(screen) if(NEWSCASTER_HEADLINES, NEWSCASTER_CHANNEL) // Get the list of stories to pick from - either all or from a specific channel depending on the screen @@ -177,19 +236,18 @@ continue last_views[user_name][C.UID()] = now if(NEWSCASTER_PRINT) - // TODO - // var/total_num = length(GLOB.news_network.channels) - // var/active_num = total_num - // var/message_num=0 - // for(var/datum/feed_channel/FC in GLOB.news_network.channels) - // if(!FC.censored) - // message_num += length(FC.messages) - // else - // active_num-- - // data["total_num"] = total_num - // data["active_num"] = active_num - // data["message_num"] = message_num - // data["paper_remaining"] = paper_remaining * 100 + var/total_num = length(GLOB.news_network.channels) + var/active_num = total_num + var/message_num=0 + for(var/datum/feed_channel/FC in GLOB.news_network.channels) + if(!FC.censored) + message_num += length(FC.messages) + else + active_num-- + data["total_num"] = total_num + data["active_num"] = active_num + data["message_num"] = message_num + data["paper_remaining"] = paper_remaining * 100 if(NEWSCASTER_JOBS) var/list/jobs = list() data["jobs"] = jobs @@ -197,7 +255,7 @@ jobs[cat] = list() for(var/datum/job/job in SSjobs.occupations) - if(job_blacklisted(job)) + if(job.type in jobblacklist) continue if(job.is_position_available()) var/list/opening_data = list("title" = job.title) @@ -221,7 +279,7 @@ jobs["supply"] += opening_data // Append temp photo - if(photo && data["modal"] && data["modal"]["id"] in list("create_story", "wanted_notice")) + if(photo && data["modal"] && (data["modal"]["id"] in list("create_story", "wanted_notice"))) data["photo"] = list( name = photo.name, uid = photo.UID(), @@ -243,6 +301,7 @@ icon = C.icon, public = C.is_public, frozen = C.frozen, + censored = C.censored, admin = C.admin_locked, unread = 0, ) @@ -331,19 +390,19 @@ if("eject_photo") eject_photo(usr) return FALSE // Updating handled in that proc - if("freeze_channel") - if(is_security && !has_security_access(usr)) + if("censor_channel") + if(is_security && !get_scanned_user(usr)["security"]) set_temp("You do not have permission to perform this action. Please ensure your ID has appropiate access.", "danger") return var/datum/feed_channel/FC = locateUID(params["uid"]) if(!istype(FC)) return if(FC.admin_locked && !usr.can_admin_interact()) - set_temp("This channel has been locked by CentComm and thus cannot be (un)frozen.", "danger") + set_temp("This channel has been locked by CentComm and thus cannot be (un)censored.", "danger") return - FC.frozen = !FC.frozen + FC.censored = !FC.censored if("censor_author", "censor_story") - if(is_security && !has_security_access(usr)) + if(is_security && !get_scanned_user(usr)["security"]) set_temp("You do not have permission to perform this action. Please ensure your ID has appropiate access.", "danger") return var/datum/feed_message/FM = locateUID(params["uid"]) @@ -359,7 +418,7 @@ else return FALSE if("clear_wanted_notice") - if(is_security && !has_security_access(usr)) + if(is_security && !get_scanned_user(usr)["security"]) set_temp("You do not have permission to perform this action. Please ensure your ID has appropiate access.", "danger") return var/datum/feed_message/WN = GLOB.news_network.wanted_issue @@ -373,6 +432,13 @@ return FALSE if("toggle_mute") is_silent = !is_silent + if("print_newspaper") + if(is_printing) + return + if(paper_remaining <= 0) + set_temp("There is no more paper available.", "danger") + return + print_newspaper() else return FALSE @@ -396,7 +462,7 @@ // If trying to manage the channel, make sure the user is allowed to! if(id == "manage_channel") var/datum/feed_channel/FC = locateUID(arguments["uid"]) - if(!istype(FC) || !FC.can_modify(usr, get_scanned_user(usr))) + if(!istype(FC) || !FC.can_modify(usr, get_scanned_user(usr)["name"])) return tgui_modal_message(src, id, "", arguments = list( uid = arguments["uid"], // Only when managing a channel @@ -429,7 +495,9 @@ if(GLOB.news_network.get_channel_by_name(name)) set_temp("A channel with this name already exists.", "danger") return - // TODO: check if author already has made a channel or not + if(GLOB.news_network.get_channel_by_author(author)) + set_temp("A channel with this author name already exists.", "danger") + return FC = new GLOB.news_network.channels += FC feedback_inc("newscaster_channels", 1) @@ -438,7 +506,7 @@ viewing_channel = FC else if (id == "manage_channel") // Channel management FC = locateUID(arguments["uid"]) - if(!FC || !FC.can_modify(usr, get_scanned_user(usr))) + if(!FC || !FC.can_modify(usr, get_scanned_user(usr)["name"])) return // Add/update the information FC.channel_name = copytext(name, 1, CHANNEL_NAME_MAX_LENGTH) @@ -457,7 +525,7 @@ if(!length(author) || !length(title) || !length(body)) return // Find the named channel the user is trying to publish a story to - var/user_name = get_scanned_user(usr) + var/user_name = get_scanned_user(usr)["name"] var/datum/feed_channel/FC for(var/fc in GLOB.news_network.channels) var/datum/feed_channel/_FC = fc @@ -553,277 +621,71 @@ if(update_now) SStgui.update_uis(src) -/obj/machinery/newscaster/wrench_act(mob/user, obj/item/I) - . = TRUE - if(!I.tool_use_check(user, 0)) - return - to_chat(user, "Now [anchored ? "un" : ""]securing [name]") - if(!I.use_tool(src, user, 60, volume = I.tool_volume)) - return - playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) - if(stat & BROKEN) - to_chat(user, "The broken remains of [src] fall on the ground.") - new /obj/item/stack/sheet/metal(loc, 5) - new /obj/item/shard(loc) - new /obj/item/shard(loc) - else - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - new /obj/item/mounted/frame/newscaster_frame(loc) - qdel(src) - -/obj/machinery/newscaster/welder_act(mob/user, obj/item/I) - . = TRUE - if(!I.tool_use_check(user, 0)) - return - default_welder_repair(user, I) - -/obj/machinery/newscaster/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0) - switch(damage_type) - if(BRUTE) - if(stat & BROKEN) - playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, TRUE) - else - playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE) - if(BURN) - playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) - -/obj/machinery/newscaster/deconstruct(disassembled = TRUE) - if(!(flags & NODECONSTRUCT)) - new /obj/item/stack/sheet/metal(loc, 2) - new /obj/item/shard(loc) - new /obj/item/shard(loc) - qdel(src) - -/obj/machinery/newscaster/obj_break() - if(!(stat & BROKEN) && !(flags & NODECONSTRUCT)) - stat |= BROKEN - playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE) - update_icon() - -/obj/machinery/newscaster/proc/AttachPhoto(mob/user) - if(photo) - if(!issilicon(user)) - photo.forceMove(get_turf(src)) - user.put_in_inactive_hand(photo) - photo = null - if(istype(user.get_active_hand(), /obj/item/photo)) - photo = user.get_active_hand() - user.drop_item() - photo.forceMove(src) - else if(issilicon(user)) - var/mob/living/silicon/tempAI = user - var/obj/item/camera/siliconcam/camera = tempAI.aiCamera - - if(!camera) - return - var/datum/picture/selection = camera.selectpicture() - if(!selection) - return - - var/obj/item/photo/P = new/obj/item/photo() - P.construct(selection) - photo = P - - -//######################################################################################################################## -//###################################### NEWSPAPER! ###################################################################### -//######################################################################################################################## - -/obj/item/newspaper - name = "newspaper" - desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations." - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "newspaper" - w_class = WEIGHT_CLASS_SMALL //Let's make it fit in trashbags! - attack_verb = list("bapped") - var/screen = 0 - var/pages = 0 - var/curr_page = 0 - var/list/datum/feed_channel/news_content = list() - var/datum/feed_message/important_message = null - var/scribble="" - var/scribble_page = null - -/obj/item/newspaper/attack_self(mob/user as mob) - if(ishuman(user)) - var/mob/living/carbon/human/human_user = user - var/dat - pages = 0 - switch(screen) - if(0) //Cover - dat+="

"
- else
- dat+="None"
- else
- dat+="Apart from some uninteresting Classified ads, there's nothing on this page..."
- if(scribble_page==curr_page)
- dat+="
"
+ else
+ dat += "None"
+ else
+ dat += "Apart from some uninteresting Classified ads, there's nothing on this page..."
+ if(scribble_page==curr_page)
+ dat += "