diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 69d5a23bb2b..f0dc1c3c720 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -46,6 +46,10 @@ RestrainedClickOn(A) return */ + if(aicamera.in_camera_mode) //Cyborg picture taking + aicamera.camera_mode_off() + aicamera.captureimage(A, usr) + return var/obj/item/W = get_active_hand() diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 3f0695d07ae..6be391c1312 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -59,6 +59,20 @@ var/const/BORG_WIRE_CAMERA = 16 if(new_ai && (new_ai != R.connected_ai)) R.connected_ai = new_ai R.notify_ai(1) + var/numberer = 1 // Send images the Cyborg has taken to the AI's album upon sync. + for(var/datum/picture/z in R.aicamera.aipictures) + for(var/datum/picture/t in R.connected_ai.aicamera.aipictures) //Hopefully to prevent someone spamming images to silicons, by spamming this wire + if((z.fields["pixel_y"] != t.fields["pixel_y"]) && (z.fields["pixel_x"] != t.fields["pixel_x"])) //~2.26 out of 1000 chance this will stop something it shouldn't + var/datum/picture/p = new() + p = z + p.fields["name"] = "Uploaded Image [numberer] (synced from [R.name])" + R.connected_ai.aicamera.aipictures += p + else + continue + numberer++ + if(R.aicamera.aipictures.len > 0) + R << "Locally saved images synced with AI. Images were retained in local database in case of loss of connection with the AI." + if (BORG_WIRE_CAMERA) if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes) diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index afaca2f0e76..c9837d90924 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -1,1030 +1,1054 @@ -//############################################## -//################### NEWSCASTERS BE HERE! #### -//###-Agouri################################### - -/datum/feed_message - var/author ="" - var/body ="" - //var/parent_channel - var/backup_body ="" - var/backup_author ="" - var/is_admin_message = 0 - var/icon/img = null - var/time_stamp = "" - -/datum/feed_channel - var/channel_name="" - var/list/datum/feed_message/messages = list() - //var/message_count = 0 - var/locked=0 - var/author="" - var/backup_author="" - var/censored=0 - var/is_admin_channel=0 - //var/page = null //For newspapers - -/datum/feed_message/proc/clear() - src.author = "" - src.body = "" - src.backup_body = "" - src.backup_author = "" - src.img = null - -/datum/feed_channel/proc/clear() - src.channel_name = "" - src.messages = list() - src.locked = 0 - src.author = "" - src.backup_author = "" - src.censored = 0 - src.is_admin_channel = 0 - -/datum/feed_network - var/list/datum/feed_channel/network_channels = list() - var/datum/feed_message/wanted_issue - -/datum/feed_network/New() - CreateFeedChannel("Central Command", "Centcom Official", 1) - -/datum/feed_network/proc/CreateFeedChannel(var/channel_name, var/author, var/locked, var/adminChannel = 0) - var/datum/feed_channel/newChannel = new /datum/feed_channel - newChannel.channel_name = channel_name - newChannel.author = author - newChannel.locked = locked - newChannel.is_admin_channel = adminChannel - network_channels += newChannel - -/datum/feed_network/proc/SubmitArticle(var/msg, var/author, var/channel_name, var/obj/item/weapon/photo/photo, var/adminMessage = 0) - var/datum/feed_message/newMsg = new /datum/feed_message - newMsg.author = author - newMsg.body = msg - newMsg.time_stamp = "[worldtime2text()]" - newMsg.is_admin_message = adminMessage - if(photo) - newMsg.img = photo.img - for(var/datum/feed_channel/FC in network_channels) - if(FC.channel_name == channel_name) - FC.messages += newMsg //Adding message to the network's appropriate feed_channel - break - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.newsAlert(channel_name) - - -var/datum/feed_network/news_network = new /datum/feed_network //The global news-network, which is coincidentally a global list. - -var/list/obj/machinery/newscaster/allCasters = list() //Global list that will contain reference to all newscasters in existence. - - -/obj/item/newscaster_frame - name = "newscaster frame" - desc = "Used to build newscasters, just secure to the wall." - icon_state = "newscaster" - item_state = "syringe_kit" - m_amt = 14000 - g_amt = 8000 - -/obj/item/newscaster_frame/proc/try_build(turf/on_wall) - if (get_dist(on_wall,usr)>1) - return - var/ndir = get_dir(usr,on_wall) - if (!(ndir in cardinal)) - return - var/turf/loc = get_turf(usr) - var/area/A = loc.loc - if (!istype(loc, /turf/simulated/floor)) - usr << "Newscaster cannot be placed on this spot." - return - if (A.requires_power == 0 || A.name == "Space") - usr << "Newscaster cannot be placed in this area." - return - for(var/obj/machinery/newscaster/T in loc) - usr << "There is another newscaster here." - return - var/obj/machinery/newscaster/N = new(loc) - N.pixel_y -= (loc.y - on_wall.y) * 32 - N.pixel_x -= (loc.x - on_wall.x) * 32 - qdel(src) - - - - -/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!" - icon = 'icons/obj/terminals.dmi' - icon_state = "newscaster_normal" - var/isbroken = 0 //1 if someone banged it with something heavy - var/ispowered = 1 //starts powered, changes with power_change() - //var/list/datum/feed_channel/channel_list = list() //This list will contain the names of the feed channels. Each name will refer to a data region where the messages of the feed channels are stored. - //OBSOLETE: We're now using a global news network - var/screen = 0 - // 0 = welcome screen - main menu - // 1 = view feed channels - // 2 = create feed channel - // 3 = create feed story - // 4 = feed story submited sucessfully - // 5 = feed channel created successfully - // 6 = ERROR: Cannot create feed story - // 7 = ERROR: Cannot create feed channel - // 8 = print newspaper - // 9 = viewing channel feeds - // 10 = censor feed story - // 11 = censor feed channel - //Holy shit this is outdated, made this when I was still starting newscasters :3 - var/paper_remaining = 0 - var/securityCaster = 0 - // 0 = Caster cannot be used to issue wanted posters - // 1 = the opposite - var/unit_no = 0 //Each newscaster has a unit number - //var/datum/feed_message/wanted //We're gonna use a feed_message to store data of the wanted person because fields are similar - //var/wanted_issue = 0 //OBSOLETE - // 0 = there's no WANTED issued, we don't need a special icon_state - // 1 = Guess what. - var/alert_delay = 500 - var/alert = 0 - // 0 = there hasn't been a news/wanted update in the last alert_delay - // 1 = there has - var/scanned_user = "Unknown" //Will contain the name of the person who currently uses the newscaster - var/msg = ""; //Feed message - var/obj/item/weapon/photo/photo = null - var/channel_name = ""; //the feed channel which will be receiving the feed, or being created - var/c_locked=0; //Will our new channel be locked to public submissions? - var/hitstaken = 0 //Death at 3 hits from an item with force>=15 - var/datum/feed_channel/viewing_channel = null - luminosity = 0 - anchored = 1 - - -/obj/machinery/newscaster/security_unit //Security unit - name = "security newscaster" - securityCaster = 1 - -/obj/machinery/newscaster/New() - allCasters += src - src.paper_remaining = 15 - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - src.unit_no++ - src.update_icon() //for any custom ones on the map... - ..() //I just realised the newscasters weren't in the global machines list. The superconstructor call will tend to that - -/obj/machinery/newscaster/Destroy() - allCasters -= src - ..() - -/obj/machinery/newscaster/update_icon() - if(!ispowered || isbroken) - icon_state = "newscaster_off" - if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite. - src.overlays.Cut() - src.overlays += image(src.icon, "crack3") - return - - src.overlays.Cut() //reset overlays - - if(news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message - icon_state = "newscaster_wanted" - return - - if(alert) //new message alert overlay - src.overlays += "newscaster_alert" - - if(hitstaken > 0) //Cosmetic damage overlay - src.overlays += image(src.icon, "crack[hitstaken]") - - icon_state = "newscaster_normal" - return - -/obj/machinery/newscaster/power_change() - if(isbroken) //Broken shit can't be powered. - return - if( src.powered() ) - src.ispowered = 1 - stat &= ~NOPOWER - src.update_icon() - else - spawn(rand(0, 15)) - src.ispowered = 0 - stat |= NOPOWER - src.update_icon() - - -/obj/machinery/newscaster/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - src.isbroken=1 - if(prob(50)) - qdel(src) - else - src.update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in. - return - else - if(prob(50)) - src.isbroken=1 - src.update_icon() - return - return - -/obj/machinery/newscaster/attack_ai(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/newscaster/attack_hand(mob/user as mob) //########### THE MAIN BEEF IS HERE! And in the proc below this...############ - if(!src.ispowered || src.isbroken) - return - if(istype(user, /mob/living/carbon/human) || istype(user,/mob/living/silicon) ) - var/mob/living/human_or_robot_user = user - var/dat - - src.scan_user(human_or_robot_user) //Newscaster scans you - - switch(screen) - if(0) - dat += "Welcome to Newscasting Unit #[src.unit_no].
Interface & News networks Operational." - dat += "
Property of Nanotransen Inc" - if(news_network.wanted_issue) - dat+= "
Read Wanted Issue" - dat+= "

Create Feed Channel" - dat+= "
View Feed Channels" - dat+= "
Submit new Feed story" - dat+= "
Print newspaper" - dat+= "
Re-scan User" - dat+= "

Exit" - if(src.securityCaster) - var/wanted_already = 0 - if(news_network.wanted_issue) - wanted_already = 1 - - dat+="
Feed Security functions:
" - dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue" - dat+="
Censor Feed Stories" - dat+="
Mark Feed Channel with Nanotrasen D-Notice" - dat+="

