diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 06e7af036bd..e1279431002 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -621,3 +621,16 @@ #define TATTOO_VISIBILITY_RANGE 3 #define SIMPLEMOB_IGNORE 1 + +#define PHUD_NONE "GENITAL_HUD_NONE" +#define PHUD_BUTT "GENITAL_HUD_BUTT" +#define PHUD_BOOB "GENITAL_HUD_BREASTS" +#define PHUD_PENIS "GENITAL_HUD_PEEN" +#define PHUD_BALLS "GENITAL_HUD_BALLS" +#define PHUD_VAG "GENITAL_HUD_VAG" +#define PHUD_BELLY "GENITAL_HUD_BELLY" +#define PHUD_TAIL "GENITAL_HUD_TAIL" +#define PHUD_WINGS "GENITAL_HUD_WINGS" +#define PHUD_SHIRT "GENITAL_HUD_SHIRT" +#define PHUD_PANTS "GENITAL_HUD_PANTS" +#define PHUD_SOCKS "GENITAL_HUD_SOCKS" diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 510abda5e43..cbabe3f5986 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -124,7 +124,7 @@ var/name = input(user, message, title, default) as message|null if(isnull(name)) // Return null if canceled. return null - if(!check_rights_for(user?.client, R_ADMIN) || i_will_sanitize_dont_worry) + if(!check_rights(R_ADMIN, FALSE) || i_will_sanitize_dont_worry) name = strip_html_simple(name, max_length) // I'd prefer not to stab myself with a url if(length(name) > max_length) to_chat(user, name) diff --git a/code/controllers/subsystem/pornhud.dm b/code/controllers/subsystem/pornhud.dm new file mode 100644 index 00000000000..274ce92e936 --- /dev/null +++ b/code/controllers/subsystem/pornhud.dm @@ -0,0 +1,411 @@ +// A cute lil subsystem that draws pictures of peoples butts and wieners on your screen +SUBSYSTEM_DEF(pornhud) + name = "PornHUD" + wait = 0.5 SECONDS + flags = SS_NO_INIT|SS_BACKGROUND + + // list of all bits + /// format: list("Jimmy Shits" = /datum/genital_images) + var/list/hoohaws = list() + /// players who need a full on update of everyone's genitals + var/list/needs_updating = list() + /// genical datums that need to be sent to all players + var/list/gunts_changed = list() + var/list/currentrun = list() + var/list/guntrun = list() + var/image_cache_max = 512 + var/max_whitelist_search = 15 + var/debug_force_broadcast_update = TRUE + var/debug_force_request_update = TRUE + var/debug_clotheshud = TRUE // coming soon in 2096 + +/datum/controller/subsystem/pornhud/fire(resumed) + if (!resumed) + guntrun = gunts_changed.Copy() + currentrun = needs_updating.Copy() + needs_updating = list() + gunts_changed = list() + //cache for sanic speed (lists are references anyways) + var/list/gunt_run = guntrun + var/list/current_run = currentrun + + while(current_run.len) + var/ckey = current_run[current_run.len] + current_run.len-- + var/mob/living/carbon/human/dork = ckey2mob(ckey) + if(!dork) + continue + send_everything_to_viewer(dork, debug_force_request_update) + if (MC_TICK_CHECK) + return + + while(gunt_run.len) + var/datum/genital_images/GI = gunt_run[gunt_run.len] + gunt_run.len-- + if(!GI) + continue + send_genitals_to_everyone(GI, debug_force_broadcast_update) + if (MC_TICK_CHECK) + return + +/datum/controller/subsystem/pornhud/proc/catalogue_part(mob/living/dork, part, list/images = list()) + if(!isliving(dork) || !part) + return + var/datum/genital_images/GI = get_genital_datum(dork) + GI.add_part(part, images) + return TRUE + +/datum/controller/subsystem/pornhud/proc/get_genital_datum(mob/living/carbon/human/dork) + if(!ishuman(dork)) + return + if(!dork.pornhud_key) + generate_key(dork) + var/datum/genital_images/GI = LAZYACCESS(hoohaws, dork.pornhud_key) + if(!GI) + GI = new /datum/genital_images(dork) + hoohaws[dork.pornhud_key] = GI + return GI + +/// A player changed their view settings, so we need to give them a fresh +/// copy of everyone's genitals +/datum/controller/subsystem/pornhud/proc/request_every_genital(mob/living/dork) + if(!dork.client) + return + needs_updating |= dork.ckey + +/// A set of genitals changed, so we need to send everyone a fresh copy of these +/datum/controller/subsystem/pornhud/proc/request_genital_broadcast(datum/genital_images/GI) + gunts_changed |= GI + +/// flush a player's genital images, and give them a fresh copy of everyone's +/// This is the *viewer*, so it'll pull everyone's images +/// Force is happen when the *viewer* changed their settings +/datum/controller/subsystem/pornhud/proc/send_everything_to_viewer(mob/living/dork, force) + if(!dork.client) + return + for(var/mobname in hoohaws) + var/datum/genital_images/GI = hoohaws[mobname] + GI.show_images_to(dork, force) + +/// A genital thing has updated, so we need to send it to everyone +/datum/controller/subsystem/pornhud/proc/send_genitals_to_everyone(datum/genital_images/gunt, force) + for(var/mob/seer in GLOB.player_list) + gunt.show_images_to(seer, force) + +/datum/controller/subsystem/pornhud/proc/flush_genitals(mob/living/carbon/human/flusher) + if(!ishuman(flusher)) + return + var/datum/genital_images/GI = get_genital_datum(flusher) + if(!GI) + return + GI.flush_genitals() + +/datum/controller/subsystem/pornhud/proc/flush_undies(mob/living/carbon/human/flusher) + if(!ishuman(flusher)) + return + var/datum/genital_images/GI = get_genital_datum(flusher) + if(!GI) + return + GI.flush_genitals() + +/datum/controller/subsystem/pornhud/proc/update_visibility(mob/living/carbon/human/dork, part, on_off) + if(!ishuman(dork)) + return + var/datum/genital_images/GI = get_genital_datum(dork) + if(!GI) + return + GI.update_visibility(part, on_off) + +/datum/controller/subsystem/pornhud/proc/generate_key(mob/living/carbon/human/newnadhaver) + if(!ishuman(newnadhaver)) + return + if(newnadhaver.pornhud_key) + return + var/key = newnadhaver.ckey ? "[newnadhaver.ckey]-" : "stiff-" + key += "[LAZYLEN(hoohaws) + 1]-" + key += "[newnadhaver.real_name]-" + key += "[world.time]-bepis" + newnadhaver.pornhud_key = key + return key + +// scornhud +/mob/living/carbon/human + var/pornhud_key + +/// Holds all the genital images of a single human mob +/// This is the *owner*, so it'll only pull their own images +/// also defines if they're visible or not +/// get_all_images() will return a list of all images that should be visible +/// It'll not send images that the viewer has set to be hidden +/datum/genital_images + var/datum/weakref/owner + + /// ckeys with people we've already shown our genitals to + var/list/shown_to = list() + + var/list/butt = list() + var/butt_visible + + var/list/breasts = list() + var/breasts_visible + + var/list/peen = list() + var/peen_visible + + var/list/balls = list() + var/balls_visible + + var/list/vag = list() + var/vag_visible + + var/list/belly = list() + var/belly_visible + + var/list/tail = list() // nice and suggestive + var/tail_visible + + var/list/wings = list() // dingo wings + var/wings_visible + + var/image/undershirt + var/shirt_visible + + var/image/underpants + var/underpants_visible + + var/image/socks + var/socks_visible + + /// if this is true, the player has changed their appearance since the last time we updated + var/has_changed + + var/undies_over_genitals = TRUE + + /// massive, unwashed list of all images that were on the player at some point + /// pruned? why? not like we'd be using that ram for anything else + var/list/old_image_cache = list() + +/datum/genital_images/New(mob/living/carbon/human/newowner) + . = ..() + owner = WEAKREF(newowner) + +/// is this player whitelisted? +/// if so, they can see genitals even if they're hidden +/datum/genital_images/proc/is_whitelisted(mob/someone) + if(!someone || !someone.client) + return FALSE + var/datum/preferences/P = extract_prefs(someone) + var/list/whitelist = splittext(P.genital_whitelist, ",") + var/index = 1 + for(var/entry in whitelist) + entry = ckey(entry) + if(findtext(ckey(someone.real_name), entry)) + return TRUE + if(findtext(entry, ckey(someone.real_name))) + return TRUE + if(findtext(ckey(someone.name), entry)) + return TRUE + if(findtext(entry, ckey(someone.name))) + return TRUE + if(index++ > SSpornhud.max_whitelist_search) + return FALSE + +// add a part to the list +/datum/genital_images/proc/add_part(part, list/images) + if(!islist(images)) + if(isnull(images)) + images = list() + else + images = list(images) + var/list/images2change + switch(part) + if(PHUD_BUTT) + images2change = butt + if(PHUD_BOOB) + images2change = breasts + if(PHUD_PENIS) + images2change = peen + if(PHUD_BALLS) + images2change = balls + if(PHUD_VAG) + images2change = vag + if(PHUD_BELLY) + images2change = belly + if(PHUD_TAIL) + images2change = tail + if(PHUD_WINGS) + images2change = wings + if(PHUD_SHIRT) + images2change = undershirt + if(PHUD_PANTS) + images2change = underpants + if(PHUD_SOCKS) + images2change = socks + if(!LAZYLEN(images ^ images2change)) + return // nothing changed + switch(part) + if(PHUD_BUTT) + butt = images + if(PHUD_BOOB) + breasts = images + if(PHUD_PENIS) + peen = images + if(PHUD_BALLS) + balls = images + if(PHUD_VAG) + vag = images + if(PHUD_BELLY) + belly = images + if(PHUD_TAIL) + tail = images + if(PHUD_WINGS) + wings = images + if(PHUD_SHIRT) + undershirt = images + if(PHUD_PANTS) + underpants = images + if(PHUD_SOCKS) + socks = images + set_changed() + +/datum/genital_images/proc/update_visibility(part, on_off) + switch(part) + if(PHUD_BUTT) + if(butt_visible == on_off) + return + butt_visible = on_off + if(PHUD_BOOB) + if(breasts_visible == on_off) + return + breasts_visible = on_off + if(PHUD_PENIS) + if(peen_visible == on_off) + return + peen_visible = on_off + if(PHUD_BALLS) + if(balls_visible == on_off) + return + balls_visible = on_off + if(PHUD_VAG) + if(vag_visible == on_off) + return + vag_visible = on_off + if(PHUD_BELLY) + if(belly_visible == on_off) + return + belly_visible = on_off + if(PHUD_TAIL) + if(tail_visible == on_off) + return + tail_visible = on_off + if(PHUD_WINGS) + if(wings_visible == on_off) + return + wings_visible = on_off + if(PHUD_SHIRT) + if(shirt_visible == on_off) + return + shirt_visible = on_off + if(PHUD_PANTS) + if(underpants_visible == on_off) + return + underpants_visible = on_off + if(PHUD_SOCKS) + if(socks_visible == on_off) + return + socks_visible = on_off + set_changed() + +/datum/genital_images/proc/cache_images(list/imgs = list()) + for(var/imgl in imgs) + old_image_cache |= imgs[imgl] + if(LAZYLEN(old_image_cache) >= SSpornhud.image_cache_max) + var/num_to_remove = LAZYLEN(old_image_cache) - SSpornhud.image_cache_max + if(num_to_remove > 1) + old_image_cache.Cut(1, num_to_remove) + +/datum/genital_images/proc/show_images_to(mob/seer, force) + if(!seer || !seer.client) + return // they cant see us! + if(shown_to[seer.ckey] && !force) + return // no need to update + shown_to[seer.ckey] = TRUE + remove_images(seer) + var/list/imgs = get_all_images(seer.client.prefs) + add_images(seer, imgs) + +/datum/genital_images/proc/remove_images(mob/seer) + if(!seer) + return + seer.client.images -= old_image_cache + +/datum/genital_images/proc/add_images(mob/seer, list/imgs = list()) + if(!seer) + return + for(var/imglayer in imgs) + seer.client.images += imgs[imglayer] + +/datum/genital_images/proc/get_all_images(datum/preferences/P) + if(!P) + return + var/list/all_images = list() + var/mob/living/carbon/human/myowner = GET_WEAKREF(owner) + if(!ishuman(myowner)) + return + var/list/image_order = myowner.dna.decode_cockstring(FALSE) + var/preflag = is_whitelisted(P.parent.mob) ? NONE : P.features["genital_hide"] + for(var/entry in image_order) + switch(entry) + if(CS_BUTT) + if(butt_visible && !CHECK_BITFIELD(preflag, HIDE_BUTT)) + all_images += butt + if(CS_BOOB) + if(breasts_visible && !CHECK_BITFIELD(preflag, HIDE_BOOBS)) + all_images += breasts + if(CS_PENIS) + if(peen_visible && !CHECK_BITFIELD(preflag, HIDE_PENIS)) + all_images += peen + if(CS_BALLS) + if(balls_visible && !CHECK_BITFIELD(preflag, HIDE_BALLS)) + all_images += balls + if(CS_VAG) + if(vag_visible && !CHECK_BITFIELD(preflag, HIDE_VAG)) + all_images += vag + if(CS_BELLY) + if(belly_visible && !CHECK_BITFIELD(preflag, HIDE_BELLY)) + all_images += belly + if(tail && tail_visible) + all_images += tail + var/list/imgsformatted = list() + for(var/image/I in all_images) + var/image/flat = imgsformatted["[I.layer]"] + if(!flat) + flat = image('icons/mob/hud.dmi', myowner, "") + flat.appearance_flags = RESET_COLOR|RESET_TRANSFORM + imgsformatted["[I.layer]"] = flat + flat.overlays += I + cache_images(imgsformatted) + return imgsformatted + +/datum/genital_images/proc/flush_genitals() + var/changed = LAZYLEN(butt) || LAZYLEN(breasts) || LAZYLEN(peen) || LAZYLEN(balls) || LAZYLEN(vag) || LAZYLEN(belly) + butt = list() + breasts = list() + peen = list() + balls = list() + vag = list() + belly = list() + if(changed) + set_changed() + return TRUE + +/datum/genital_images/proc/flush_undies() + cache_images(get_all_images()) + undershirt = null + underpants = null + socks = null + return TRUE + +/datum/genital_images/proc/set_changed() + shown_to.Cut() + SSpornhud.request_genital_broadcast(src) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 8efa1bddd75..2d0131fffbb 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -747,10 +747,12 @@ /// takes in whatever's at features["genital_order"] and spits out a list in order of what's present /// reverses it cus its more intuitive that way (for everyone but me) -/datum/dna/proc/decode_cockstring() +/datum/dna/proc/decode_cockstring(reverse = TRUE) + RETURN_TYPE(/list) var/list/list_out = list() list_out = splittext(features["genital_order"], ":") - list_out = reverseList(list_out) + if(reverse) + list_out = reverseList(list_out) return list_out /// takes in a list of nads and outputs a cockstring, then saves it diff --git a/code/datums/hud.dm b/code/datums/hud.dm index c3a2b2a3302..4532a9c6651 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -31,8 +31,6 @@ GLOBAL_LIST_INIT(huds, list( ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(), ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden(), DATA_HUD_CLIENT = new/datum/atom_hud/data/client(), - GENITAL_PORNHUD = new/datum/atom_hud/data/human/genital(), - TAIL_HUD_DATUM = new/datum/atom_hud/data/human/tail(), )) /datum/atom_hud diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm index 01b4b993634..c211a7d6cc1 100644 --- a/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -2,6 +2,7 @@ color = "#fcccb3" w_class = WEIGHT_CLASS_SMALL organ_flags = ORGAN_NO_DISMEMBERMENT|ORGAN_EDIBLE + var/pornhud_slot = PHUD_NONE var/associated_has = CS_MISC // for cockstring stuff var/shape var/sensitivity = 1 // wow if this were ever used that'd be cool but it's not but i'm keeping it for my unshit code @@ -61,6 +62,11 @@ var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed /obj/item/organ/genital/proc/is_exposed() + var/exposed = check_exposure() + SSpornhud.update_visibility(owner, pornhud_slot, exposed) + return exposed + +/obj/item/organ/genital/proc/check_exposure() if(!owner || CHECK_BITFIELD(genital_flags,GENITAL_INTERNAL) || CHECK_BITFIELD(genital_visflags,GENITAL_ALWAYS_HIDDEN)) return FALSE if(CHECK_BITFIELD(genital_visflags,GENITAL_ALWAYS_VISIBLE)) @@ -454,30 +460,31 @@ if (NOGENITALS in dna.species.species_traits) return if(dna.features["has_vag"]) - give_genital(/obj/item/organ/genital/vagina) + give_genital(/obj/item/organ/genital/vagina, FALSE) if(dna.features["has_womb"]) - give_genital(/obj/item/organ/genital/womb) + give_genital(/obj/item/organ/genital/womb, FALSE) if(dna.features["has_balls"]) - give_genital(/obj/item/organ/genital/testicles) + give_genital(/obj/item/organ/genital/testicles, FALSE) if(dna.features["has_breasts"]) - give_genital(/obj/item/organ/genital/breasts) + give_genital(/obj/item/organ/genital/breasts, FALSE) if(dna.features["has_butt"]) - give_genital(/obj/item/organ/genital/butt) + give_genital(/obj/item/organ/genital/butt, FALSE) if(dna.features["has_cock"]) - give_genital(/obj/item/organ/genital/penis) + give_genital(/obj/item/organ/genital/penis, FALSE) if(dna.features["has_belly"]) - give_genital(/obj/item/organ/genital/belly) + give_genital(/obj/item/organ/genital/belly, FALSE) + update_body(TRUE) -/mob/living/carbon/human/proc/give_genital(obj/item/organ/genital/G) +/mob/living/carbon/human/proc/give_genital(obj/item/organ/genital/G, update = TRUE) if(!dna || (NOGENITALS in dna.species.species_traits) || getorganslot(initial(G.slot))) return FALSE G = new G(null, FALSE) - G.get_features(src) + G.get_features(src, update) G.Insert(src) return G /// Called when the giblet is first stuffed into the mob -/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H) +/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H, update = TRUE) return /// Returns its respective sprite accessory from the global list (full of init'd types, hopefully) @@ -520,15 +527,15 @@ /// Holds a list of relevant genital layers and positions GLOBAL_LIST_INIT(genital_layers, list( - "layers" = list( - GENITALS_BEHIND_LAYER, - GENITAL_UNDER_UNDERWEAR_FRONT_LAYER, - GENITAL_UNDER_UNDERWEAR_MID_LAYER, - GENITAL_OVER_UNDERWEAR_FRONT_LAYER, - GENITAL_OVER_UNDERWEAR_MID_LAYER, - GENITAL_OVER_CLOTHES_FRONT_LAYER, - GENITAL_OVER_CLOTHES_MID_LAYER, - ), + // "layers" = list( + // GENITALS_BEHIND_LAYER, + // GENITAL_UNDER_UNDERWEAR_FRONT_LAYER, + // GENITAL_UNDER_UNDERWEAR_MID_LAYER, + // GENITAL_OVER_UNDERWEAR_FRONT_LAYER, + // GENITAL_OVER_UNDERWEAR_MID_LAYER, + // GENITAL_OVER_CLOTHES_FRONT_LAYER, + // GENITAL_OVER_CLOTHES_MID_LAYER, + // ), "positions" = list( "BEHIND", "MID", @@ -546,15 +553,9 @@ GLOBAL_LIST_INIT(genital_layers, list( return for(var/layernum in GLOB.genital_layers["layers"]) // Clear all our genital overlays remove_overlay(layernum) - var/datum/atom_hud/data/human/genital/pornHUD = GLOB.huds[GENITAL_PORNHUD] - if(!islist(hud_list)) - prepare_huds() - pornHUD.remove_from_hud(src, signal) - if(!LAZYLEN(internal_organs) || ((NOGENITALS in dna.species.species_traits) && !genital_override) || HAS_TRAIT(src, TRAIT_HUSK)) - return + SSpornhud.flush_genitals(src) //okay cool, compile a list of genitals that are visible - var/list/genitals_to_add[GENITAL_LAYER_INDEX_LENGTH] var/has_nads = FALSE var/list/nad_order = splittext(dna?.features["genital_order"], ":") // NOT reversed cus the reversal is only for UI shit @@ -567,9 +568,8 @@ GLOBAL_LIST_INIT(genital_layers, list( /// for the fuckin preview thing var/list/genital_sprites = list() // format list("[layer_number]" = list(mutable_sprites)) - /// for the actual PornHud - var/list/porn_hud_images = list() // format list("has_butt" = list("FRONT" = list(img, img, img))") // I FUCKIN LOVE HUGEASS LISTS for(var/obj/item/organ/genital/nad in genitals_to_add) + var/list/nadpics = list() // list of sprites for these genitals (usually one or two) for(var/position in GLOB.genital_layers["positions"]) // "BEHIND", "MID", "FRONT" var/layer_to_put_it = nad.get_layer_number(position) @@ -619,25 +619,15 @@ GLOBAL_LIST_INIT(genital_layers, list( if(!genital_sprites["[layer_to_put_it]"]) genital_sprites["[layer_to_put_it]"] = list() - if(!porn_hud_images["[nad.associated_has]"]) - porn_hud_images["[nad.associated_has]"] = list() - - if(!porn_hud_images["[nad.associated_has]"]["[position]"]) - porn_hud_images["[nad.associated_has]"]["[position]"] = list() - // cus byond doesnt like arbitrary indexes or something, idk im dum genital_sprites["[layer_to_put_it]"] |= genital_overlay - porn_hud_images["[nad.associated_has]"]["[position]"] |= gross_image // i hate everything about this + nadpics += gross_image + SSpornhud.catalogue_part(src, nad.pornhud_slot, nadpics) if(istype(src, /mob/living/carbon/human/dummy)) // cus our user eyes dont have PornHUDs in the character prefs window for(var/index in genital_sprites) overlays_standing[text2num(index)] = genital_sprites[index] apply_overlay(text2num(index)) - - if(!LAZYLEN(porn_hud_images)) // the freshest! - return // nothing there? *shruggo* - hud_list[GENITAL_HUD] = porn_hud_images - pornHUD.add_to_hud(src, signal) //Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours. /mob/living/carbon/human/proc/emergent_genital_call() diff --git a/code/modules/arousal/organs/belly.dm b/code/modules/arousal/organs/belly.dm index 5d4d9ba8163..83280abec2c 100644 --- a/code/modules/arousal/organs/belly.dm +++ b/code/modules/arousal/organs/belly.dm @@ -300,6 +300,7 @@ GLOBAL_LIST_INIT(belly_descriptors, list( var/shape_kind = "tummy" associated_has = CS_BELLY // for cockstring stuff hide_flag = HIDE_BELLY // for hideflag stuff + pornhud_slot = PHUD_BELLY /obj/item/organ/genital/belly/modify_size(modifier, min = BELLY_SIZE_MIN, max = BELLY_SIZE_MAX) var/new_value = clamp(cached_size + modifier, min, max) diff --git a/code/modules/arousal/organs/breasts.dm b/code/modules/arousal/organs/breasts.dm index 2ab231e8dda..5b3d0ff963a 100644 --- a/code/modules/arousal/organs/breasts.dm +++ b/code/modules/arousal/organs/breasts.dm @@ -21,6 +21,7 @@ fluid_transfer_factor = 0.5 associated_has = CS_BOOB // for cockstring stuff hide_flag = HIDE_BOOBS // for hideflag stuff + pornhud_slot = PHUD_BOOB GLOBAL_LIST_INIT(breast_values, list( "a" = 1, diff --git a/code/modules/arousal/organs/butt.dm b/code/modules/arousal/organs/butt.dm index f0a93d36c93..76339265420 100644 --- a/code/modules/arousal/organs/butt.dm +++ b/code/modules/arousal/organs/butt.dm @@ -48,6 +48,7 @@ GLOBAL_LIST_INIT(butt_descriptors, list( masturbation_verb = "massage" associated_has = CS_BUTT // for cockstring stuff hide_flag = HIDE_BUTT // for hideflag stuff + pornhud_slot = PHUD_BUTT /obj/item/organ/genital/butt/modify_size(modifier, min = BUTT_SIZE_MIN, max = BUTT_SIZE_MAX) var/new_value = clamp(cached_size + modifier, min, max) diff --git a/code/modules/arousal/organs/penis.dm b/code/modules/arousal/organs/penis.dm index 138730ae540..150bd00386a 100644 --- a/code/modules/arousal/organs/penis.dm +++ b/code/modules/arousal/organs/penis.dm @@ -21,6 +21,7 @@ var/diameter_ratio = COCK_DIAMETER_RATIO_DEF //0.25; check citadel_defines.dm associated_has = CS_PENIS // for cockstring stuff hide_flag = HIDE_PENIS // for hideflag stuff + pornhud_slot = PHUD_PENIS /obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY) var/new_value = clamp(length + modifier, min, max) diff --git a/code/modules/arousal/organs/testicles.dm b/code/modules/arousal/organs/testicles.dm index 662f75915b7..bbae7536dd0 100644 --- a/code/modules/arousal/organs/testicles.dm +++ b/code/modules/arousal/organs/testicles.dm @@ -17,6 +17,7 @@ layer_index = TESTICLES_LAYER_INDEX associated_has = CS_BALLS // for cockstring stuff hide_flag = HIDE_BALLS // for hideflag stuff + pornhud_slot = PHUD_BALLS /obj/item/organ/genital/testicles/generate_fluid() if(!linked_organ && !update_link()) diff --git a/code/modules/arousal/organs/vagina.dm b/code/modules/arousal/organs/vagina.dm index 24815a6e046..befcd83500b 100644 --- a/code/modules/arousal/organs/vagina.dm +++ b/code/modules/arousal/organs/vagina.dm @@ -22,6 +22,7 @@ var/list/vag_types = list("tentacle", "dentata", "hairy", "spade", "furred", "inconspicuous") associated_has = CS_VAG // for cockstring stuff hide_flag = HIDE_VAG // for hideflag stuff + pornhud_slot = PHUD_VAG /obj/item/organ/genital/vagina/update_appearance() . = ..() diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index c4ea0f24558..db9ccbdc2df 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -1136,6 +1136,7 @@ GLOBAL_LIST_EMPTY(every_fucking_sound_file) if (menuitem) menuitem.Load_checked(src) +/* /client/proc/checkGonadDistaste(flag) if(!flag || !prefs) return @@ -1223,3 +1224,4 @@ GLOBAL_LIST_EMPTY(every_fucking_sound_file) to_chat(src, span_notice("Toggled seeing genitals on [nicebutt].")) nicebutt.update_genitals(TRUE) return TRUE + */ diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 948ed00d564..6dc7bbd8f13 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -79,12 +79,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/pda_color = "#808000" var/pda_skin = PDA_SKIN_CLASSIC - var/uses_glasses_colour = 0 - + var/genital_whitelist = "" var/whoflags = DEFAULT_WHO_FLAGS - /// What who change things are they banned from? - /// here cus I dont know how bans work lol - var/lockouts = 0 + var/lockouts = NONE + + var/uses_glasses_colour = 0 //character preferences var/real_name //our character's name @@ -2182,11 +2181,26 @@ GLOBAL_LIST_EMPTY(preferences_datums) // return bal + 33 //max 33 point regardless of how many prosthetics // return bal -// /datum/preferences/proc/GetPositiveQuirkCount() -// . = 0 -// for(var/q in char_quirks) -// if(SSquirks.quirk_points[q] > 0) -// .++ +/datum/preferences/proc/update_genital_whitelist() + var/new_genital_whitelist = stripped_multiline_input_or_reflect( + parent, + "Which people are you okay with seeing their genitals when exposed? If a humanlike mob has a name containing \ + any of the following, if their genitals are showing, you will be able to see them, regardless of your \ + content settings. Partial names are accepted, case is not important, please no punctuation (except ','). \ + Separate your entries with a comma!", + "Genital Whitelist", + genital_whitelist) + if(isnull(new_genital_whitelist)) + to_chat(parent, "Never mind!!") + return + if(trim(new_genital_whitelist) == "" && trim(genital_whitelist) != "") + var/whoa = alert(usr, "Are you sure you want to clear your genital whitelist?", "Clear Genital Whitelist", "Yes", "No") + if(whoa == "No") + to_chat(parent, "Never mind!!") + return + genital_whitelist = new_genital_whitelist + to_chat(parent, span_notice("Updated your genital whitelist! It should kick in soon!")) + save_preferences() /datum/preferences/Topic(href, href_list, hsrc) //yeah, gotta do this I guess.. . = ..() @@ -2224,20 +2238,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(href_list["preference"] == "change_genital_order") shift_genital_order(href_list["which"], (href_list["direction"]=="up")) if(href_list["preference"] == "change_genital_whitelist") - var/new_genital_whitelist = stripped_multiline_input_or_reflect( - user, - "Which people are you okay with seeing their genitals when exposed? If a humanlike mob has a name containing \ - any of the following, if their genitals are showing, you will be able to see them, regardless of your \ - content settings. Partial names are accepted, case is not important, please no punctuation (except ','). \ - Keep in mind this matches their 'real' name, so 'unknown' likely won't do much. Separate your entries with a comma!", - "Genital Whitelist", - features["genital_whitelist"]) - if(new_genital_whitelist == "") - var/whoathere = alert(user, "This will clear your genital whitelist, you sure?", "Just checkin'", "Yes", "No") - if(whoathere == "Yes") - features["genital_whitelist"] = new_genital_whitelist - else if(!isnull(new_genital_whitelist)) - features["genital_whitelist"] = new_genital_whitelist + update_genital_whitelist() if(href_list["preference"] == "change_genital_clothing") var/list/genital_overrides = GENITAL_CLOTHING_FLAG_LIST var/new_visibility = input(user, "When your genitals are visible, how should they appear in relation to your clothes/underwear?", "Character Preference", href_list["nadflag"]) as null|anything in GENITAL_CLOTHING_FLAG_LIST diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 98f93238949..789ad495833 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -198,10 +198,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car whoflags = DEFAULT_WHO_FLAGS WRITE_FILE(S["whoflags"], whoflags) current_version |= PMC_DAN_MESSED_UP_WHO_STUFF // uncomment before release - //if(PMC_PORNHUD_WHITELIST_RELOCATION) // i moved the thing out of features - //S["feature_genital_whitelist"] >> genital_whitelist - //WRITE_FILE(S["genital_whitelist"], genital_whitelist) - //current_version |= PMC_PORNHUD_WHITELIST_RELOCATION + if(PMC_PORNHUD_WHITELIST_RELOCATION) // i moved the thing out of features + S["feature_genital_whitelist"] >> genital_whitelist + WRITE_FILE(S["genital_whitelist"], genital_whitelist) + current_version |= PMC_PORNHUD_WHITELIST_RELOCATION WRITE_FILE(S["current_version"], safe_json_encode(current_version)) /datum/preferences/proc/load_path(ckey,filename="preferences.sav") @@ -298,6 +298,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["auto_ooc"] >> auto_ooc S["no_tetris_storage"] >> no_tetris_storage S["aghost_squelches"] >> aghost_squelches + S["genital_whitelist"] >> genital_whitelist S["lockouts"] >> lockouts // my bans! @@ -316,6 +317,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car //Sanitize ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor))) lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) + genital_whitelist = sanitize_text(genital_whitelist, initial(genital_whitelist)) UI_style = sanitize_inlist(UI_style, GLOB.available_ui_styles, GLOB.available_ui_styles[1]) hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys)) chat_on_map = sanitize_integer(chat_on_map, 0, 1, initial(chat_on_map)) @@ -467,6 +469,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["no_tetris_storage"], no_tetris_storage) WRITE_FILE(S["lockouts"], lockouts) WRITE_FILE(S["aghost_squelches"], aghost_squelches) + WRITE_FILE(S["genital_whitelist"], genital_whitelist) return 1 /datum/preferences/proc/load_character(slot) @@ -574,7 +577,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car "belly_visibility_flags" = GEN_VIS_FLAG_DEFAULT, "genital_visibility_flags" = GEN_VIS_OVERALL_FLAG_DEFAULT, "genital_order" = DEF_COCKSTRING, - "genital_whitelist" = "Mr Bingus, fluntly, Doc Bungus", "genital_hide" = NONE, @@ -782,7 +784,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["feature_has_womb"] >> features["has_womb"] //cockstring S["feature_genital_order"] >> features["genital_order"] - S["feature_genital_whitelist"] >> features["genital_whitelist"] S["feature_genital_hide"] >> features["genital_hide"] S["feature_genital_visibility_flags"] >> features["genital_visibility_flags"] //taste @@ -1021,7 +1022,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["genital_order"] = sanitize_text(features["genital_order"], DEF_COCKSTRING) features["genital_hide"] = sanitize_integer(features["genital_hide"], 0, 4096, 0) - features["genital_whitelist"] = copytext(features["genital_whitelist"], 1, MAX_MESSAGE_LEN) features["taste"] = copytext(features["taste"], 1, MAX_TASTE_LEN) features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN) features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN) @@ -1240,7 +1240,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_belly_visibility_flags"], features["belly_visibility_flags"]) WRITE_FILE(S["feature_genital_order"], features["genital_order"]) WRITE_FILE(S["feature_genital_hide"], features["genital_hide"]) - WRITE_FILE(S["feature_genital_whitelist"], features["genital_whitelist"]) WRITE_FILE(S["feature_genital_visibility_flags"], features["genital_visibility_flags"]) WRITE_FILE(S["feature_has_vag"], features["has_vag"]) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e011a551287..e289fb59d61 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -327,9 +327,9 @@ dna.features["genital_visibility_flags"] = new_bit for(var/obj/item/organ/genital/nad in internal_organs) nad.update_genital_visibility(new_bit) - if(ishuman(src)) // lesigh - var/mob/living/carbon/human/dip = src - dip.update_body(TRUE) + // if(ishuman(src)) // lesigh + // var/mob/living/carbon/human/dip = src + // dip.update_body(TRUE) show_genital_layering_panel() if("change_genital_clothing_respect", "change_genital_underwear_respect", "change_genital_override") // they all do the same darn thing var/obj/item/organ/genital/clotheme = locate(href_list["which"]) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 8990612ed4c..94720d93253 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -48,8 +48,8 @@ GLOBAL_VAR_INIT(crotch_call_cooldown, 0) RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood) GLOB.human_list += src - var/datum/atom_hud/data/human/genital/pornHud = GLOB.huds[GENITAL_PORNHUD] - pornHud.add_to_hud(src) + // var/datum/atom_hud/data/human/genital/pornHud = GLOB.huds[GENITAL_PORNHUD] + // pornHud.add_to_hud(src) update_body(TRUE) /mob/living/carbon/human/ComponentInitialize() @@ -577,37 +577,24 @@ GLOBAL_VAR_INIT(crotch_call_cooldown, 0) update_body(TRUE) show_underwear_panel() if("update_every_fucking_crotch") - if(COOLDOWN_FINISHED(GLOB, crotch_call_cooldown)) - for(var/mob/living/carbon/human/dic in GLOB.human_list) - dic.update_genitals(TRUE) - COOLDOWN_START(GLOB, crotch_call_cooldown, CROTCH_COOLDOWN) + // if(COOLDOWN_FINISHED(GLOB, crotch_call_cooldown)) + // for(var/mob/living/carbon/human/dic in GLOB.human_list) + // dic.update_genitals(TRUE) + // COOLDOWN_START(GLOB, crotch_call_cooldown, CROTCH_COOLDOWN) show_genital_hide_panel() if("open_genital_hide") show_genital_hide_panel() if("change_genital_whitelist") if(!client?.prefs) return - var/new_genital_whitelist = stripped_multiline_input_or_reflect( - usr, - "Which people are you okay with seeing their genitals when exposed? If a humanlike mob has a name containing \ - any of the following, if their genitals are showing, you will be able to see them, regardless of your \ - content settings. Partial names are accepted, case is not important, please no punctuation (except ','). \ - Keep in mind this matches their 'real' name, so 'unknown' likely won't do much. Separate your entries with a comma!", - "Genital Whitelist", - client?.prefs?.features["genital_whitelist"]) - if(new_genital_whitelist == "") - var/whoathere = alert(usr, "This will clear your genital whitelist, you sure?", "Just checkin'", "Yes", "No") - if(whoathere == "Yes") - client?.prefs?.features["genital_whitelist"] = new_genital_whitelist - client?.loadCockWhitelist() - else if(!isnull(new_genital_whitelist)) - client?.prefs?.features["genital_whitelist"] = new_genital_whitelist - client?.loadCockWhitelist() + client.prefs.update_genital_whitelist() + SSpornhud.request_every_genital(src) update_body(TRUE) show_genital_hide_panel() if("toggle_hide_genitals") if(client?.prefs) TOGGLE_BITFIELD(client.prefs.features["genital_hide"], text2num(href_list["genital_flag"])) + SSpornhud.request_every_genital(src) show_genital_hide_panel() update_body(TRUE) if("shirt") @@ -781,7 +768,7 @@ GLOBAL_VAR_INIT(crotch_call_cooldown, 0) ?src=[REF(src)]; action=toggle_hide_genitals; genital_flag=[HIDE_BELLY]'> - [client?.checkGonadDistaste(HIDE_BELLY) ? "No" : "Yes"] + [CHECK_BITFIELD(client.prefs.features["genital_hide"], HIDE_BELLY) ? "No" : "Yes"] "} dat += "
See Butts:
" // everyone can has_cheezburger dat += {" - [client?.checkGonadDistaste(HIDE_BUTT) ? "No" : "Yes"] + [CHECK_BITFIELD(client.prefs.features["genital_hide"], HIDE_BUTT) ? "No" : "Yes"] "} dat += "
See Breasts:
" // everyone can has_cheezburger dat += {" - [client?.checkGonadDistaste(HIDE_BOOBS) ? "No" : "Yes"] + [CHECK_BITFIELD(client.prefs.features["genital_hide"], HIDE_BOOBS) ? "No" : "Yes"] "} dat += "
See Vaginas:
" // everyone can has_cheezburger dat += {" - [client?.checkGonadDistaste(HIDE_VAG) ? "No" : "Yes"] + [CHECK_BITFIELD(client.prefs.features["genital_hide"], HIDE_VAG) ? "No" : "Yes"] "} dat += "
See Penises:
" // everyone can has_cheezburger dat += {" - [client?.checkGonadDistaste(HIDE_PENIS) ? "No" : "Yes"] + [CHECK_BITFIELD(client.prefs.features["genital_hide"], HIDE_PENIS) ? "No" : "Yes"] "} dat += "
See Balls:
" // GET UR FUCKIN BURGER dat += {" - [client?.checkGonadDistaste(HIDE_BALLS) ? "No" : "Yes"] + [CHECK_BITFIELD(client.prefs.features["genital_hide"], HIDE_BALLS) ? "No" : "Yes"] "} dat += "
Visibility Whitelist:
" // BURGER TIME diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 83809103f48..105e599f30c 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -641,6 +641,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) standing += left_eye standing += right_eye + //SSpornhud.flush_undies(H) // coming soon var/list/standing_undies = list() var/list/standing_overdies = list() //Underwear, Undershirts & Socks @@ -808,7 +809,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m" var/husk = HAS_TRAIT(H, TRAIT_HUSK) - var/image/tail_hack // tailhud's a bazinga, innit + var/tailhacked // tailhud's a bazinga, innit for(var/layer in relevant_layers) var/list/standing = list() @@ -921,7 +922,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] if(layertext == "FRONT" && mutant_string == "tail") // durty hack so asses dont eat tails - tail_hack = accessory_overlay + tailhacked = TRUE + SSpornhud.catalogue_part(H, PHUD_TAIL, accessory_overlay) // oh baby gimme that tail~ standing += accessory_overlay if(S.extra) //apply the extra overlay, if there is one @@ -1018,8 +1020,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.apply_overlay(BODY_ADJ_UPPER_LAYER) H.apply_overlay(BODY_FRONT_LAYER) H.apply_overlay(HORNS_LAYER) - H.tail_hud_update(tail_hack) - + if(!tailhacked) + SSpornhud.catalogue_part(H, PHUD_TAIL, null) // hey gimme back my tail /* * Equip the outfit required for life. Replaces items currently worn. diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 04599b08c9e..f6269b1092d 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -13,8 +13,6 @@ medhud.add_to_hud(src) var/datum/atom_hud/data/client/clienthud = GLOB.huds[DATA_HUD_CLIENT] clienthud.add_to_hud(src) - var/datum/atom_hud/data/human/tail/tailhud = GLOB.huds[TAIL_HUD_DATUM] - tailhud.add_to_hud(src) for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.add_to_hud(src) faction += "[REF(src)]" diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index a2eda5afc14..10caed3767c 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -21,12 +21,7 @@ if(loc) loc.on_log(TRUE) - client.loadCockWhitelist() - - var/datum/atom_hud/H = GLOB.huds[GENITAL_PORNHUD] - H.add_hud_to(src) - var/datum/atom_hud/tail_hud = GLOB.huds[TAIL_HUD_DATUM] - tail_hud.add_hud_to(src) + SSpornhud.request_every_genital(src) //readd this mob's HUDs (antag, med, etc) reload_huds() diff --git a/fortune13.dme b/fortune13.dme index 307b7354137..886c9cb5685 100644 --- a/fortune13.dme +++ b/fortune13.dme @@ -374,6 +374,7 @@ #include "code\controllers\subsystem\pathfinder.dm" #include "code\controllers\subsystem\persistence.dm" #include "code\controllers\subsystem\plants.dm" +#include "code\controllers\subsystem\pornhud.dm" #include "code\controllers\subsystem\prefbreak.dm" #include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\progress_bars.dm" @@ -799,12 +800,10 @@ #include "code\game\atoms_movement.dm" #include "code\game\communications.dm" #include "code\game\data_huds.dm" -#include "code\game\genital_hud.dm" #include "code\game\movable_luminosity.dm" #include "code\game\say.dm" #include "code\game\shuttle_engines.dm" #include "code\game\sound.dm" -#include "code\game\tail_hud.dm" #include "code\game\vault_door.dm" #include "code\game\world.dm" #include "code\game\area\ai_monitored.dm"