diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm index 1f65364e1ae..cc77b8c3c59 100644 --- a/code/__defines/machinery.dm +++ b/code/__defines/machinery.dm @@ -50,6 +50,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define NETWORK_SECURITY "Security" #define NETWORK_TELECOM "Tcomsat" #define NETWORK_THUNDER "Thunderdome" +#define NETWORK_COMMUNICATORS "Communicators" // Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them. var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret") diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 0858ebc1a40..1e14d391833 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1257,7 +1257,7 @@ var/list/WALLITEMS = list( arglist = list2params(arglist) return "[content]" -/proc/get_random_colour(var/simple, var/lower, var/upper) +/proc/get_random_colour(var/simple, var/lower=0, var/upper=255) var/colour if(simple) colour = pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF")) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 291b9852949..7c466514194 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -35,10 +35,13 @@ var/affected_by_emp_until = 0 + var/client_huds = list() + /obj/machinery/camera/New() wires = new(src) assembly = new(src) assembly.state = 4 + client_huds |= global_hud.whitense /* // Use this to look for cameras that have the same c_tag. for(var/obj/machinery/camera/C in cameranet.cameras) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index ea730a4a9ff..c9350bd3d1d 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -17,7 +17,8 @@ var/global/list/station_networks = list( NETWORK_RESEARCH_OUTPOST, NETWORK_ROBOTS, NETWORK_PRISON, - NETWORK_SECURITY + NETWORK_SECURITY, + NETWORK_COMMUNICATORS ) var/global/list/engineering_networks = list( NETWORK_ENGINE, diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index b0f1460249a..0f3ff025b95 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -741,7 +741,8 @@ /obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 8, /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 8, /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 8, - /obj/item/weapon/reagent_containers/pill/diet = 8) + /obj/item/weapon/reagent_containers/pill/diet = 8, + /obj/item/weapon/towel/random = 8) prices = list(/obj/item/weapon/reagent_containers/food/drinks/milk/smallcarton = 3, /obj/item/weapon/reagent_containers/food/drinks/milk/smallcarton/chocolate = 3, @@ -749,7 +750,8 @@ /obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 5, /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 5, /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 5, - /obj/item/weapon/reagent_containers/pill/diet = 25) + /obj/item/weapon/reagent_containers/pill/diet = 25, + /obj/item/weapon/towel/random = 40) contraband = list(/obj/item/weapon/reagent_containers/syringe/steroid = 4) diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index 9b62767eb85..97e856e27ab 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -18,6 +18,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list() matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10) var/video_range = 4 + var/obj/machinery/camera/communicator/video_source // Their camera + var/obj/machinery/camera/communicator/camera // Our camera var/list/voice_mobs = list() var/list/voice_requests = list() @@ -63,6 +65,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list() all_communicators = sortAtom(all_communicators) node = get_exonet_node() processing_objects |= src + camera = new(src) + camera.name = "[src] #[rand(100,999)]" + camera.c_tag = camera.name //This is a pretty terrible way of doing this. spawn(5 SECONDS) //Wait for our mob to finish spawning. if(ismob(loc)) @@ -74,6 +79,14 @@ var/global/list/obj/item/device/communicator/all_communicators = list() register_device(S.loc) initialize_exonet(S.loc) +// Proc: examine() +// Parameters: user - the user doing the examining +// Description: Allows the user to click a link when examining to look at video if one is going. +/obj/item/device/communicator/examine(mob/user) + . = ..(user, 1) + if(. && video_source) + user << "It looks like it's on a video call: \[view\]" + // Proc: initialize_exonet() // Parameters: 1 (user - the person the communicator belongs to) // Description: Sets up the exonet datum, gives the device an address, and then gets a node reference. Afterwards, populates the device @@ -257,27 +270,27 @@ var/global/list/obj/item/device/communicator/all_communicators = list() //Now for ghosts who we pretend have communicators. for(var/mob/observer/dead/O in known_devices) if(O.client && O.client.prefs.communicator_visibility == 1 && O.exonet) - communicators[++communicators.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address) + communicators[++communicators.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address, "ref" = "\ref[O]") //Lists all the other communicators that we invited. for(var/obj/item/device/communicator/comm in voice_invites) if(comm.exonet) - invites[++invites.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address) + invites[++invites.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address, "ref" = "\ref[comm]") //Ghosts we invited. for(var/mob/observer/dead/O in voice_invites) if(O.exonet && O.client) - invites[++invites.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address) + invites[++invites.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address, "ref" = "\ref[O]") //Communicators that want to talk to us. for(var/obj/item/device/communicator/comm in voice_requests) if(comm.exonet) - requests[++requests.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address) + requests[++requests.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address, "ref" = "\ref[comm]") //Ghosts that want to talk to us. for(var/mob/observer/dead/O in voice_requests) if(O.exonet && O.client) - requests[++requests.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address) + requests[++requests.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address, "ref" = "\ref[O]") //Now for all the voice mobs inside the communicator. for(var/mob/living/voice/voice in contents) @@ -285,12 +298,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list() //Finally, all the communicators linked to this one. for(var/obj/item/device/communicator/comm in communicating) - connected_communicators[++connected_communicators.len] = list("name" = sanitize(comm.name), "true_name" = sanitize(comm.name)) + connected_communicators[++connected_communicators.len] = list("name" = sanitize(comm.name), "true_name" = sanitize(comm.name), "ref" = "\ref[comm]") //Devices that have been messaged or recieved messages from. for(var/obj/item/device/communicator/comm in im_contacts) if(comm.exonet) - im_contacts_ui[++im_contacts_ui.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address) + im_contacts_ui[++im_contacts_ui.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address, "ref" = "\ref[comm]") //Actual messages. for(var/I in im_list) @@ -313,6 +326,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list() data["requestsReceived"] = requests data["voice_mobs"] = voices data["communicating"] = connected_communicators + data["video_comm"] = video_source ? "\ref[video_source.loc]" : null data["imContacts"] = im_contacts_ui data["imList"] = im_list_ui data["time"] = worldtime2text() @@ -325,7 +339,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(!ui) // the ui does not exist, so we'll create a new() one // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "communicator.tmpl", "Communicator", 450, 700) + ui = new(user, src, ui_key, "communicator.tmpl", "Communicator", 475, 700) // when the ui is first opened this is the data it will use ui.set_initial_data(data) // open the new ui window @@ -344,9 +358,20 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(new_name) owner = new_name name = "[owner]'s [initial(name)]" + if(camera) + camera.name = name + camera.c_tag = name if(href_list["toggle_visibility"]) - network_visibility = !network_visibility + switch(network_visibility) + if(1) //Visible, becoming invisbile + network_visibility = 0 + if(camera) + camera.remove_network(NETWORK_COMMUNICATORS) + if(0) //Invisible, becoming visible + network_visibility = 1 + if(camera) + camera.add_network(NETWORK_COMMUNICATORS) if(href_list["toggle_ringer"]) ringer = !ringer @@ -371,6 +396,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list() var/their_address = href_list["dial"] exonet.send_message(their_address, "voice") + if(href_list["decline"]) + var/ref_to_remove = href_list["decline"] + var/atom/decline = locate(ref_to_remove) + if(decline) + del_request(decline) + if(href_list["message"]) if(!get_connection_to_tcomms()) usr << "Error: Cannot connect to Exonet node." @@ -385,10 +416,24 @@ var/global/list/obj/item/device/communicator/all_communicators = list() var/name_to_disconnect = href_list["disconnect"] for(var/mob/living/voice/V in contents) if(name_to_disconnect == V.name) - close_connection(usr, V, "[usr] hung up.") + close_connection(usr, V, "[usr] hung up") for(var/obj/item/device/communicator/comm in communicating) if(name_to_disconnect == comm.name) - close_connection(usr, comm, "[usr] hung up.") + close_connection(usr, comm, "[usr] hung up") + + if(href_list["startvideo"]) + var/ref_to_video = href_list["startvideo"] + var/obj/item/device/communicator/comm = locate(ref_to_video) + if(comm) + connect_video(usr, comm) + + if(href_list["endvideo"]) + if(video_source) + end_video() + + if(href_list["watchvideo"]) + if(video_source) + watch_video(usr,video_source.loc) if(href_list["copy"]) target_address = href_list["copy"] @@ -398,9 +443,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(href_list["hang_up"]) for(var/mob/living/voice/V in contents) - close_connection(usr, V, "[usr] hung up.") + close_connection(usr, V, "[usr] hung up") for(var/obj/item/device/communicator/comm in communicating) - close_connection(usr, comm, "[usr] hung up.") + close_connection(usr, comm, "[usr] hung up") if(href_list["switch_tab"]) selected_tab = href_list["switch_tab"] @@ -475,7 +520,9 @@ var/global/list/obj/item/device/communicator/all_communicators = list() owner = user.name name = "[owner]'s [initial(name)]" - + if(camera) + camera.name = name + camera.c_tag = name // Proc: add_communicating() // Parameters: 1 (comm - the communicator to add to communicating) @@ -485,6 +532,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list() communicating |= comm listening_objects |= src + update_icon() // Proc: del_communicating() // Parameters: 1 (comm - the communicator to remove from communicating) @@ -493,6 +541,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(!comm || !istype(comm)) return communicating.Remove(comm) + update_icon() // Proc: open_connection() // Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device) @@ -601,15 +650,19 @@ var/global/list/obj/item/device/communicator/all_communicators = list() visible_message("\icon[src] [reason].") voice_mobs.Remove(voice) qdel(voice) + update_icon() for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators. if(target && comm != target) continue - comm.visible_message("\icon[src] [reason].") - visible_message("\icon[src] [reason].") src.del_communicating(comm) comm.del_communicating(src) - update_icon() + comm.visible_message("\icon[src] [reason].") + visible_message("\icon[src] [reason].") + if(comm.camera && video_source == comm.camera) //We hung up on the person on video + end_video() + if(camera && comm.video_source == camera) //We hung up on them while they were watching us + comm.end_video() if(voice_mobs.len == 0 && communicating.len == 0) listening_objects.Remove(src) @@ -649,6 +702,29 @@ var/global/list/obj/item/device/communicator/all_communicators = list() if(L) L << "\icon[src] Communications request from [who]." +// Proc: del_request() +// Parameters: 1 (candidate - the ghost or communicator to be declined) +// Description: Declines a request and cleans up both ends +/obj/item/device/communicator/proc/del_request(var/atom/candidate) + if(!(candidate in voice_requests)) + return + + if(isobserver(candidate)) + candidate << "Your communicator call request was declined." + else if(istype(candidate, /obj/item/device/communicator)) + var/obj/item/device/communicator/comm = candidate + comm.voice_invites -= src + + voice_requests -= candidate + + //Search for holder of our device. + var/mob/living/us = null + if(loc && isliving(loc)) + us = loc + + if(us) + us << "\icon[src] Declined request." + // Proc: request_im() // Parameters: 3 (candidate - the communicator wanting to message the device, origin_address - the address of the sender, text - the message) // Description: Response to a communicator trying to message the device. @@ -700,6 +776,8 @@ var/global/list/obj/item/device/communicator/all_communicators = list() all_communicators -= src processing_objects -= src listening_objects.Remove(src) + qdel(camera) + camera = null if(exonet) exonet.remove_address() exonet = null @@ -709,7 +787,11 @@ var/global/list/obj/item/device/communicator/all_communicators = list() // Parameters: None // Description: Self explanatory /obj/item/device/communicator/update_icon() - if(voice_mobs.len > 0) + if(video_source) + icon_state = "communicator-video" + return + + if(voice_mobs.len || communicating.len) icon_state = "communicator-active" return @@ -833,7 +915,71 @@ var/global/list/obj/item/device/communicator/all_communicators = list() src << "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers." -/obj/item/device/communicator/integrated //For synths who have no hands. +// Proc: connect_video() +// Parameters: user - the mob doing the viewing of video, comm - the communicator at the far end +// Description: Sets up a videocall and puts the first view into it using watch_video, and updates the icon +/obj/item/device/communicator/proc/connect_video(mob/user,obj/item/device/communicator/comm) + if((!user) || (!comm) || user.stat) return //KO or dead, or already in a video + + if(video_source) //Already in a video + user << "You are already connected to a video call!" + + if(user.blinded) //User is blinded + user << "You cannot see well enough to do that!" + + if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something + user << "\icon[src]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning." + + user << "\icon[src] Attempting to start video over existing call." + sleep(30) + user << "\icon[src] Please wait..." + + video_source = comm.camera + comm.visible_message("\icon[src] New video connection from [comm].") + watch_video(user) + update_icon() + +// Proc: watch_video() +// Parameters: user - the mob doing the viewing of video +// Description: Moves a mob's eye to the far end for the duration of viewing the far end +/obj/item/device/communicator/proc/watch_video(mob/user) + if(!Adjacent(user) || !video_source) return + user.set_machine(video_source) + user.reset_view(video_source) + user << "Now viewing video session. To leave camera view: OOC -> Cancel Camera View" + spawn(0) + while(user.machine == video_source && Adjacent(user)) + var/turf/T = get_turf(video_source) + if(!T || !is_on_same_plane_or_station(T.z, user.z) || !video_source.can_use()) + user << "The screen bursts into static, then goes black." + video_cleanup(user) + return + sleep(10) + + video_cleanup(user) + +// Proc: video_cleanup() +// Parameters: user - the mob who doesn't want to see video anymore +// Description: Cleans up mob's client when they stop watching a video +/obj/item/device/communicator/proc/video_cleanup(mob/user) + if(!user) return + + user.reset_view(null) + user.unset_machine() + +// Proc: end_video() +// Parameters: reason - the text reason to print for why it ended +// Description: Ends the video call by clearing video_source +/obj/item/device/communicator/proc/end_video(var/reason) + video_source = null + + . = "\icon[src] [reason ? reason : "Video session ended"]." + + visible_message(.) + update_icon() + +//For synths who have no hands. +/obj/item/device/communicator/integrated name = "integrated communicator" desc = "A circuit used for long-range communications, able to be integrated into a system." @@ -864,3 +1010,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list() return src.attack_self(usr) + +// A camera preset for spawning in the communicator +/obj/machinery/camera/communicator + network = list(NETWORK_COMMUNICATORS) + +/obj/machinery/camera/communicator/New() + ..() + client_huds |= global_hud.whitense + client_huds |= global_hud.darkMask \ No newline at end of file diff --git a/code/game/objects/items/weapons/towels.dm b/code/game/objects/items/weapons/towels.dm index 94c266142e5..d51cc8d1d06 100644 --- a/code/game/objects/items/weapons/towels.dm +++ b/code/game/objects/items/weapons/towels.dm @@ -12,3 +12,7 @@ /obj/item/weapon/towel/attack_self(mob/living/user as mob) user.visible_message(text("[] uses [] to towel themselves off.", user, src)) playsound(user, 'sound/weapons/towelwipe.ogg', 25, 1) + +/obj/item/weapon/towel/random/New() + ..() + color = "#"+get_random_colour() \ No newline at end of file diff --git a/code/modules/client/preference_setup/antagonism/01_basic.dm b/code/modules/client/preference_setup/antagonism/01_basic.dm index eefc531da15..5b0be7bb71f 100644 --- a/code/modules/client/preference_setup/antagonism/01_basic.dm +++ b/code/modules/client/preference_setup/antagonism/01_basic.dm @@ -15,6 +15,10 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None") /datum/category_item/player_setup_item/antagonism/basic/sanitize_character() pref.uplinklocation = sanitize_inlist(pref.uplinklocation, uplink_locations, initial(pref.uplinklocation)) +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/antagonism/basic/copy_to_mob(var/mob/living/carbon/human/character) + character.exploit_record = pref.exploit_record + /datum/category_item/player_setup_item/antagonism/basic/content(var/mob/user) . +="Uplink Type : [pref.uplinklocation]" . +="
" diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 6a0c0705aec..da1cab4ecc9 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -40,6 +40,25 @@ datum/preferences/proc/set_biological_gender(var/gender) pref.spawnpoint = sanitize_inlist(pref.spawnpoint, spawntypes, initial(pref.spawnpoint)) pref.be_random_name = sanitize_integer(pref.be_random_name, 0, 1, initial(pref.be_random_name)) +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/general/basic/copy_to_mob(var/mob/living/carbon/human/character) + if(config.humans_need_surnames) + var/firstspace = findtext(pref.real_name, " ") + var/name_length = length(pref.real_name) + if(!firstspace) //we need a surname + pref.real_name += " [pick(last_names)]" + else if(firstspace == name_length) + pref.real_name += "[pick(last_names)]" + + character.real_name = pref.real_name + character.name = character.real_name + if(character.dna) + character.dna.real_name = character.real_name + + character.gender = pref.biological_gender + character.identifying_gender = pref.identifying_gender + character.age = pref.age + /datum/category_item/player_setup_item/general/basic/content() . = list() . += "Name: " diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index a092b859b31..8bd528cb5d6 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -76,6 +76,53 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(!pref.organ_data) pref.organ_data = list() if(!pref.rlimb_data) pref.rlimb_data = list() +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character) + // Copy basic values + character.r_eyes = pref.r_eyes + character.g_eyes = pref.g_eyes + character.b_eyes = pref.b_eyes + character.h_style = pref.h_style + character.r_hair = pref.r_hair + character.g_hair = pref.g_hair + character.b_hair = pref.b_hair + character.f_style = pref.f_style + character.r_facial = pref.r_facial + character.g_facial = pref.g_facial + character.b_facial = pref.b_facial + character.r_skin = pref.r_skin + character.g_skin = pref.g_skin + character.b_skin = pref.b_skin + character.s_tone = pref.s_tone + character.h_style = pref.h_style + character.f_style = pref.f_style + character.b_type = pref.b_type + + // Destroy/cyborgize organs and limbs. + for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO)) + var/status = pref.organ_data[name] + var/obj/item/organ/external/O = character.organs_by_name[name] + if(O) + if(status == "amputated") + O.remove_rejuv() + else if(status == "cyborg") + if(pref.rlimb_data[name]) + O.robotize(pref.rlimb_data[name]) + else + O.robotize() + + for(var/name in list(O_HEART,O_EYES,O_BRAIN)) + var/status = pref.organ_data[name] + if(!status) + continue + var/obj/item/organ/I = character.internal_organs_by_name[name] + if(I) + if(status == "assisted") + I.mechassist() + else if(status == "mechanical") + I.robotize() + return + /datum/category_item/player_setup_item/general/body/content(var/mob/user) . = list() if(!pref.preview_icon) diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm index c455cef524a..537f2632e73 100644 --- a/code/modules/client/preference_setup/general/04_equipment.dm +++ b/code/modules/client/preference_setup/general/04_equipment.dm @@ -18,6 +18,30 @@ S["backbag"] << pref.backbag S["pdachoice"] << pref.pdachoice +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/general/equipment/copy_to_mob(var/mob/living/carbon/human/character) + character.all_underwear.Cut() + character.all_underwear_metadata.Cut() + + for(var/underwear_category_name in pref.all_underwear) + var/datum/category_group/underwear/underwear_category = global_underwear.categories_by_name[underwear_category_name] + if(underwear_category) + var/underwear_item_name = pref.all_underwear[underwear_category_name] + character.all_underwear[underwear_category_name] = underwear_category.items_by_name[underwear_item_name] + if(pref.all_underwear_metadata[underwear_category_name]) + character.all_underwear_metadata[underwear_category_name] = pref.all_underwear_metadata[underwear_category_name] + else + pref.all_underwear -= underwear_category_name + + // TODO - Looks like this is duplicating the work of sanitize_character() if so, remove + if(pref.backbag > 4 || pref.backbag < 1) + pref.backbag = 1 //Same as above + character.backbag = pref.backbag + + if(pref.pdachoice > 3 || pref.pdachoice < 1) + pref.pdachoice = 1 + character.pdachoice = pref.pdachoice + /datum/category_item/player_setup_item/general/equipment/sanitize_character() if(!islist(pref.gear)) pref.gear = list() diff --git a/code/modules/client/preference_setup/general/05_background.dm b/code/modules/client/preference_setup/general/05_background.dm index 5708d3c757e..e3076629a8e 100644 --- a/code/modules/client/preference_setup/general/05_background.dm +++ b/code/modules/client/preference_setup/general/05_background.dm @@ -30,6 +30,16 @@ pref.nanotrasen_relation = sanitize_inlist(pref.nanotrasen_relation, COMPANY_ALIGNMENTS, initial(pref.nanotrasen_relation)) +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/general/background/copy_to_mob(var/mob/living/carbon/human/character) + character.med_record = pref.med_record + character.sec_record = pref.sec_record + character.gen_record = pref.gen_record + character.home_system = pref.home_system + character.citizenship = pref.citizenship + character.personal_faction = pref.faction + character.religion = pref.religion + /datum/category_item/player_setup_item/general/background/content(var/mob/user) . += "Background Information
" . += "[company_name] Relation: [pref.nanotrasen_relation]
" diff --git a/code/modules/client/preference_setup/general/06_flavor.dm b/code/modules/client/preference_setup/general/06_flavor.dm index b312bb95e9b..94525ee06ff 100644 --- a/code/modules/client/preference_setup/general/06_flavor.dm +++ b/code/modules/client/preference_setup/general/06_flavor.dm @@ -36,6 +36,18 @@ /datum/category_item/player_setup_item/general/flavor/sanitize_character() return +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/general/flavor/copy_to_mob(var/mob/living/carbon/human/character) + character.flavor_texts["general"] = pref.flavor_texts["general"] + character.flavor_texts["head"] = pref.flavor_texts["head"] + character.flavor_texts["face"] = pref.flavor_texts["face"] + character.flavor_texts["eyes"] = pref.flavor_texts["eyes"] + character.flavor_texts["torso"] = pref.flavor_texts["torso"] + character.flavor_texts["arms"] = pref.flavor_texts["arms"] + character.flavor_texts["hands"] = pref.flavor_texts["hands"] + character.flavor_texts["legs"] = pref.flavor_texts["legs"] + character.flavor_texts["feet"] = pref.flavor_texts["feet"] + /datum/category_item/player_setup_item/general/flavor/content(var/mob/user) . += "Flavor:
" . += "Set Flavor Text
" diff --git a/code/modules/client/preference_setup/preference_setup.dm b/code/modules/client/preference_setup/preference_setup.dm index 7028894fda4..6344d538e7c 100644 --- a/code/modules/client/preference_setup/preference_setup.dm +++ b/code/modules/client/preference_setup/preference_setup.dm @@ -72,6 +72,10 @@ for(var/datum/category_group/player_setup_category/PS in categories) PS.save_preferences(S) +/datum/category_collection/player_setup_collection/proc/copy_to_mob(var/mob/living/carbon/human/C) + for(var/datum/category_group/player_setup_category/PS in categories) + PS.copy_to_mob(C) + /datum/category_collection/player_setup_collection/proc/header() var/dat = "" for(var/datum/category_group/player_setup_category/PS in categories) @@ -143,6 +147,10 @@ for(var/datum/category_item/player_setup_item/PI in items) PI.save_preferences(S) +/datum/category_group/player_setup_category/proc/copy_to_mob(var/mob/living/carbon/human/C) + for(var/datum/category_item/player_setup_item/PI in items) + PI.copy_to_mob(C) + /datum/category_group/player_setup_category/proc/content(var/mob/user) . = "
" var/current = 0 @@ -201,6 +209,12 @@ /datum/category_item/player_setup_item/proc/save_preferences(var/savefile/S) return +/* +* Called when the item is asked to apply its per character settings to a new mob. +*/ +/datum/category_item/player_setup_item/proc/copy_to_mob(var/mob/living/carbon/human/C) + return + /datum/category_item/player_setup_item/proc/content() return diff --git a/code/modules/client/preference_setup/skills/skills.dm b/code/modules/client/preference_setup/skills/skills.dm index 7255e25bc46..ab5a6c17e10 100644 --- a/code/modules/client/preference_setup/skills/skills.dm +++ b/code/modules/client/preference_setup/skills/skills.dm @@ -18,6 +18,11 @@ if(!pref.skills.len) pref.ZeroSkills() if(pref.used_skillpoints < 0) pref.used_skillpoints = 0 +// Moved from /datum/preferences/proc/copy_to() +/datum/category_item/player_setup_item/skills/copy_to_mob(var/mob/living/carbon/human/character) + character.skills = pref.skills + character.used_skillpoints = pref.used_skillpoints + /datum/category_item/player_setup_item/skills/content() . = list() . += "Select your Skills
" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c26bde7fa0c..6600b78c830 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -254,123 +254,14 @@ datum/preferences // Sanitizing rather than saving as someone might still be editing when copy_to occurs. player_setup.sanitize_setup() - // VOREStation Edit - Start - player_setup.copy_to_mob(character) - // VOREStation Edit - End - + // This needs to happen before anything else becuase it sets some variables. character.set_species(species) - + // Special Case: This references variables owned by two different datums, so do it here. if(be_random_name) real_name = random_name(identifying_gender,species) - if(config.humans_need_surnames) - var/firstspace = findtext(real_name, " ") - var/name_length = length(real_name) - if(!firstspace) //we need a surname - real_name += " [pick(last_names)]" - else if(firstspace == name_length) - real_name += "[pick(last_names)]" - - character.real_name = real_name - character.name = character.real_name - if(character.dna) - character.dna.real_name = character.real_name - - character.flavor_texts["general"] = flavor_texts["general"] - character.flavor_texts["head"] = flavor_texts["head"] - character.flavor_texts["face"] = flavor_texts["face"] - character.flavor_texts["eyes"] = flavor_texts["eyes"] - character.flavor_texts["torso"] = flavor_texts["torso"] - character.flavor_texts["arms"] = flavor_texts["arms"] - character.flavor_texts["hands"] = flavor_texts["hands"] - character.flavor_texts["legs"] = flavor_texts["legs"] - character.flavor_texts["feet"] = flavor_texts["feet"] - - character.med_record = med_record - character.sec_record = sec_record - character.gen_record = gen_record - character.exploit_record = exploit_record - - character.gender = biological_gender - character.identifying_gender = identifying_gender - character.age = age - character.b_type = b_type - - character.r_eyes = r_eyes - character.g_eyes = g_eyes - character.b_eyes = b_eyes - - character.h_style = h_style - character.r_hair = r_hair - character.g_hair = g_hair - character.b_hair = b_hair - - character.f_style = f_style - character.r_facial = r_facial - character.g_facial = g_facial - character.b_facial = b_facial - - character.r_skin = r_skin - character.g_skin = g_skin - character.b_skin = b_skin - - character.s_tone = s_tone - - character.h_style = h_style - character.f_style = f_style - - character.home_system = home_system - character.citizenship = citizenship - character.personal_faction = faction - character.religion = religion - - character.skills = skills - character.used_skillpoints = used_skillpoints - - // Destroy/cyborgize organs and limbs. - for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO)) - var/status = organ_data[name] - var/obj/item/organ/external/O = character.organs_by_name[name] - if(O) - if(status == "amputated") - O.remove_rejuv() - else if(status == "cyborg") - if(rlimb_data[name]) - O.robotize(rlimb_data[name]) - else - O.robotize() - - for(var/name in list(O_HEART,O_EYES,O_BRAIN)) - var/status = organ_data[name] - if(!status) - continue - var/obj/item/organ/I = character.internal_organs_by_name[name] - if(I) - if(status == "assisted") - I.mechassist() - else if(status == "mechanical") - I.robotize() - - character.all_underwear.Cut() - character.all_underwear_metadata.Cut() - - for(var/underwear_category_name in all_underwear) - var/datum/category_group/underwear/underwear_category = global_underwear.categories_by_name[underwear_category_name] - if(underwear_category) - var/underwear_item_name = all_underwear[underwear_category_name] - character.all_underwear[underwear_category_name] = underwear_category.items_by_name[underwear_item_name] - if(all_underwear_metadata[underwear_category_name]) - character.all_underwear_metadata[underwear_category_name] = all_underwear_metadata[underwear_category_name] - else - all_underwear -= underwear_category_name - - if(backbag > 4 || backbag < 1) - backbag = 1 //Same as above - character.backbag = backbag - - if(pdachoice > 3 || pdachoice < 1) - pdachoice = 1 - character.pdachoice = pdachoice + // Ask the preferences datums to apply their own settings to the new mob + player_setup.copy_to_mob(character) if(icon_updates) character.force_update_limbs() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index d61ab57048a..b669647ec93 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1050,7 +1050,11 @@ if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe client.images.Remove(hud) - client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science) + client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.thermal, global_hud.meson, global_hud.science, global_hud.whitense) + + if(istype(client.eye,/obj/machinery/camera)) + var/obj/machinery/camera/cam = client.eye + client.screen |= cam.client_huds if(damageoverlay.overlays) damageoverlay.overlays = list() diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index 69472021b84..f2770d98237 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -132,7 +132,7 @@ reagents.add_reagent("soymilk", 50) /obj/item/weapon/reagent_containers/food/drinks/milk/smallcarton - name = "small chocolate milk carton" + name = "small milk carton" volume = 30 icon_state = "mini-milk" /obj/item/weapon/reagent_containers/food/drinks/milk/smallcarton/New() @@ -140,9 +140,9 @@ reagents.add_reagent("milk", 30) /obj/item/weapon/reagent_containers/food/drinks/milk/smallcarton/chocolate - name = "Small Carton of Chocolate Milk" + name = "small chocolate milk carton" desc = "It's milk! This one is in delicious chocolate flavour." - + icon_state = "mini-milk_choco" /obj/item/weapon/reagent_containers/food/drinks/milk/smallcarton/chocolate/New() ..() reagents.add_reagent("chocolate_milk", 30) diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index cba5ea04cae..2c2e234a3ff 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/nano/templates/communicator.tmpl b/nano/templates/communicator.tmpl index bb0a26842f5..58b86a30d7e 100644 --- a/nano/templates/communicator.tmpl +++ b/nano/templates/communicator.tmpl @@ -103,7 +103,12 @@ Used In File(s): code\game\objects\items\devices\communicator\communicator.dm {{:value.name}}
-
{{:helper.link('Disconnect', 'close', {'disconnect' : value.true_name}, null, 'redButton')}}
+ {{:helper.link('Disconnect', 'close', {'disconnect' : value.true_name}, null, 'redButton')}} + {{if data.video_comm == null}} + {{:helper.link('Start Video', 'signal-diag', {'startvideo' : value.ref})}} + {{else data.video_comm == value.ref}} + {{:helper.link('End Video', 'signal-diag', {'endvideo' : value.true_name}, null, 'redButton')}} + {{/if}}
{{/for}} @@ -114,7 +119,7 @@ Used In File(s): code\game\objects\items\devices\communicator\communicator.dm {{:value.name}}
-
{{:value.address}}
{{:helper.link('Dial', 'signal-diag', {'dial' : value.address})}} +
{{:value.address}}
{{:helper.link('Accept', 'signal-diag', {'dial' : value.address})}}{{:helper.link('Decline', 'close', {'decline' : value.ref})}}
{{/for}}