The newscaster recognises you as: [src.scanned_user]" - if(1) - dat+= "Station Feed Channels
" - if( isemptylist(news_network.network_channels) ) - dat+="No active channels found..." - else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) - if(CHANNEL.is_admin_channel) - dat+="[CHANNEL.channel_name]
" - else - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - /*for(var/datum/feed_channel/CHANNEL in src.channel_list) - dat+="[CHANNEL.channel_name]:
\[created by: [CHANNEL.author]\]

" - if( isemptylist(CHANNEL.messages) ) - dat+="No feed messages found in channel...

" - else - for(var/datum/feed_message/MESSAGE in CHANNEL.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"*/ - - dat+="

Refresh" - dat+="
Back" - if(2) - dat+="Creating new Feed Channel..." - dat+="
Channel Name: [src.channel_name]
" - dat+="Channel Author: [src.scanned_user]
" - dat+="Will Accept Public Feeds: [(src.c_locked) ? ("NO") : ("YES")]

" - dat+="
Submit

Cancel
" - if(3) - dat+="Creating new Feed Message..." - dat+="
Receiving Channel: [src.channel_name]
" //MARK - dat+="Message Author: [src.scanned_user]
" - dat+="Message Body: [src.msg]
" - dat+="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")]
" - dat+="
Submit

Cancel
" - if(4) - dat+="Feed story successfully submitted to [src.channel_name].

" - dat+="
Return
" - if(5) - dat+="Feed Channel [src.channel_name] created successfully.

" - dat+="
Return
" - if(6) - dat+="ERROR: Could not submit Feed story to Network.

" - if(src.channel_name=="") - dat+="•Invalid receiving channel name.
" - if(src.scanned_user=="Unknown") - dat+="•Channel author unverified.
" - if(src.msg == "" || src.msg == "\[REDACTED\]") - dat+="•Invalid message body.
" - - dat+="
Return
" - if(7) - dat+="ERROR: Could not submit Feed Channel to Network.

" - //var/list/existing_channels = list() //Let's get dem existing channels - OBSOLETE - var/list/existing_authors = list() - for(var/datum/feed_channel/FC in news_network.network_channels) - //existing_channels += FC.channel_name //OBSOLETE - if(FC.author == "\[REDACTED\]") - existing_authors += FC.backup_author - else - existing_authors += FC.author - if(src.scanned_user in existing_authors) - dat+="•There already exists a Feed channel under your name.
" - if(src.channel_name=="" || src.channel_name == "\[REDACTED\]") - dat+="•Invalid channel name.
" - var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.channel_name) - check = 1 - break - if(check) - dat+="•Channel name already in use.
" - if(src.scanned_user=="Unknown") - dat+="•Channel author unverified.
" - dat+="
Return
" - if(8) - var/total_num=length(news_network.network_channels) - var/active_num=total_num - var/message_num=0 - for(var/datum/feed_channel/FC in news_network.network_channels) - if(!FC.censored) - message_num += length(FC.messages) //Dont forget, datum/feed_channel's var messages is a list of datum/feed_message - else - active_num-- - dat+="Network currently serves a total of [total_num] Feed channels, [active_num] of which are active, and a total of [message_num] Feed Stories." //TODO: CONTINUE - dat+="

Liquid Paper remaining: [(src.paper_remaining) *100 ] cm^3" - dat+="

Print Paper" - dat+="
Cancel" - if(9) - dat+="[src.viewing_channel.channel_name]: \[created by: [src.viewing_channel.author]\]
" - if(src.viewing_channel.censored) - dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" - dat+="No further feed story additions are allowed while the D-Notice is in effect.

" - else - if( isemptylist(src.viewing_channel.messages) ) - dat+="No feed messages found in channel...
" - else - var/i = 0 - for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) - i++ - dat+="-[MESSAGE.body]
" - if(MESSAGE.img) - usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") - dat+="

" - dat+="\[Story by [MESSAGE.author] \] - ([MESSAGE.time_stamp])
" - dat+="

Refresh" - dat+="
Back" - if(10) - dat+="Nanotrasen Feed Censorship Tool
" - dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
" - dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
" - dat+="
Select Feed channel to get Stories from:
" - if(isemptylist(news_network.network_channels)) - dat+="No feed channels found active...
" - else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - dat+="
Cancel" - if(11) - dat+="Nanotrasen D-Notice Handler
" - dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's" - dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed" - dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
" - if(isemptylist(news_network.network_channels)) - dat+="No feed channels found active...
" - else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - - dat+="
Back" - if(12) - dat+="[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
" - dat+="[(src.viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
" - - - if( isemptylist(src.viewing_channel.messages) ) - dat+="No feed messages found in channel...
" - else - for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" - dat+="[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
" - dat+="
Back" - if(13) - dat+="[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
" - dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
" - if(src.viewing_channel.censored) - dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" - dat+="No further feed story additions are allowed while the D-Notice is in effect.

" - else - if( isemptylist(src.viewing_channel.messages) ) - dat+="No feed messages found in channel...
" - else - for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" - - dat+="
Back" - if(14) - dat+="Wanted Issue Handler:" - var/wanted_already = 0 - var/end_param = 1 - if(news_network.wanted_issue) - wanted_already = 1 - end_param = 2 - - if(wanted_already) - dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below.
" - dat+="
" - dat+="Criminal Name: [src.channel_name]
" - dat+="Description: [src.msg]
" - dat+="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")]
" - if(wanted_already) - dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
" - else - dat+="Wanted Issue will be created under prosecutor: [src.scanned_user]
" - dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]" - if(wanted_already) - dat+="
Take down Issue" - dat+="
Cancel" - if(15) - dat+="Wanted issue for [src.channel_name] is now in Network Circulation.

" - dat+="
Return
" - if(16) - dat+="ERROR: Wanted Issue rejected by Network.

" - if(src.channel_name=="" || src.channel_name == "\[REDACTED\]") - dat+="•Invalid name for person wanted.
" - if(src.scanned_user=="Unknown") - dat+="•Issue author unverified.
" - if(src.msg == "" || src.msg == "\[REDACTED\]") - dat+="•Invalid description.
" - dat+="
Return
" - if(17) - dat+="Wanted Issue successfully deleted from Circulation
" - dat+="
Return
" - if(18) - if(news_network.wanted_issue) - dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [news_network.wanted_issue.backup_author]\]
" - dat+="Criminal: [news_network.wanted_issue.author]
" - dat+="Description: [news_network.wanted_issue.body]
" - dat+="Photo:: " - if(news_network.wanted_issue.img) - usr << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png") - dat+="
" - else - dat+="None" - else - dat+="No current wanted issue found.

" - dat+="

Back
" - if(19) - dat+="Wanted issue for [src.channel_name] successfully edited.

" - dat+="
Return
" - if(20) - dat+="Printing successful. Please receive your newspaper from the bottom of the machine.

" - dat+="Return" - if(21) - dat+="Unable to print newspaper. Insufficient paper. Please notify maintenance personnel to refill machine storage.

" - dat+="Return" - else - dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" - - //human_or_robot_user << browse(dat, "window=newscaster_main;size=400x600") - //onclose(human_or_robot_user, "newscaster_main") - - var/datum/browser/popup = new(human_or_robot_user, "newscaster_main", "Newscaster Unit #[src.unit_no]", 400, 600) - popup.set_content(dat) - popup.set_title_image(human_or_robot_user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/newscaster/Topic(href, href_list) - if(..()) - return - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - if(href_list["set_channel_name"]) - src.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) - while (findtext(src.channel_name," ") == 1) - src.channel_name = copytext(src.channel_name,2,lentext(src.channel_name)+1) - src.updateUsrDialog() - //src.update_icon() - - else if(href_list["set_channel_lock"]) - src.c_locked = !src.c_locked - src.updateUsrDialog() - //src.update_icon() - - else if(href_list["submit_new_channel"]) - var/list/existing_authors = list() - for(var/datum/feed_channel/FC in news_network.network_channels) - //existing_channels += FC.channel_name - if(FC.author == "\[REDACTED\]") - existing_authors += FC.backup_author - else - existing_authors +=FC.author - var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.channel_name) - check = 1 - break - if(src.channel_name == "" || src.channel_name == "\[REDACTED\]" || src.scanned_user == "Unknown" || check || (src.scanned_user in existing_authors) ) - src.screen=7 - else - var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel") - if(choice=="Confirm") - news_network.CreateFeedChannel(src.channel_name, src.scanned_user, c_locked) - feedback_inc("newscaster_channels",1) - src.screen=5 - src.updateUsrDialog() - //src.update_icon() - - else if(href_list["set_channel_receiving"]) - //var/list/datum/feed_channel/available_channels = list() - var/list/available_channels = list() - for(var/datum/feed_channel/F in news_network.network_channels) - if( (!F.locked || F.author == scanned_user) && !F.censored) - available_channels += F.channel_name - src.channel_name = input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels - src.updateUsrDialog() - - else if(href_list["set_new_message"]) - src.msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", "")) - while (findtext(src.msg," ") == 1) - src.msg = copytext(src.msg,2,lentext(src.msg)+1) - src.updateUsrDialog() - - else if(href_list["set_attachment"]) - AttachPhoto(usr) - src.updateUsrDialog() - - else if(href_list["submit_new_message"]) - if(src.msg =="" || src.msg=="\[REDACTED\]" || src.scanned_user == "Unknown" || src.channel_name == "" ) - src.screen=6 - else - news_network.SubmitArticle(msg, scanned_user, channel_name, photo) - feedback_inc("newscaster_stories",1) - src.screen=4 - src.updateUsrDialog() - - else if(href_list["create_channel"]) - src.screen=2 - src.updateUsrDialog() - - else if(href_list["create_feed_story"]) - src.screen=3 - src.updateUsrDialog() - - else if(href_list["menu_paper"]) - src.screen=8 - src.updateUsrDialog() - else if(href_list["print_paper"]) - if(!src.paper_remaining) - src.screen=21 - else - src.print_paper() - src.screen = 20 - src.updateUsrDialog() - - else if(href_list["menu_censor_story"]) - src.screen=10 - src.updateUsrDialog() - - else if(href_list["menu_censor_channel"]) - src.screen=11 - src.updateUsrDialog() - - else if(href_list["menu_wanted"]) - var/already_wanted = 0 - if(news_network.wanted_issue) - already_wanted = 1 - - if(already_wanted) - src.channel_name = news_network.wanted_issue.author - src.msg = news_network.wanted_issue.body - src.screen = 14 - src.updateUsrDialog() - - else if(href_list["set_wanted_name"]) - src.channel_name = strip_html(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) - while (findtext(src.channel_name," ") == 1) - src.channel_name = copytext(src.channel_name,2,lentext(src.channel_name)+1) - src.updateUsrDialog() - - else if(href_list["set_wanted_desc"]) - src.msg = strip_html(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) - while (findtext(src.msg," ") == 1) - src.msg = copytext(src.msg,2,lentext(src.msg)+1) - src.updateUsrDialog() - - else if(href_list["submit_wanted"]) - var/input_param = text2num(href_list["submit_wanted"]) - if(src.msg == "" || src.channel_name == "" || src.scanned_user == "Unknown") - src.screen = 16 - else - var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel") - if(choice=="Confirm") - if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below - var/datum/feed_message/WANTED = new /datum/feed_message - WANTED.author = src.channel_name - WANTED.body = src.msg - WANTED.backup_author = src.scanned_user //I know, a bit wacky - if(photo) - WANTED.img = photo.img - news_network.wanted_issue = WANTED - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.newsAlert() - NEWSCASTER.update_icon() - src.screen = 15 - else - if(news_network.wanted_issue.is_admin_message) - alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok") - return - news_network.wanted_issue.author = src.channel_name - news_network.wanted_issue.body = src.msg - news_network.wanted_issue.backup_author = src.scanned_user - if(photo) - news_network.wanted_issue.img = photo.img - src.screen = 19 - - src.updateUsrDialog() - - else if(href_list["cancel_wanted"]) - if(news_network.wanted_issue.is_admin_message) - alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot take it down.","Ok") - return - var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel") - if(choice=="Confirm") - news_network.wanted_issue = null - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.update_icon() - src.screen=17 - src.updateUsrDialog() - - else if(href_list["view_wanted"]) - src.screen=18 - src.updateUsrDialog() - else if(href_list["censor_channel_author"]) - var/datum/feed_channel/FC = locate(href_list["censor_channel_author"]) - if(FC.is_admin_channel) - alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok") - return - if(FC.author != "\[REDACTED\]") - FC.backup_author = FC.author - FC.author = "\[REDACTED\]" - else - FC.author = FC.backup_author - src.updateUsrDialog() - - else if(href_list["censor_channel_story_author"]) - var/datum/feed_message/MSG = locate(href_list["censor_channel_story_author"]) - if(MSG.is_admin_message) - alert("This message was created by a Nanotrasen Officer. You cannot censor its author.","Ok") - return - if(MSG.author != "\[REDACTED\]") - MSG.backup_author = MSG.author - MSG.author = "\[REDACTED\]" - else - MSG.author = MSG.backup_author - src.updateUsrDialog() - - else if(href_list["censor_channel_story_body"]) - var/datum/feed_message/MSG = locate(href_list["censor_channel_story_body"]) - if(MSG.is_admin_message) - alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok") - return - if(MSG.body != "\[REDACTED\]") - MSG.backup_body = MSG.body - MSG.body = "\[REDACTED\]" - else - MSG.body = MSG.backup_body - src.updateUsrDialog() - - else if(href_list["pick_d_notice"]) - var/datum/feed_channel/FC = locate(href_list["pick_d_notice"]) - src.viewing_channel = FC - src.screen=13 - src.updateUsrDialog() - - else if(href_list["toggle_d_notice"]) - var/datum/feed_channel/FC = locate(href_list["toggle_d_notice"]) - if(FC.is_admin_channel) - alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok") - return - FC.censored = !FC.censored - src.updateUsrDialog() - - else if(href_list["view"]) - src.screen=1 - src.updateUsrDialog() - - else if(href_list["setScreen"]) //Brings us to the main menu and resets all fields~ - src.screen = text2num(href_list["setScreen"]) - if (src.screen == 0) - src.scanned_user = "Unknown"; - msg = ""; - src.c_locked=0; - channel_name=""; - src.viewing_channel = null - src.updateUsrDialog() - - else if(href_list["show_channel"]) - var/datum/feed_channel/FC = locate(href_list["show_channel"]) - src.viewing_channel = FC - src.screen = 9 - src.updateUsrDialog() - - else if(href_list["pick_censor_channel"]) - var/datum/feed_channel/FC = locate(href_list["pick_censor_channel"]) - src.viewing_channel = FC - src.screen = 12 - src.updateUsrDialog() - - else if(href_list["refresh"]) - src.updateUsrDialog() - - -/obj/machinery/newscaster/attackby(obj/item/I as obj, mob/user as mob) - -/* if (istype(I, /obj/item/weapon/card/id) || istype(I, /obj/item/device/pda) ) //Name verification for channels or messages - if(src.screen == 4 || src.screen == 5) - if( istype(I, /obj/item/device/pda) ) - var/obj/item/device/pda/P = I - if(P.id) - src.scanned_user = "[P.id.registered_name] ([P.id.assignment])" - src.screen=2 - else - var/obj/item/weapon/card/id/T = I - src.scanned_user = text("[T.registered_name] ([T.assignment])") - src.screen=2*/ //Obsolete after autorecognition - - if(istype(I, /obj/item/weapon/wrench)) - user << "Now [anchored ? "un" : ""]securing [name]" - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, 60)) - new /obj/item/newscaster_frame(loc) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src) - return - - if (src.isbroken) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, 1) - for (var/mob/O in hearers(5, src.loc)) - O.show_message("[user.name] further abuses the shattered [src.name].") - else - if(istype(I, /obj/item/weapon) ) - var/obj/item/weapon/W = I - if(W.force <15) - for (var/mob/O in hearers(5, src.loc)) - O.show_message("[user.name] hits the [src.name] with the [W.name] with no visible effect." ) - playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1) - else - src.hitstaken++ - if(src.hitstaken==3) - for (var/mob/O in hearers(5, src.loc)) - O.show_message("[user.name] smashes the [src.name]!" ) - src.isbroken=1 - playsound(src.loc, 'sound/effects/Glassbr3.ogg', 100, 1) - else - for (var/mob/O in hearers(5, src.loc)) - O.show_message("[user.name] forcefully slams the [src.name] with the [I.name]!" ) - playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1) - else - user << "This does nothing." - src.update_icon() - - -/obj/machinery/newscaster/attack_paw(mob/user as mob) - user << "The newscaster controls are far too complicated for your tiny brain!" - return - -/obj/machinery/newscaster/proc/AttachPhoto(mob/user as mob) - if(photo) - photo.loc = src.loc - user.put_in_inactive_hand(photo) - photo = null - if(istype(user.get_active_hand(), /obj/item/weapon/photo)) - photo = user.get_active_hand() - user.drop_item() - photo.loc = src - if(istype(usr,/mob/living/silicon/ai)) - var/list/nametemp = list() - var/find - var/datum/picture/selection - var/mob/living/silicon/ai/tempAI = user - if(tempAI.aicamera.aipictures.len == 0) - usr << "No images saved" - return - for(var/datum/picture/t in tempAI.aicamera.aipictures) - nametemp += t.fields["name"] - find = input("Select image (numbered in order taken)") in nametemp - var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - for(var/datum/picture/q in tempAI.aicamera.aipictures) - if(q.fields["name"] == find) - selection = q - break // just in case some AI decides to take 10 thousand pictures in a round - P.icon = selection.fields["icon"] - P.img = selection.fields["img"] - P.desc = selection.fields["desc"] - photo = P - - - - - -//######################################################################################################################## -//###################################### NEWSPAPER! ###################################################################### -//######################################################################################################################## - -/obj/item/weapon/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 = 2 //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/weapon/newspaper/attack_hand(mob/user as mob) - ..() - world << "derp"*/ - -obj/item/weapon/newspaper/attack_self(mob/user as mob) - if(ishuman(user)) - var/mob/living/carbon/human/human_user = user - var/dat - src.pages = 0 - switch(screen) - if(0) //Cover - dat+="
The Griffon
" - dat+="
Nanotrasen-standard newspaper, for use on Nanotrasen© Space Facilities

" - if(isemptylist(src.news_content)) - if(src.important_message) - dat+="Contents:
" - else - dat+="Other than the title, the rest of the newspaper is unprinted..." - else - dat+="Contents:
" - if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" - dat+= "
Next Page
Done reading
" - if(1) // X channel pages inbetween. - for(var/datum/feed_channel/NP in src.news_content) - src.pages++ //Let's get it right again. - var/datum/feed_channel/C = src.news_content[src.curr_page] - dat+="[C.channel_name] \[created by: [C.author]\]

" - if(C.censored) - dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing." - else - if(isemptylist(C.messages)) - dat+="No Feed stories stem from this channel..." - else - dat+="" - if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" - dat+= "

Previous Page
Next Page
" - if(2) //Last page - for(var/datum/feed_channel/NP in src.news_content) - src.pages++ - if(src.important_message!=null) - dat+="
Wanted Issue:


" - dat+="Criminal name: [important_message.author]
" - dat+="Description: [important_message.body]
" - dat+="Photo:: " - if(important_message.img) - user << browse_rsc(important_message.img, "tmp_photow.png") - dat+="
" - else - dat+="None" - else - dat+="Apart from some uninteresting Classified ads, there's nothing on this page..." - if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" - dat+= "
Previous Page
" - else - dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" - - dat+="

[src.curr_page+1]
" - human_user << browse(dat, "window=newspaper_main;size=300x400") - onclose(human_user, "newspaper_main") - else - user << "The paper is full of intelligible symbols!" - - -obj/item/weapon/newspaper/Topic(href, href_list) - var/mob/living/U = usr - ..() - if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) )) - U.set_machine(src) - if(href_list["next_page"]) - if(curr_page==src.pages+1) - return //Don't need that at all, but anyway. - if(src.curr_page == src.pages) //We're at the middle, get to the end - src.screen = 2 - else - if(curr_page == 0) //We're at the start, get to the middle - src.screen=1 - src.curr_page++ - playsound(src.loc, "pageturn", 50, 1) - - else if(href_list["prev_page"]) - if(curr_page == 0) - return - if(curr_page == 1) - src.screen = 0 - - else - if(curr_page == src.pages+1) //we're at the end, let's go back to the middle. - src.screen = 1 - src.curr_page-- - playsound(src.loc, "pageturn", 50, 1) - - if (istype(src.loc, /mob)) - src.attack_self(src.loc) - - -obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/pen)) - if(src.scribble_page == src.curr_page) - user << "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?" - else - var/s = strip_html( input(user, "Write something", "Newspaper", "") ) - s = copytext(sanitize(s), 1, MAX_MESSAGE_LEN) - if (!s) - return - if (!in_range(src, usr) && src.loc != usr) - return - src.scribble_page = src.curr_page - src.scribble = s - src.attack_self(user) - return - - -////////////////////////////////////helper procs - - -/obj/machinery/newscaster/proc/scan_user(mob/living/user as mob) - if(istype(user,/mob/living/carbon/human)) //User is a human - var/mob/living/carbon/human/human_user = user - if(human_user.wear_id) //Newscaster scans you - if(istype(human_user.wear_id, /obj/item/device/pda) ) //autorecognition, woo! - var/obj/item/device/pda/P = human_user.wear_id - if(P.id) - src.scanned_user = "[P.id.registered_name] ([P.id.assignment])" - else - src.scanned_user = "Unknown" - else if(istype(human_user.wear_id, /obj/item/weapon/card/id) ) - var/obj/item/weapon/card/id/ID = human_user.wear_id - src.scanned_user ="[ID.registered_name] ([ID.assignment])" - else - src.scanned_user ="Unknown" - else - src.scanned_user ="Unknown" - else - var/mob/living/silicon/ai_user = user - src.scanned_user = "[ai_user.name] ([ai_user.job])" - - -/obj/machinery/newscaster/proc/print_paper() - feedback_inc("newscaster_newspapers_printed",1) - var/obj/item/weapon/newspaper/NEWSPAPER = new /obj/item/weapon/newspaper - for(var/datum/feed_channel/FC in news_network.network_channels) - NEWSPAPER.news_content += FC - if(news_network.wanted_issue) - NEWSPAPER.important_message = news_network.wanted_issue - NEWSPAPER.loc = get_turf(src) - src.paper_remaining-- - return - -//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later. -///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not -// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list. - -/obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile. - var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ - if(channel) - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"Breaking news from [channel]!\"",2) - src.alert = 1 - src.update_icon() - spawn(300) - src.alert = 0 - src.update_icon() - playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1) - else - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("[src.name] beeps, \"Attention! Wanted issue distributed!\"",2) - playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1) +//############################################## +//################### NEWSCASTERS BE HERE! #### +//###-Agouri################################### + +/datum/feed_message + var/author ="" + var/body ="" + //var/parent_channel + var/backup_body ="" + var/backup_author ="" + var/is_admin_message = 0 + var/icon/img = null + var/time_stamp = "" + +/datum/feed_channel + var/channel_name="" + var/list/datum/feed_message/messages = list() + //var/message_count = 0 + var/locked=0 + var/author="" + var/backup_author="" + var/censored=0 + var/is_admin_channel=0 + //var/page = null //For newspapers + +/datum/feed_message/proc/clear() + src.author = "" + src.body = "" + src.backup_body = "" + src.backup_author = "" + src.img = null + +/datum/feed_channel/proc/clear() + src.channel_name = "" + src.messages = list() + src.locked = 0 + src.author = "" + src.backup_author = "" + src.censored = 0 + src.is_admin_channel = 0 + +/datum/feed_network + var/list/datum/feed_channel/network_channels = list() + var/datum/feed_message/wanted_issue + +/datum/feed_network/New() + CreateFeedChannel("Central Command", "Centcom Official", 1) + +/datum/feed_network/proc/CreateFeedChannel(var/channel_name, var/author, var/locked, var/adminChannel = 0) + var/datum/feed_channel/newChannel = new /datum/feed_channel + newChannel.channel_name = channel_name + newChannel.author = author + newChannel.locked = locked + newChannel.is_admin_channel = adminChannel + network_channels += newChannel + +/datum/feed_network/proc/SubmitArticle(var/msg, var/author, var/channel_name, var/obj/item/weapon/photo/photo, var/adminMessage = 0) + var/datum/feed_message/newMsg = new /datum/feed_message + newMsg.author = author + newMsg.body = msg + newMsg.time_stamp = "[worldtime2text()]" + newMsg.is_admin_message = adminMessage + if(photo) + newMsg.img = photo.img + for(var/datum/feed_channel/FC in network_channels) + if(FC.channel_name == channel_name) + FC.messages += newMsg //Adding message to the network's appropriate feed_channel + break + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + NEWSCASTER.newsAlert(channel_name) + + +var/datum/feed_network/news_network = new /datum/feed_network //The global news-network, which is coincidentally a global list. + +var/list/obj/machinery/newscaster/allCasters = list() //Global list that will contain reference to all newscasters in existence. + + +/obj/item/newscaster_frame + name = "newscaster frame" + desc = "Used to build newscasters, just secure to the wall." + icon_state = "newscaster" + item_state = "syringe_kit" + m_amt = 14000 + g_amt = 8000 + +/obj/item/newscaster_frame/proc/try_build(turf/on_wall) + if (get_dist(on_wall,usr)>1) + return + var/ndir = get_dir(usr,on_wall) + if (!(ndir in cardinal)) + return + var/turf/loc = get_turf(usr) + var/area/A = loc.loc + if (!istype(loc, /turf/simulated/floor)) + usr << "Newscaster cannot be placed on this spot." + return + if (A.requires_power == 0 || A.name == "Space") + usr << "Newscaster cannot be placed in this area." + return + for(var/obj/machinery/newscaster/T in loc) + usr << "There is another newscaster here." + return + var/obj/machinery/newscaster/N = new(loc) + N.pixel_y -= (loc.y - on_wall.y) * 32 + N.pixel_x -= (loc.x - on_wall.x) * 32 + qdel(src) + + + + +/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!" + icon = 'icons/obj/terminals.dmi' + icon_state = "newscaster_normal" + var/isbroken = 0 //1 if someone banged it with something heavy + var/ispowered = 1 //starts powered, changes with power_change() + //var/list/datum/feed_channel/channel_list = list() //This list will contain the names of the feed channels. Each name will refer to a data region where the messages of the feed channels are stored. + //OBSOLETE: We're now using a global news network + var/screen = 0 + // 0 = welcome screen - main menu + // 1 = view feed channels + // 2 = create feed channel + // 3 = create feed story + // 4 = feed story submited sucessfully + // 5 = feed channel created successfully + // 6 = ERROR: Cannot create feed story + // 7 = ERROR: Cannot create feed channel + // 8 = print newspaper + // 9 = viewing channel feeds + // 10 = censor feed story + // 11 = censor feed channel + //Holy shit this is outdated, made this when I was still starting newscasters :3 + var/paper_remaining = 0 + var/securityCaster = 0 + // 0 = Caster cannot be used to issue wanted posters + // 1 = the opposite + var/unit_no = 0 //Each newscaster has a unit number + //var/datum/feed_message/wanted //We're gonna use a feed_message to store data of the wanted person because fields are similar + //var/wanted_issue = 0 //OBSOLETE + // 0 = there's no WANTED issued, we don't need a special icon_state + // 1 = Guess what. + var/alert_delay = 500 + var/alert = 0 + // 0 = there hasn't been a news/wanted update in the last alert_delay + // 1 = there has + var/scanned_user = "Unknown" //Will contain the name of the person who currently uses the newscaster + var/msg = ""; //Feed message + var/obj/item/weapon/photo/photo = null + var/channel_name = ""; //the feed channel which will be receiving the feed, or being created + var/c_locked=0; //Will our new channel be locked to public submissions? + var/hitstaken = 0 //Death at 3 hits from an item with force>=15 + var/datum/feed_channel/viewing_channel = null + luminosity = 0 + anchored = 1 + + +/obj/machinery/newscaster/security_unit //Security unit + name = "security newscaster" + securityCaster = 1 + +/obj/machinery/newscaster/New() + allCasters += src + src.paper_remaining = 15 + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + src.unit_no++ + src.update_icon() //for any custom ones on the map... + ..() //I just realised the newscasters weren't in the global machines list. The superconstructor call will tend to that + +/obj/machinery/newscaster/Destroy() + allCasters -= src + ..() + +/obj/machinery/newscaster/update_icon() + if(!ispowered || isbroken) + icon_state = "newscaster_off" + if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite. + src.overlays.Cut() + src.overlays += image(src.icon, "crack3") + return + + src.overlays.Cut() //reset overlays + + if(news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message + icon_state = "newscaster_wanted" + return + + if(alert) //new message alert overlay + src.overlays += "newscaster_alert" + + if(hitstaken > 0) //Cosmetic damage overlay + src.overlays += image(src.icon, "crack[hitstaken]") + + icon_state = "newscaster_normal" + return + +/obj/machinery/newscaster/power_change() + if(isbroken) //Broken shit can't be powered. + return + if( src.powered() ) + src.ispowered = 1 + stat &= ~NOPOWER + src.update_icon() + else + spawn(rand(0, 15)) + src.ispowered = 0 + stat |= NOPOWER + src.update_icon() + + +/obj/machinery/newscaster/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + src.isbroken=1 + if(prob(50)) + qdel(src) + else + src.update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in. + return + else + if(prob(50)) + src.isbroken=1 + src.update_icon() + return + return + +/obj/machinery/newscaster/attack_ai(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/newscaster/attack_hand(mob/user as mob) //########### THE MAIN BEEF IS HERE! And in the proc below this...############ + if(!src.ispowered || src.isbroken) + return + if(istype(user, /mob/living/carbon/human) || istype(user,/mob/living/silicon) ) + var/mob/living/human_or_robot_user = user + var/dat + + src.scan_user(human_or_robot_user) //Newscaster scans you + + switch(screen) + if(0) + dat += "Welcome to Newscasting Unit #[src.unit_no].
Interface & News networks Operational." + dat += "
Property of Nanotransen Inc" + if(news_network.wanted_issue) + dat+= "
Read Wanted Issue" + dat+= "

Create Feed Channel" + dat+= "
View Feed Channels" + dat+= "
Submit new Feed story" + dat+= "
Print newspaper" + dat+= "
Re-scan User" + dat+= "

Exit" + if(src.securityCaster) + var/wanted_already = 0 + if(news_network.wanted_issue) + wanted_already = 1 + + dat+="
Feed Security functions:
" + dat+="
[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue" + dat+="
Censor Feed Stories" + dat+="
Mark Feed Channel with Nanotrasen D-Notice" + dat+="

The newscaster recognises you as: [src.scanned_user]" + if(1) + dat+= "Station Feed Channels
" + if( isemptylist(news_network.network_channels) ) + dat+="No active channels found..." + else + for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + if(CHANNEL.is_admin_channel) + dat+="[CHANNEL.channel_name]
" + else + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + /*for(var/datum/feed_channel/CHANNEL in src.channel_list) + dat+="[CHANNEL.channel_name]:
\[created by: [CHANNEL.author]\]

" + if( isemptylist(CHANNEL.messages) ) + dat+="No feed messages found in channel...

" + else + for(var/datum/feed_message/MESSAGE in CHANNEL.messages) + dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"*/ + + dat+="

Refresh" + dat+="
Back" + if(2) + dat+="Creating new Feed Channel..." + dat+="
Channel Name: [src.channel_name]
" + dat+="Channel Author: [src.scanned_user]
" + dat+="Will Accept Public Feeds: [(src.c_locked) ? ("NO") : ("YES")]

" + dat+="
Submit

Cancel
" + if(3) + dat+="Creating new Feed Message..." + dat+="
Receiving Channel: [src.channel_name]
" //MARK + dat+="Message Author: [src.scanned_user]
" + dat+="Message Body: [src.msg]
" + dat+="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")]
" + dat+="
Submit

Cancel
" + if(4) + dat+="Feed story successfully submitted to [src.channel_name].

" + dat+="
Return
" + if(5) + dat+="Feed Channel [src.channel_name] created successfully.

" + dat+="
Return
" + if(6) + dat+="ERROR: Could not submit Feed story to Network.

" + if(src.channel_name=="") + dat+="•Invalid receiving channel name.
" + if(src.scanned_user=="Unknown") + dat+="•Channel author unverified.
" + if(src.msg == "" || src.msg == "\[REDACTED\]") + dat+="•Invalid message body.
" + + dat+="
Return
" + if(7) + dat+="ERROR: Could not submit Feed Channel to Network.

" + //var/list/existing_channels = list() //Let's get dem existing channels - OBSOLETE + var/list/existing_authors = list() + for(var/datum/feed_channel/FC in news_network.network_channels) + //existing_channels += FC.channel_name //OBSOLETE + if(FC.author == "\[REDACTED\]") + existing_authors += FC.backup_author + else + existing_authors += FC.author + if(src.scanned_user in existing_authors) + dat+="•There already exists a Feed channel under your name.
" + if(src.channel_name=="" || src.channel_name == "\[REDACTED\]") + dat+="•Invalid channel name.
" + var/check = 0 + for(var/datum/feed_channel/FC in news_network.network_channels) + if(FC.channel_name == src.channel_name) + check = 1 + break + if(check) + dat+="•Channel name already in use.
" + if(src.scanned_user=="Unknown") + dat+="•Channel author unverified.
" + dat+="
Return
" + if(8) + var/total_num=length(news_network.network_channels) + var/active_num=total_num + var/message_num=0 + for(var/datum/feed_channel/FC in news_network.network_channels) + if(!FC.censored) + message_num += length(FC.messages) //Dont forget, datum/feed_channel's var messages is a list of datum/feed_message + else + active_num-- + dat+="Network currently serves a total of [total_num] Feed channels, [active_num] of which are active, and a total of [message_num] Feed Stories." //TODO: CONTINUE + dat+="

Liquid Paper remaining: [(src.paper_remaining) *100 ] cm^3" + dat+="

Print Paper" + dat+="
Cancel" + if(9) + dat+="[src.viewing_channel.channel_name]: \[created by: [src.viewing_channel.author]\]
" + if(src.viewing_channel.censored) + dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" + dat+="No further feed story additions are allowed while the D-Notice is in effect.


" + else + if( isemptylist(src.viewing_channel.messages) ) + dat+="No feed messages found in channel...
" + else + var/i = 0 + for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) + i++ + dat+="-[MESSAGE.body]
" + if(MESSAGE.img) + usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png") + dat+="

" + dat+="\[Story by [MESSAGE.author] \] - ([MESSAGE.time_stamp])
" + dat+="

Refresh" + dat+="
Back" + if(10) + dat+="Nanotrasen Feed Censorship Tool
" + dat+="NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.
" + dat+="Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.
" + dat+="
Select Feed channel to get Stories from:
" + if(isemptylist(news_network.network_channels)) + dat+="No feed channels found active...
" + else + for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + dat+="
Cancel" + if(11) + dat+="Nanotrasen D-Notice Handler
" + dat+="A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's" + dat+="morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed" + dat+="stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.
" + if(isemptylist(news_network.network_channels)) + dat+="No feed channels found active...
" + else + for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + + dat+="
Back" + if(12) + dat+="[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
" + dat+="[(src.viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
" + + + if( isemptylist(src.viewing_channel.messages) ) + dat+="No feed messages found in channel...
" + else + for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) + dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" + dat+="[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
" + dat+="
Back" + if(13) + dat+="[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
" + dat+="Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
" + if(src.viewing_channel.censored) + dat+="ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
" + dat+="No further feed story additions are allowed while the D-Notice is in effect.

" + else + if( isemptylist(src.viewing_channel.messages) ) + dat+="No feed messages found in channel...
" + else + for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) + dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" + + dat+="
Back" + if(14) + dat+="Wanted Issue Handler:" + var/wanted_already = 0 + var/end_param = 1 + if(news_network.wanted_issue) + wanted_already = 1 + end_param = 2 + + if(wanted_already) + dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below.
" + dat+="
" + dat+="Criminal Name: [src.channel_name]
" + dat+="Description: [src.msg]
" + dat+="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")]
" + if(wanted_already) + dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
" + else + dat+="Wanted Issue will be created under prosecutor: [src.scanned_user]
" + dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]" + if(wanted_already) + dat+="
Take down Issue" + dat+="
Cancel" + if(15) + dat+="Wanted issue for [src.channel_name] is now in Network Circulation.

" + dat+="
Return
" + if(16) + dat+="ERROR: Wanted Issue rejected by Network.

" + if(src.channel_name=="" || src.channel_name == "\[REDACTED\]") + dat+="•Invalid name for person wanted.
" + if(src.scanned_user=="Unknown") + dat+="•Issue author unverified.
" + if(src.msg == "" || src.msg == "\[REDACTED\]") + dat+="•Invalid description.
" + dat+="
Return
" + if(17) + dat+="Wanted Issue successfully deleted from Circulation
" + dat+="
Return
" + if(18) + if(news_network.wanted_issue) + dat+="-- STATIONWIDE WANTED ISSUE --
\[Submitted by: [news_network.wanted_issue.backup_author]\]
" + dat+="Criminal: [news_network.wanted_issue.author]
" + dat+="Description: [news_network.wanted_issue.body]
" + dat+="Photo:: " + if(news_network.wanted_issue.img) + usr << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png") + dat+="
" + else + dat+="None" + else + dat+="No current wanted issue found.

" + dat+="

Back
" + if(19) + dat+="Wanted issue for [src.channel_name] successfully edited.

" + dat+="
Return
" + if(20) + dat+="Printing successful. Please receive your newspaper from the bottom of the machine.

" + dat+="Return" + if(21) + dat+="Unable to print newspaper. Insufficient paper. Please notify maintenance personnel to refill machine storage.

" + dat+="Return" + else + dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" + + //human_or_robot_user << browse(dat, "window=newscaster_main;size=400x600") + //onclose(human_or_robot_user, "newscaster_main") + + var/datum/browser/popup = new(human_or_robot_user, "newscaster_main", "Newscaster Unit #[src.unit_no]", 400, 600) + popup.set_content(dat) + popup.set_title_image(human_or_robot_user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/newscaster/Topic(href, href_list) + if(..()) + return + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + if(href_list["set_channel_name"]) + src.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) + while (findtext(src.channel_name," ") == 1) + src.channel_name = copytext(src.channel_name,2,lentext(src.channel_name)+1) + src.updateUsrDialog() + //src.update_icon() + + else if(href_list["set_channel_lock"]) + src.c_locked = !src.c_locked + src.updateUsrDialog() + //src.update_icon() + + else if(href_list["submit_new_channel"]) + var/list/existing_authors = list() + for(var/datum/feed_channel/FC in news_network.network_channels) + //existing_channels += FC.channel_name + if(FC.author == "\[REDACTED\]") + existing_authors += FC.backup_author + else + existing_authors +=FC.author + var/check = 0 + for(var/datum/feed_channel/FC in news_network.network_channels) + if(FC.channel_name == src.channel_name) + check = 1 + break + if(src.channel_name == "" || src.channel_name == "\[REDACTED\]" || src.scanned_user == "Unknown" || check || (src.scanned_user in existing_authors) ) + src.screen=7 + else + var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel") + if(choice=="Confirm") + news_network.CreateFeedChannel(src.channel_name, src.scanned_user, c_locked) + feedback_inc("newscaster_channels",1) + src.screen=5 + src.updateUsrDialog() + //src.update_icon() + + else if(href_list["set_channel_receiving"]) + //var/list/datum/feed_channel/available_channels = list() + var/list/available_channels = list() + for(var/datum/feed_channel/F in news_network.network_channels) + if( (!F.locked || F.author == scanned_user) && !F.censored) + available_channels += F.channel_name + src.channel_name = input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels + src.updateUsrDialog() + + else if(href_list["set_new_message"]) + src.msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", "")) + while (findtext(src.msg," ") == 1) + src.msg = copytext(src.msg,2,lentext(src.msg)+1) + src.updateUsrDialog() + + else if(href_list["set_attachment"]) + AttachPhoto(usr) + src.updateUsrDialog() + + else if(href_list["submit_new_message"]) + if(src.msg =="" || src.msg=="\[REDACTED\]" || src.scanned_user == "Unknown" || src.channel_name == "" ) + src.screen=6 + else + news_network.SubmitArticle(msg, scanned_user, channel_name, photo) + feedback_inc("newscaster_stories",1) + src.screen=4 + src.updateUsrDialog() + + else if(href_list["create_channel"]) + src.screen=2 + src.updateUsrDialog() + + else if(href_list["create_feed_story"]) + src.screen=3 + src.updateUsrDialog() + + else if(href_list["menu_paper"]) + src.screen=8 + src.updateUsrDialog() + else if(href_list["print_paper"]) + if(!src.paper_remaining) + src.screen=21 + else + src.print_paper() + src.screen = 20 + src.updateUsrDialog() + + else if(href_list["menu_censor_story"]) + src.screen=10 + src.updateUsrDialog() + + else if(href_list["menu_censor_channel"]) + src.screen=11 + src.updateUsrDialog() + + else if(href_list["menu_wanted"]) + var/already_wanted = 0 + if(news_network.wanted_issue) + already_wanted = 1 + + if(already_wanted) + src.channel_name = news_network.wanted_issue.author + src.msg = news_network.wanted_issue.body + src.screen = 14 + src.updateUsrDialog() + + else if(href_list["set_wanted_name"]) + src.channel_name = strip_html(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) + while (findtext(src.channel_name," ") == 1) + src.channel_name = copytext(src.channel_name,2,lentext(src.channel_name)+1) + src.updateUsrDialog() + + else if(href_list["set_wanted_desc"]) + src.msg = strip_html(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) + while (findtext(src.msg," ") == 1) + src.msg = copytext(src.msg,2,lentext(src.msg)+1) + src.updateUsrDialog() + + else if(href_list["submit_wanted"]) + var/input_param = text2num(href_list["submit_wanted"]) + if(src.msg == "" || src.channel_name == "" || src.scanned_user == "Unknown") + src.screen = 16 + else + var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel") + if(choice=="Confirm") + if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below + var/datum/feed_message/WANTED = new /datum/feed_message + WANTED.author = src.channel_name + WANTED.body = src.msg + WANTED.backup_author = src.scanned_user //I know, a bit wacky + if(photo) + WANTED.img = photo.img + news_network.wanted_issue = WANTED + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + NEWSCASTER.newsAlert() + NEWSCASTER.update_icon() + src.screen = 15 + else + if(news_network.wanted_issue.is_admin_message) + alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok") + return + news_network.wanted_issue.author = src.channel_name + news_network.wanted_issue.body = src.msg + news_network.wanted_issue.backup_author = src.scanned_user + if(photo) + news_network.wanted_issue.img = photo.img + src.screen = 19 + + src.updateUsrDialog() + + else if(href_list["cancel_wanted"]) + if(news_network.wanted_issue.is_admin_message) + alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot take it down.","Ok") + return + var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel") + if(choice=="Confirm") + news_network.wanted_issue = null + for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + NEWSCASTER.update_icon() + src.screen=17 + src.updateUsrDialog() + + else if(href_list["view_wanted"]) + src.screen=18 + src.updateUsrDialog() + else if(href_list["censor_channel_author"]) + var/datum/feed_channel/FC = locate(href_list["censor_channel_author"]) + if(FC.is_admin_channel) + alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok") + return + if(FC.author != "\[REDACTED\]") + FC.backup_author = FC.author + FC.author = "\[REDACTED\]" + else + FC.author = FC.backup_author + src.updateUsrDialog() + + else if(href_list["censor_channel_story_author"]) + var/datum/feed_message/MSG = locate(href_list["censor_channel_story_author"]) + if(MSG.is_admin_message) + alert("This message was created by a Nanotrasen Officer. You cannot censor its author.","Ok") + return + if(MSG.author != "\[REDACTED\]") + MSG.backup_author = MSG.author + MSG.author = "\[REDACTED\]" + else + MSG.author = MSG.backup_author + src.updateUsrDialog() + + else if(href_list["censor_channel_story_body"]) + var/datum/feed_message/MSG = locate(href_list["censor_channel_story_body"]) + if(MSG.is_admin_message) + alert("This channel was created by a Nanotrasen Officer. You cannot censor it.","Ok") + return + if(MSG.body != "\[REDACTED\]") + MSG.backup_body = MSG.body + MSG.body = "\[REDACTED\]" + else + MSG.body = MSG.backup_body + src.updateUsrDialog() + + else if(href_list["pick_d_notice"]) + var/datum/feed_channel/FC = locate(href_list["pick_d_notice"]) + src.viewing_channel = FC + src.screen=13 + src.updateUsrDialog() + + else if(href_list["toggle_d_notice"]) + var/datum/feed_channel/FC = locate(href_list["toggle_d_notice"]) + if(FC.is_admin_channel) + alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok") + return + FC.censored = !FC.censored + src.updateUsrDialog() + + else if(href_list["view"]) + src.screen=1 + src.updateUsrDialog() + + else if(href_list["setScreen"]) //Brings us to the main menu and resets all fields~ + src.screen = text2num(href_list["setScreen"]) + if (src.screen == 0) + src.scanned_user = "Unknown"; + msg = ""; + src.c_locked=0; + channel_name=""; + src.viewing_channel = null + src.updateUsrDialog() + + else if(href_list["show_channel"]) + var/datum/feed_channel/FC = locate(href_list["show_channel"]) + src.viewing_channel = FC + src.screen = 9 + src.updateUsrDialog() + + else if(href_list["pick_censor_channel"]) + var/datum/feed_channel/FC = locate(href_list["pick_censor_channel"]) + src.viewing_channel = FC + src.screen = 12 + src.updateUsrDialog() + + else if(href_list["refresh"]) + src.updateUsrDialog() + + +/obj/machinery/newscaster/attackby(obj/item/I as obj, mob/user as mob) + +/* if (istype(I, /obj/item/weapon/card/id) || istype(I, /obj/item/device/pda) ) //Name verification for channels or messages + if(src.screen == 4 || src.screen == 5) + if( istype(I, /obj/item/device/pda) ) + var/obj/item/device/pda/P = I + if(P.id) + src.scanned_user = "[P.id.registered_name] ([P.id.assignment])" + src.screen=2 + else + var/obj/item/weapon/card/id/T = I + src.scanned_user = text("[T.registered_name] ([T.assignment])") + src.screen=2*/ //Obsolete after autorecognition + + if(istype(I, /obj/item/weapon/wrench)) + user << "Now [anchored ? "un" : ""]securing [name]" + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, 60)) + new /obj/item/newscaster_frame(loc) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + qdel(src) + return + + if (src.isbroken) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, 1) + for (var/mob/O in hearers(5, src.loc)) + O.show_message("[user.name] further abuses the shattered [src.name].") + else + if(istype(I, /obj/item/weapon) ) + var/obj/item/weapon/W = I + if(W.force <15) + for (var/mob/O in hearers(5, src.loc)) + O.show_message("[user.name] hits the [src.name] with the [W.name] with no visible effect." ) + playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1) + else + src.hitstaken++ + if(src.hitstaken==3) + for (var/mob/O in hearers(5, src.loc)) + O.show_message("[user.name] smashes the [src.name]!" ) + src.isbroken=1 + playsound(src.loc, 'sound/effects/Glassbr3.ogg', 100, 1) + else + for (var/mob/O in hearers(5, src.loc)) + O.show_message("[user.name] forcefully slams the [src.name] with the [I.name]!" ) + playsound(src.loc, 'sound/effects/Glasshit.ogg', 100, 1) + else + user << "This does nothing." + src.update_icon() + + +/obj/machinery/newscaster/attack_paw(mob/user as mob) + user << "The newscaster controls are far too complicated for your tiny brain!" + return + +/obj/machinery/newscaster/proc/AttachPhoto(mob/user as mob) + if(photo) + photo.loc = src.loc + if(!issilicon(user)) + user.put_in_inactive_hand(photo) + photo = null + if(istype(user.get_active_hand(), /obj/item/weapon/photo)) + photo = user.get_active_hand() + user.drop_item() + photo.loc = src + if(istype(user,/mob/living/silicon/ai)) + var/list/nametemp = list() + var/find + var/datum/picture/selection + var/mob/living/silicon/ai/tempAI = user + if(tempAI.aicamera.aipictures.len == 0) + usr << "No images saved" + return + for(var/datum/picture/t in tempAI.aicamera.aipictures) + nametemp += t.fields["name"] + find = input("Select image (numbered in order taken)") in nametemp + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + for(var/datum/picture/q in tempAI.aicamera.aipictures) + if(q.fields["name"] == find) + selection = q + break // just in case some AI decides to take 10 thousand pictures in a round + P.icon = selection.fields["icon"] + P.img = selection.fields["img"] + P.desc = selection.fields["desc"] + photo = P + if(istype(user,/mob/living/silicon/robot)) + var/list/nametemp = list() + var/find + var/datum/picture/selection + var/mob/living/silicon/robot/R = user + var/obj/item/device/camera/siliconcam/targetcam = null + if(R.connected_ai) + targetcam = R.connected_ai.aicamera + else + targetcam = R.aicamera + if(targetcam.aipictures.len == 0) + usr << "No images saved" + return + for(var/datum/picture/t in targetcam.aipictures) + nametemp += t.fields["name"] + find = input("Select image (numbered in order taken)") in nametemp + for(var/datum/picture/q in targetcam.aipictures) + if(q.fields["name"] == find) + selection = q + break + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + P.construct(selection.fields["icon"], selection.fields["img"], selection.fields["desc"]) + photo = P + + + + + +//######################################################################################################################## +//###################################### NEWSPAPER! ###################################################################### +//######################################################################################################################## + +/obj/item/weapon/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 = 2 //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/weapon/newspaper/attack_hand(mob/user as mob) + ..() + world << "derp"*/ + +obj/item/weapon/newspaper/attack_self(mob/user as mob) + if(ishuman(user)) + var/mob/living/carbon/human/human_user = user + var/dat + src.pages = 0 + switch(screen) + if(0) //Cover + dat+="
The Griffon
" + dat+="
Nanotrasen-standard newspaper, for use on Nanotrasen© Space Facilities

" + if(isemptylist(src.news_content)) + if(src.important_message) + dat+="Contents:
" + else + dat+="Other than the title, the rest of the newspaper is unprinted..." + else + dat+="Contents:
" + if(scribble_page==curr_page) + dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" + dat+= "
Next Page
Done reading
" + if(1) // X channel pages inbetween. + for(var/datum/feed_channel/NP in src.news_content) + src.pages++ //Let's get it right again. + var/datum/feed_channel/C = src.news_content[src.curr_page] + dat+="[C.channel_name] \[created by: [C.author]\]

" + if(C.censored) + dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing." + else + if(isemptylist(C.messages)) + dat+="No Feed stories stem from this channel..." + else + dat+="" + if(scribble_page==curr_page) + dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" + dat+= "

Previous Page
Next Page
" + if(2) //Last page + for(var/datum/feed_channel/NP in src.news_content) + src.pages++ + if(src.important_message!=null) + dat+="
Wanted Issue:


" + dat+="Criminal name: [important_message.author]
" + dat+="Description: [important_message.body]
" + dat+="Photo:: " + if(important_message.img) + user << browse_rsc(important_message.img, "tmp_photow.png") + dat+="
" + else + dat+="None" + else + dat+="Apart from some uninteresting Classified ads, there's nothing on this page..." + if(scribble_page==curr_page) + dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" + dat+= "
Previous Page
" + else + dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" + + dat+="

[src.curr_page+1]
" + human_user << browse(dat, "window=newspaper_main;size=300x400") + onclose(human_user, "newspaper_main") + else + user << "The paper is full of intelligible symbols!" + + +obj/item/weapon/newspaper/Topic(href, href_list) + var/mob/living/U = usr + ..() + if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) )) + U.set_machine(src) + if(href_list["next_page"]) + if(curr_page==src.pages+1) + return //Don't need that at all, but anyway. + if(src.curr_page == src.pages) //We're at the middle, get to the end + src.screen = 2 + else + if(curr_page == 0) //We're at the start, get to the middle + src.screen=1 + src.curr_page++ + playsound(src.loc, "pageturn", 50, 1) + + else if(href_list["prev_page"]) + if(curr_page == 0) + return + if(curr_page == 1) + src.screen = 0 + + else + if(curr_page == src.pages+1) //we're at the end, let's go back to the middle. + src.screen = 1 + src.curr_page-- + playsound(src.loc, "pageturn", 50, 1) + + if (istype(src.loc, /mob)) + src.attack_self(src.loc) + + +obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/pen)) + if(src.scribble_page == src.curr_page) + user << "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?" + else + var/s = strip_html( input(user, "Write something", "Newspaper", "") ) + s = copytext(sanitize(s), 1, MAX_MESSAGE_LEN) + if (!s) + return + if (!in_range(src, usr) && src.loc != usr) + return + src.scribble_page = src.curr_page + src.scribble = s + src.attack_self(user) + return + + +////////////////////////////////////helper procs + + +/obj/machinery/newscaster/proc/scan_user(mob/living/user as mob) + if(istype(user,/mob/living/carbon/human)) //User is a human + var/mob/living/carbon/human/human_user = user + if(human_user.wear_id) //Newscaster scans you + if(istype(human_user.wear_id, /obj/item/device/pda) ) //autorecognition, woo! + var/obj/item/device/pda/P = human_user.wear_id + if(P.id) + src.scanned_user = "[P.id.registered_name] ([P.id.assignment])" + else + src.scanned_user = "Unknown" + else if(istype(human_user.wear_id, /obj/item/weapon/card/id) ) + var/obj/item/weapon/card/id/ID = human_user.wear_id + src.scanned_user ="[ID.registered_name] ([ID.assignment])" + else + src.scanned_user ="Unknown" + else + src.scanned_user ="Unknown" + else + var/mob/living/silicon/ai_user = user + src.scanned_user = "[ai_user.name] ([ai_user.job])" + + +/obj/machinery/newscaster/proc/print_paper() + feedback_inc("newscaster_newspapers_printed",1) + var/obj/item/weapon/newspaper/NEWSPAPER = new /obj/item/weapon/newspaper + for(var/datum/feed_channel/FC in news_network.network_channels) + NEWSPAPER.news_content += FC + if(news_network.wanted_issue) + NEWSPAPER.important_message = news_network.wanted_issue + NEWSPAPER.loc = get_turf(src) + src.paper_remaining-- + return + +//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later. +///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not +// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list. + +/obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile. + var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ + if(channel) + for(var/mob/O in hearers(world.view-1, T)) + O.show_message("[src.name] beeps, \"Breaking news from [channel]!\"",2) + src.alert = 1 + src.update_icon() + spawn(300) + src.alert = 0 + src.update_icon() + playsound(src.loc, 'sound/machines/twobeep.ogg', 75, 1) + else + for(var/mob/O in hearers(world.view-1, T)) + O.show_message("[src.name] beeps, \"Attention! Wanted issue distributed!\"",2) + playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 75, 1) return \ No newline at end of file diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index c27b4893cc2..d0150d440d2 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -22,6 +22,8 @@ var/icon_old = null var/pathweight = 1 + flags = 0 + /turf/New() ..() for(var/atom/movable/AM as mob|obj in src) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index f078b822e3d..141c5047419 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -29,7 +29,7 @@ var/list/ai_list = list() var/icon/holo_icon//Default is assigned when AI is created. var/obj/item/device/pda/ai/aiPDA = null var/obj/item/device/multitool/aiMulti = null - var/obj/item/device/camera/ai_camera/aicamera = null + var/obj/item/device/camera/siliconcam/aicamera = null //MALFUNCTION var/datum/module_picker/malf_picker @@ -86,7 +86,7 @@ var/list/ai_list = list() aiPDA.name = name + " (" + aiPDA.ownjob + ")" aiMulti = new(src) - aicamera = new/obj/item/device/camera/ai_camera(src) + aicamera = new/obj/item/device/camera/siliconcam/ai_camera(src) if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 54c38fcb787..5e561a38922 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -57,6 +57,9 @@ var/obj/item/weapon/tank/internal = null //Hatred. Used if a borg has a jetpack. var/obj/item/robot_parts/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. + var/obj/item/device/camera/siliconcam/aicamera = null //photography + var/toner = 0 + var/tonermax = 40 @@ -112,6 +115,9 @@ mmi.brainmob.container = mmi mmi.contents += mmi.brainmob + aicamera = new/obj/item/device/camera/siliconcam/robot_camera(src) + toner = 40 + playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) @@ -579,6 +585,15 @@ else usr << "Upgrade error!" + else if(istype(W, /obj/item/device/toner)) + if(toner >= tonermax) + usr << "The toner level of [src] is at it's highest level possible" + else + toner = 40 + usr.drop_item() + qdel(W) + usr << "You fill the toner level of [src] to it's max capacity" + else if(W.force) @@ -1103,4 +1118,4 @@ if(2) //New Module connected_ai << "

NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.
" if(3) //New Name - connected_ai << "

NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].
" \ No newline at end of file + connected_ai << "

NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].
" diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index b002c91a8dc..1df8ee0aa83 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -188,7 +188,7 @@ var/datum/picture/selection var/mob/living/silicon/ai/tempAI = usr if(tempAI.aicamera.aipictures.len == 0) - usr << "No images saved" + usr << "No images saved" return for(var/datum/picture/t in tempAI.aicamera.aipictures) nametemp += t.fields["name"] diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 7a052ab2aa4..fb9637ca84f 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -4,6 +4,7 @@ * Camera Film * Photos * Photo Albums + * AI Photography */ /* @@ -77,6 +78,11 @@ name = "photo[(n_name ? text("- '[n_name]'") : null)]" add_fingerprint(usr) +/obj/item/weapon/photo/proc/construct(var/inicon, var/inimg, var/indesc, var/inblueprints) + icon = inicon + img = inimg + desc = indesc + blueprints = inblueprints /* * Photo album @@ -106,26 +112,53 @@ var/pictures_left = 10 var/on = 1 var/blueprints = 0 //are blueprints visible in the current photo being created? - var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info + var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info. Keeping this here allows us to share some procs w/ regualar camera -/obj/item/device/camera/ai_camera //camera AI can take pictures with - name = "AI photo camera" +/obj/item/device/camera/siliconcam + name = "silicon photo camera" var/in_camera_mode = 0 - verb/picture() - set category ="AI Commands" - set name = "Take Image" - set src in usr +/obj/item/device/camera/siliconcam/ai_camera //camera AI can take pictures with + name = "AI photo camera" - toggle_camera_mode() +/obj/item/device/camera/siliconcam/ai_camera/verb/picture() + set category ="AI Commands" + set name = "Take Image" + set src in usr - verb/viewpicture() - set category ="AI Commands" - set name = "View Images" - set src in usr + toggle_camera_mode() - viewpictures() +/obj/item/device/camera/siliconcam/ai_camera/verb/viewpicture() + set category ="AI Commands" + set name = "View Images" + set src in usr + + viewpictures() + +/obj/item/device/camera/siliconcam/robot_camera //camera cyborgs can take pictures with.. needs it's own because of verb CATEGORY >.> + name = "Cyborg photo camera" + +/obj/item/device/camera/siliconcam/robot_camera/verb/picture() + set category ="Robot Commands" + set name = "Take Image" + set src in usr + + toggle_camera_mode() + +/obj/item/device/camera/siliconcam/robot_camera/verb/viewpicture() + set category ="Robot Commands" + set name = "View Images" + set src in usr + + viewpictures(usr) + +/obj/item/device/camera/siliconcam/robot_camera/verb/borgprinting() + set category ="Robot Commands" + set name = "Print Image" + set src in usr + + borgprint() /obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user) @@ -232,10 +265,10 @@ temp.Blend("#000", ICON_OVERLAY) temp.Blend(camera_get_icon(turfs, target), ICON_OVERLAY) - if(!isAi) + if(!issilicon(user)) printpicture(user, temp, mobs, flag) else - aipicture(user, temp, mobs, blueprints) + aipicture(user, temp, mobs, isAi, blueprints) @@ -258,7 +291,7 @@ blueprints = 0 -/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs) //instead of printing a picture like a regular camera would, we do this instead for the AI +/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs, isAi) //instead of printing a picture like a regular camera would, we do this instead for the AI var/icon/small_img = icon(temp) var/icon/ic = icon('icons/obj/items.dmi',"photo") @@ -275,7 +308,10 @@ injectblueprints = 1 blueprints = 0 - injectaialbum(icon, img, desc, pixel_x, pixel_y, injectblueprints) + if(isAi) + injectaialbum(icon, img, desc, pixel_x, pixel_y, injectblueprints) + else + injectmasteralbum(icon, img, desc, pixel_x, pixel_y, injectblueprints) /datum/picture @@ -288,7 +324,7 @@ for(var/datum/picture in src.aipictures) numberer++ var/datum/picture/P = new() - P.fields["name"] = "Image [numberer]" + P.fields["name"] = "Image [numberer] (taken by [src.loc.name])" P.fields["icon"] = icon P.fields["img"] = img P.fields["desc"] = desc @@ -297,33 +333,65 @@ P.fields["blueprints"] = blueprintsinject aipictures += P - usr << "Image recorded" //feedback to the AI player that the picture was taken + usr << "Image recorded" //feedback to the AI player that the picture was taken +/obj/item/device/camera/proc/injectmasteralbum(var/icon, var/img, var/desc, var/pixel_x, var/pixel_y, var/blueprintsinject) //stores image information to a list similar to that of the datacore + var/numberer = 1 + var/mob/living/silicon/robot/C = src.loc + if(C.connected_ai) + for(var/datum/picture in C.connected_ai.aicamera.aipictures) + numberer++ + var/datum/picture/P = new() + P.fields["name"] = "Image [numberer] (taken by [src.loc.name])" + P.fields["icon"] = icon + P.fields["img"] = img + P.fields["desc"] = desc + P.fields["pixel_x"] = pixel_x + P.fields["pixel_y"] = pixel_y + P.fields["blueprints"] = blueprintsinject -/obj/item/device/camera/ai_camera/proc/viewpictures() //AI proc for viewing pictures they have taken + C.connected_ai.aicamera.aipictures += P + usr << "Image recorded and saved to remote database" //feedback to the Cyborg player that the picture was taken + else + injectaialbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject) + +obj/item/device/camera/siliconcam/proc/viewpichelper(var/obj/item/device/camera/siliconcam/targetloc) var/list/nametemp = list() var/find var/datum/picture/selection - if(src.aipictures.len == 0) - usr << "No images saved" + if(targetloc.aipictures.len == 0) + usr << "No images saved" return - for(var/datum/picture/t in src.aipictures) + for(var/datum/picture/t in targetloc.aipictures) nametemp += t.fields["name"] find = input("Select image (numbered in order taken)") in nametemp var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - for(var/datum/picture/q in src.aipictures) + for(var/datum/picture/q in targetloc.aipictures) if(q.fields["name"] == find) selection = q break // just in case some AI decides to take 10 thousand pictures in a round - P.icon = selection.fields["icon"] - P.img = selection.fields["img"] - P.desc = selection.fields["desc"] + P.construct(selection.fields["icon"], selection.fields["img"], selection.fields["desc"]) P.pixel_x = selection.fields["pixel_x"] P.pixel_y = selection.fields["pixel_y"] P.show(usr) usr << P.desc - qdel(P) //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all. + qdel(P) //so 10 thousand picture items are not left in memory should an AI take them and then view them all + +obj/item/device/camera/siliconcam/proc/viewpictures(user) + if(isrobot(user)) // Cyborg + var/mob/living/silicon/robot/C = src.loc + var/obj/item/device/camera/siliconcam/Cinfo + if(C.connected_ai) + Cinfo = C.connected_ai.aicamera + viewpichelper(Cinfo) + else + Cinfo = C.aicamera + viewpichelper(Cinfo) + else // AI + var/Ainfo = src + viewpichelper(Ainfo) + /obj/item/device/camera/afterattack(atom/target, mob/user, flag) if(!on || !pictures_left || ismob(target.loc)) return @@ -340,16 +408,47 @@ icon_state = "camera" on = 1 -/obj/item/device/camera/ai_camera/proc/toggle_camera_mode() +/obj/item/device/camera/siliconcam/proc/toggle_camera_mode() if(in_camera_mode) camera_mode_off() else camera_mode_on() -/obj/item/device/camera/ai_camera/proc/camera_mode_off() +/obj/item/device/camera/siliconcam/proc/camera_mode_off() src.in_camera_mode = 0 usr << "Camera Mode deactivated" -/obj/item/device/camera/ai_camera/proc/camera_mode_on() +/obj/item/device/camera/siliconcam/proc/camera_mode_on() src.in_camera_mode = 1 - usr << "Camera Mode activated" \ No newline at end of file + usr << "Camera Mode activated" + +obj/item/device/camera/siliconcam/robot_camera/proc/borgprint() + var/list/nametemp = list() + var/find + var/datum/picture/selection + var/mob/living/silicon/robot/C = src.loc + var/obj/item/device/camera/siliconcam/targetcam = null + if(C.toner < 20) + usr << "Insufficent toner to print image." + return + if(C.connected_ai) + targetcam = C.connected_ai.aicamera + else + targetcam = C.aicamera + if(targetcam.aipictures.len == 0) + usr << "No images saved" + return + for(var/datum/picture/t in targetcam.aipictures) + nametemp += t.fields["name"] + find = input("Select image (numbered in order taken)") in nametemp + for(var/datum/picture/q in targetcam.aipictures) + if(q.fields["name"] == find) + selection = q + break + var/obj/item/weapon/photo/p = new /obj/item/weapon/photo(C.loc) + p.construct(selection.fields["icon"], selection.fields["img"], selection.fields["desc"], selection.fields["blueprints"]) + p.pixel_x = rand(-10, 10) + p.pixel_y = rand(-10, 10) + C.toner -= 20 //Cyborgs are very ineffeicient at printing an image + visible_message("[C.name] spits out a photograph from a narrow slot on it's chassis.") + usr << "You print a photograph." diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index a0f1b088155..cf33cbb7529 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -645,6 +645,7 @@ obj/machinery/computer/pandemic/proc/replicator_cooldown(var/waittime) D = new type(0, null) if(!D) return + replicator_cooldown(50) var/list/data = list("viruses"=list(D)) var/name = sanitize(input(usr,"Name:","Name the culture",D.name)) if(!name || name == " ") name = D.name @@ -652,7 +653,6 @@ obj/machinery/computer/pandemic/proc/replicator_cooldown(var/waittime) B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium." B.reagents.add_reagent("blood",20,data) src.updateUsrDialog() - replicator_cooldown(50) else src.temp_html = "The replicator is not ready yet." src.updateUsrDialog() diff --git a/html/changelog.html b/html/changelog.html index 5cdc20127fd..87fb69cc6e2 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -104,6 +104,7 @@ should be listed in the changelog upon commit tho. Thanks. -->
+

3 April 2014

Ikarrus updated: