mirror of
https://github.com/CHOMPstation/CHOMPstation.git
synced 2026-08-25 04:56:29 +01:00
Adds the Body Designer for resleeving
* Adds Body Designer computer, which allows you to customize body designs similarly to character setup, but in game. * Designs are savable to disks which can be loaded into the the resleeving controller console to print and resleeve into. * Fixes line breaks on OOC notes in the resleeving computer. * Added circuits so the body designer is constructable, and designs so the circuit is researchable. * Added a proc for reverse lookup of size_multiplier -> scale name (0.25 -> Micro etc)
This commit is contained in:
@@ -24,7 +24,9 @@
|
||||
/datum/category_item/player_setup_item/vore/resleeve/copy_to_mob(var/mob/living/carbon/human/character)
|
||||
if(character && !istype(character,/mob/living/carbon/human/dummy))
|
||||
spawn(50)
|
||||
new/datum/transhuman/body_record/(character, pref.resleeve_scan, pref.resleeve_lock) //Clearly related to size.
|
||||
if(pref.resleeve_scan)
|
||||
var/datum/transhuman/body_record/BR = new() //Clearly related to size.
|
||||
BR.init_from_mob(character, pref.resleeve_scan, pref.resleeve_lock)
|
||||
if(pref.resleeve_lock)
|
||||
character.resleeve_lock = character.ckey
|
||||
|
||||
|
||||
@@ -107,6 +107,13 @@
|
||||
build_path = /obj/item/weapon/circuitboard/resleeving_control
|
||||
sort_string = "HAADE"
|
||||
|
||||
/datum/design/circuit/body_designer
|
||||
name = "Body design console"
|
||||
id = "body_designer"
|
||||
req_tech = list(TECH_DATA = 5)
|
||||
build_path = /obj/item/weapon/circuitboard/body_designer
|
||||
sort_string = "HAADF"
|
||||
|
||||
/datum/design/circuit/partslathe
|
||||
name = "Parts lathe"
|
||||
id = "partslathe"
|
||||
|
||||
@@ -32,10 +32,16 @@
|
||||
req_components = list(
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 2,
|
||||
/obj/item/weapon/stock_parts/manipulator = 2,
|
||||
/obj/item/weapon/stock_parts/manipulator = 2,
|
||||
/obj/item/weapon/stock_parts/console_screen = 1)
|
||||
|
||||
/obj/item/weapon/circuitboard/resleeving_control
|
||||
name = T_BOARD("resleeving control console")
|
||||
build_path = /obj/machinery/computer/transhuman/resleeving
|
||||
origin_tech = list(TECH_DATA = 5)
|
||||
|
||||
|
||||
/obj/item/weapon/circuitboard/body_designer
|
||||
name = T_BOARD("body design console")
|
||||
build_path = /obj/machinery/computer/transhuman/designer
|
||||
origin_tech = list(TECH_DATA = 5)
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
if(istype(W, /obj/item/device/multitool))
|
||||
var/obj/item/device/multitool/M = W
|
||||
var/obj/machinery/clonepod/transhuman/P = M.connecting
|
||||
if(P && !(P in pods))
|
||||
if(istype(P) && !(P in pods))
|
||||
pods += P
|
||||
P.connected = src
|
||||
P.name = "[initial(P.name)] #[pods.len]"
|
||||
@@ -78,6 +78,17 @@
|
||||
disk = W
|
||||
disk.forceMove(src)
|
||||
user << "<span class='notice'>You insert \the [W] into \the [src].</span>"
|
||||
if(istype(W, /obj/item/weapon/disk/body_record))
|
||||
var/obj/item/weapon/disk/body_record/brDisk = W
|
||||
if(!brDisk.stored)
|
||||
to_chat(user, "<span class='warning'>\The [W] does not contain a stored body record.</span>")
|
||||
return
|
||||
user.unEquip(W)
|
||||
W.forceMove(get_turf(src)) // Drop on top of us
|
||||
active_br = new /datum/transhuman/body_record(brDisk.stored) // Loads a COPY!
|
||||
menu = 4
|
||||
to_chat(user, "<span class='notice'>\The [src] loads the body record from \the [W] before ejecting it.</span>")
|
||||
attack_hand(user)
|
||||
else
|
||||
..()
|
||||
return
|
||||
@@ -192,7 +203,7 @@
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "sleever.tmpl", src.name, 400, 450)
|
||||
ui = new(user, src, ui_key, "sleever.tmpl", "Resleeving Control Console", 400, 450)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(5)
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
// Little define makes it cleaner to read the tripple color values out of mobs.
|
||||
#define MOB_HEX_COLOR(M, V) "#[num2hex(M.r_##V, 2)][num2hex(M.g_##V, 2)][num2hex(M.b_##V, 2)]"
|
||||
|
||||
/obj/machinery/computer/transhuman/designer
|
||||
name = "body design console"
|
||||
icon = 'icons/obj/computer_vr.dmi'
|
||||
icon_keyboard = "med_key"
|
||||
icon_screen = "dna"
|
||||
light_color = "#315ab4"
|
||||
circuit = /obj/item/weapon/circuitboard/body_designer
|
||||
req_access = list(access_medical) // Used for loading people's designs
|
||||
var/temp = ""
|
||||
var/menu = 1 //Which menu screen to display
|
||||
var/datum/transhuman/body_record/active_br = null
|
||||
var/icon/preview_icon = null
|
||||
// Mannequins are somewhat expensive to create, so cache it
|
||||
var/mob/living/carbon/human/dummy/mannequin/mannequin = null
|
||||
var/datum/transhuman/infocore/TC //Easy debugging access
|
||||
var/obj/item/weapon/disk/body_record/disk = null
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/initialize()
|
||||
..()
|
||||
TC = transcore
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/Destroy()
|
||||
active_br = null
|
||||
preview_icon = null
|
||||
mannequin = null
|
||||
disk = null
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/dismantle()
|
||||
if(disk)
|
||||
disk.forceMove(get_turf(src))
|
||||
disk = null
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/disk/body_record))
|
||||
user.unEquip(W)
|
||||
disk = W
|
||||
disk.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You insert \the [W] into \the [src].</span>")
|
||||
updateUsrDialog()
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/attack_ai(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/attack_hand(mob/user as mob)
|
||||
add_fingerprint(user)
|
||||
if(inoperable())
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// log_debug("designer.ui_interact([user], force_open = [force_open])")
|
||||
user.set_machine(src)
|
||||
|
||||
var/data[0]
|
||||
|
||||
if(menu == "2")
|
||||
var/bodyrecords_list_ui[0]
|
||||
for(var/N in TC.body_scans)
|
||||
var/datum/transhuman/body_record/BR = TC.body_scans[N]
|
||||
bodyrecords_list_ui[++bodyrecords_list_ui.len] = list("name" = N, "recref" = "\ref[BR]")
|
||||
if(bodyrecords_list_ui.len)
|
||||
data["bodyrecords"] = bodyrecords_list_ui
|
||||
|
||||
if(menu == "3")
|
||||
var/stock_bodyrecords_list_ui[0]
|
||||
for (var/N in all_species)
|
||||
var/datum/species/S = all_species[N]
|
||||
if((S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) != SPECIES_CAN_JOIN) continue
|
||||
stock_bodyrecords_list_ui += N
|
||||
if(stock_bodyrecords_list_ui.len)
|
||||
data["stock_bodyrecords"] = stock_bodyrecords_list_ui
|
||||
|
||||
if(active_br)
|
||||
data["activeBodyRecord"] = list(
|
||||
"real_name" = active_br.mydna.name,
|
||||
"speciesname" = active_br.speciesname ? active_br.speciesname : active_br.mydna.dna.species,
|
||||
"gender" = active_br.bodygender,
|
||||
"synthetic" = active_br.synthetic ? "Yes" : "No",
|
||||
"locked" = active_br.locked ? "Low" : "High",
|
||||
"scale" = player_size_name(active_br.sizemult),
|
||||
"booc" = active_br.body_oocnotes,
|
||||
"styles" = list()
|
||||
)
|
||||
if(!preview_icon)
|
||||
update_preview_icon()
|
||||
force_open = 1 // Force a refresh to send the new image
|
||||
data["previewIconUrl"] = "body_preview_icon.png"
|
||||
user << browse_rsc(preview_icon, "body_preview_icon.png")
|
||||
|
||||
var/list/styles = data["activeBodyRecord"]["styles"]
|
||||
var/list/temp
|
||||
|
||||
temp = list("styleHref" = "ear_style", "style" = "Normal")
|
||||
if(mannequin.ear_style)
|
||||
temp["style"] = mannequin.ear_style.name
|
||||
styles["Ears"] = temp
|
||||
|
||||
temp = list("styleHref" = "tail_style", "style" = "Normal")
|
||||
if(mannequin.tail_style)
|
||||
temp["style"] = mannequin.tail_style.name
|
||||
if(mannequin.tail_style.do_colouration)
|
||||
temp["color"] = MOB_HEX_COLOR(mannequin, tail)
|
||||
temp["colorHref"] = "tail_color"
|
||||
styles["Tail"] = temp
|
||||
|
||||
temp = list("styleHref" = "hair_style", "style" = mannequin.h_style)
|
||||
if(mannequin.species && (mannequin.species.appearance_flags & HAS_HAIR_COLOR))
|
||||
temp["color"] = MOB_HEX_COLOR(mannequin, hair)
|
||||
temp["colorHref"] = "hair_color"
|
||||
styles["Hair"] = temp
|
||||
|
||||
temp = list("styleHref" = "facial_style", "style" = mannequin.f_style)
|
||||
if(mannequin.species && (mannequin.species.appearance_flags & HAS_HAIR_COLOR))
|
||||
temp["color"] = MOB_HEX_COLOR(mannequin, facial)
|
||||
temp["colorHref"] = "facial_color"
|
||||
styles["Facial"] = temp
|
||||
|
||||
if(mannequin.species && (mannequin.species.appearance_flags & HAS_EYE_COLOR))
|
||||
styles["Eyes"] = list("colorHref" = "eye_color", "color" = MOB_HEX_COLOR(mannequin, eyes))
|
||||
|
||||
if(mannequin.species && (mannequin.species.appearance_flags & HAS_SKIN_COLOR))
|
||||
styles["Body Color"] = list("colorHref" = "skin_color", "color" = MOB_HEX_COLOR(mannequin, skin))
|
||||
|
||||
var/datum/preferences/designer/P = new()
|
||||
apply_markings_to_prefs(mannequin, P)
|
||||
data["activeBodyRecord"]["markings"] = P.body_markings
|
||||
|
||||
data["menu"] = menu
|
||||
data["temp"] = temp
|
||||
data["disk"] = disk ? 1 : 0
|
||||
data["diskStored"] = disk && disk.stored ? 1 : 0
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "body_designer.tmpl", "Body Design Console", 400, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
else if(href_list["debug_load_my_body"])
|
||||
active_br = new /datum/transhuman/body_record(usr, FALSE, FALSE)
|
||||
preview_icon = null
|
||||
|
||||
else if (href_list["view_brec"])
|
||||
var/datum/transhuman/body_record/BR = locate(href_list["view_brec"])
|
||||
if(BR && istype(BR.mydna))
|
||||
if(allowed(usr) || BR.ckey == usr.ckey)
|
||||
active_br = new /datum/transhuman/body_record(BR) // Load a COPY!
|
||||
preview_icon = null
|
||||
menu = 4
|
||||
else
|
||||
active_br = null
|
||||
temp = "Access denied: Body records are confidential"
|
||||
else
|
||||
active_br = null
|
||||
temp = "ERROR: Record missing."
|
||||
|
||||
else if(href_list["view_stock_brec"])
|
||||
var/datum/species/S = all_species[href_list["view_stock_brec"]]
|
||||
if(S && (S.spawn_flags & (SPECIES_IS_WHITELISTED|SPECIES_CAN_JOIN)) == SPECIES_CAN_JOIN)
|
||||
// Generate body record from species!
|
||||
mannequin = new(null, S.name)
|
||||
mannequin.real_name = "Stock [S.name] Body"
|
||||
mannequin.name = mannequin.real_name
|
||||
mannequin.dna.real_name = mannequin.real_name
|
||||
active_br = new(mannequin, FALSE, FALSE)
|
||||
active_br.speciesname = "Custom Sleeve"
|
||||
preview_icon = null
|
||||
menu = 4
|
||||
else
|
||||
active_br = null
|
||||
temp = "ERROR: Stock Record missing."
|
||||
|
||||
else if (href_list["boocnotes"])
|
||||
menu = 6
|
||||
|
||||
else if (href_list["loadfromdisk"])
|
||||
if(disk && disk.stored)
|
||||
active_br = new /datum/transhuman/body_record(disk.stored) // Loads a COPY!
|
||||
preview_icon = null
|
||||
|
||||
else if (href_list["savetodisk"])
|
||||
if(disk && active_br)
|
||||
disk.stored = new /datum/transhuman/body_record(active_br) // Saves a COPY!
|
||||
disk.name = "[initial(disk.name)] ([active_br.mydna.name])"
|
||||
disk.forceMove(get_turf(src))
|
||||
disk = null
|
||||
|
||||
else if (href_list["ejectdisk"])
|
||||
disk.forceMove(get_turf(src))
|
||||
disk = null
|
||||
|
||||
else if (href_list["menu"])
|
||||
menu = href_list["menu"]
|
||||
temp = ""
|
||||
else
|
||||
OnTopic(href, href_list, usr)
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1 // Return 1 to refresh UI
|
||||
|
||||
//
|
||||
// Code below is for generating preview icons based on a body_record
|
||||
//
|
||||
|
||||
// Based on /datum/preferences/proc/update_preview_icon()
|
||||
/obj/machinery/computer/transhuman/designer/proc/update_preview_icon()
|
||||
if(!mannequin)
|
||||
mannequin = new ()
|
||||
|
||||
mannequin.delete_inventory(TRUE)
|
||||
update_preview_mob(mannequin)
|
||||
|
||||
preview_icon = icon('icons/effects/effects.dmi', "nothing")
|
||||
preview_icon.Scale(48+32, 16+32)
|
||||
|
||||
mannequin.dir = NORTH
|
||||
var/icon/stamp = getFlatIcon(mannequin)
|
||||
preview_icon.Blend(stamp, ICON_OVERLAY, 25, 17)
|
||||
|
||||
mannequin.dir = WEST
|
||||
stamp = getFlatIcon(mannequin)
|
||||
preview_icon.Blend(stamp, ICON_OVERLAY, 1, 9)
|
||||
|
||||
mannequin.dir = SOUTH
|
||||
stamp = getFlatIcon(mannequin)
|
||||
preview_icon.Blend(stamp, ICON_OVERLAY, 49, 1)
|
||||
|
||||
preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser.
|
||||
return preview_icon
|
||||
|
||||
/obj/machinery/computer/transhuman/designer/proc/update_preview_mob(var/mob/living/carbon/human/H)
|
||||
ASSERT(!deleted(H))
|
||||
ASSERT(!deleted(active_br))
|
||||
//log_debug("designer.update_preview_mob([H]) active_br = \ref[active_br]")
|
||||
//Get the DNA and generate a new mob
|
||||
var/datum/dna2/record/R = active_br.mydna
|
||||
H.set_species(R.dna.species) // This needs to happen before anything else becuase it sets some variables.
|
||||
|
||||
// Update the external organs
|
||||
for(var/part in active_br.limb_data)
|
||||
var/status = active_br.limb_data[part]
|
||||
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
|
||||
|
||||
var/obj/item/organ/external/O = H.organs_by_name[part]
|
||||
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
|
||||
|
||||
if(status == 1) //Normal limbs
|
||||
continue
|
||||
else if(status == 0) //Missing limbs
|
||||
O.remove_rejuv()
|
||||
else if(status) //Anything else is a manufacturer
|
||||
if(active_br.synthetic)
|
||||
O.robotize(status)
|
||||
else
|
||||
O.remove_rejuv()
|
||||
|
||||
// Then the internal organs. I think only O_EYES acutally counts, but lets do all just in case
|
||||
for(var/part in active_br.organ_data)
|
||||
var/status = active_br.organ_data[part]
|
||||
if(status == null) continue //Species doesn't have organ? Child of missing part?
|
||||
|
||||
var/obj/item/organ/I = H.internal_organs_by_name[part]
|
||||
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
|
||||
|
||||
if(status == 0) //Normal organ
|
||||
continue
|
||||
else if(status == 1) //Assisted organ
|
||||
I.mechassist()
|
||||
else if(status == 2) //Mechanical organ
|
||||
I.robotize()
|
||||
else if(status == 3) //Digital organ
|
||||
I.digitize()
|
||||
|
||||
// Apply DNA
|
||||
H.dna = R.dna.Clone()
|
||||
H.UpdateAppearance() // Update all appearance stuff from the DNA record
|
||||
H.sync_organ_dna() // Do this because sprites depend on DNA-gender of organs (chest etc)
|
||||
H.size_multiplier = active_br.sizemult
|
||||
|
||||
// And as for clothing...
|
||||
// We don't actually dress them! This is a medical machine, handle the nakedness DOCTOR!
|
||||
|
||||
H.regenerate_icons()
|
||||
return 0 // Success!
|
||||
|
||||
// HORROR SHOW BELOW
|
||||
// In order to avoid duplicating the many lines of code in player_setup that handle customizing
|
||||
// body setup, we acutally are invoking those methods in order to let people customize the body here.
|
||||
// Problem is, those procs save their data to /datum/preferences, not a body_record.
|
||||
// Luckily the procs to convert from body_record to /datum/preferences and back already exist.
|
||||
// Its ugly, but I think its still better than duplicating and maintaining all that code.
|
||||
/obj/machinery/computer/transhuman/designer/proc/OnTopic(var/href,var/list/href_list, var/mob/user)
|
||||
if(!mannequin || !preview_icon || !active_br)
|
||||
return
|
||||
|
||||
if(href_list["size_multiplier"])
|
||||
var/new_size = input(user, "Choose your character's size:", "Character Preference", player_size_name(active_br.sizemult)) as null|anything in player_sizes_list
|
||||
if(new_size && (new_size in player_sizes_list))
|
||||
active_br.sizemult = player_sizes_list[new_size]
|
||||
preview_icon = null
|
||||
return 1
|
||||
|
||||
// The black magic horror show begins
|
||||
var/datum/preferences/designer/P = new()
|
||||
|
||||
// We did DNA to mob, now mob to prefs!
|
||||
P.species = mannequin.species.name
|
||||
apply_coloration_to_prefs(mannequin, P)
|
||||
apply_organs_to_prefs(mannequin, P)
|
||||
apply_markings_to_prefs(mannequin, P)
|
||||
apply_ears_to_prefs(mannequin, P)
|
||||
|
||||
// Now we start using the player_setup objects to do stuff!
|
||||
var/datum/category_collection/CC = P.player_setup
|
||||
var/datum/category_group/CG = CC.categories_by_name["General"]
|
||||
var/datum/category_item/player_setup_item/general/body/B = CG.items_by_name["Body"]
|
||||
ASSERT(istype(B))
|
||||
var/datum/category_item/player_setup_item/general/basic/G = CG.items_by_name["Basic"]
|
||||
ASSERT(istype(G))
|
||||
CG = CC.categories_by_name["VORE"]
|
||||
var/datum/category_item/player_setup_item/vore/ears/E = CG.items_by_name["Appearance"]
|
||||
ASSERT(istype(E))
|
||||
|
||||
if(href_list["bio_gender"])
|
||||
var/new_gender = input(user, "Choose your character's biological gender:", "Character Preference", active_br.bodygender) as null|anything in G.get_genders()
|
||||
if(new_gender)
|
||||
active_br.bodygender = new_gender
|
||||
active_br.mydna.dna.SetUIState(DNA_UI_GENDER, new_gender!=MALE, 1)
|
||||
preview_icon = null
|
||||
return 1
|
||||
|
||||
var/action = 0
|
||||
action = B.OnTopic(href, href_list, user)
|
||||
if(action & TOPIC_UPDATE_PREVIEW && mannequin && active_br)
|
||||
B.copy_to_mob(mannequin)
|
||||
active_br.mydna.dna.ResetUIFrom(mannequin)
|
||||
preview_icon = null
|
||||
return 1
|
||||
action = E.OnTopic(href, href_list, user)
|
||||
if(action & TOPIC_UPDATE_PREVIEW && mannequin && active_br)
|
||||
E.copy_to_mob(mannequin)
|
||||
active_br.mydna.dna.ResetUIFrom(mannequin)
|
||||
preview_icon = null
|
||||
return 1
|
||||
|
||||
// Fake subtype of preferences we can use to steal code from player_setup
|
||||
/datum/preferences/designer/New()
|
||||
player_setup = new(src)
|
||||
// Do NOT call ..(), it expects real stuff
|
||||
|
||||
|
||||
// Disk for manually moving body records between the designer and sleever console etc.
|
||||
/obj/item/weapon/disk/body_record
|
||||
name = "Body Design Disk"
|
||||
desc = "It has a small label: \n\
|
||||
\"Portable Body Record Storage Disk. \n\
|
||||
Insert into resleeving control console\""
|
||||
icon = 'icons/obj/cloning.dmi'
|
||||
icon_state = "datadisk2"
|
||||
item_state = "card-id"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/datum/transhuman/body_record/stored = null
|
||||
|
||||
/*
|
||||
* Diskette Box
|
||||
*/
|
||||
|
||||
/obj/item/weapon/storage/box/body_record_disk
|
||||
name = "body record disk box"
|
||||
desc = "A box of body record disks, apparently."
|
||||
icon_state = "disk_kit"
|
||||
|
||||
/obj/item/weapon/storage/box/disks/New()
|
||||
..()
|
||||
for(var/i = 0 to 7)
|
||||
new /obj/item/weapon/disk/body_record(src)
|
||||
|
||||
#undef MOB_HEX_COLOR
|
||||
@@ -155,8 +155,24 @@ var/datum/transhuman/infocore/transcore = new/datum/transhuman/infocore
|
||||
var/toocomplex
|
||||
var/sizemult
|
||||
|
||||
/datum/transhuman/body_record/New(var/mob/living/carbon/human/M,var/add_to_db = 1,var/ckeylock = 0)
|
||||
ASSERT(M)
|
||||
/datum/transhuman/body_record/New(var/copyfrom, var/add_to_db = 0, var/ckeylock = 0)
|
||||
..()
|
||||
if(istype(copyfrom, /datum/transhuman/body_record))
|
||||
init_from_br(copyfrom)
|
||||
else if(ishuman(copyfrom))
|
||||
init_from_mob(copyfrom, add_to_db, ckeylock)
|
||||
|
||||
/datum/transhuman/body_record/Destroy()
|
||||
mydna = null
|
||||
client_ref = null
|
||||
mind_ref = null
|
||||
limb_data.Cut()
|
||||
organ_data.Cut()
|
||||
..()
|
||||
|
||||
/datum/transhuman/body_record/proc/init_from_mob(var/mob/living/carbon/human/M, var/add_to_db = 0, var/ckeylock = 0)
|
||||
ASSERT(!deleted(M))
|
||||
ASSERT(istype(M))
|
||||
|
||||
//Person OOCly doesn't want people impersonating them
|
||||
locked = ckeylock
|
||||
@@ -232,3 +248,33 @@ var/datum/transhuman/infocore/transcore = new/datum/transhuman/infocore
|
||||
|
||||
if(add_to_db)
|
||||
transcore.add_body(src)
|
||||
|
||||
|
||||
/**
|
||||
* Make a deep copy of this record so it can be saved on a disk without mofidications
|
||||
* to the original affecting the copy.
|
||||
* Just to be clear, this has nothing to do do with acutal biological cloning, body printing, resleeving,
|
||||
* or anything like that! This is the computer science concept of "cloning" a data structure!
|
||||
*/
|
||||
/datum/transhuman/body_record/proc/init_from_br(var/datum/transhuman/body_record/orig)
|
||||
ASSERT(!deleted(orig))
|
||||
ASSERT(istype(orig))
|
||||
src.mydna = new ()
|
||||
src.mydna.dna = orig.mydna.dna.Clone()
|
||||
src.mydna.ckey = orig.mydna.ckey
|
||||
src.mydna.id = orig.mydna.id
|
||||
src.mydna.name = orig.mydna.name
|
||||
src.mydna.types = orig.mydna.types
|
||||
src.mydna.flavor = orig.mydna.flavor.Copy()
|
||||
src.ckey = orig.ckey
|
||||
src.locked = orig.locked
|
||||
src.client_ref = orig.client_ref
|
||||
src.mind_ref = orig.mind_ref
|
||||
src.synthetic = orig.synthetic
|
||||
src.speciesname = orig.speciesname
|
||||
src.bodygender = orig.bodygender
|
||||
src.body_oocnotes = orig.body_oocnotes
|
||||
src.limb_data = orig.limb_data.Copy()
|
||||
src.organ_data = orig.organ_data.Copy()
|
||||
src.toocomplex = orig.toocomplex
|
||||
src.sizemult = orig.sizemult
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
var/status = current_project.organ_data[part]
|
||||
if(status == null) continue //Species doesn't have organ? Child of missing part?
|
||||
|
||||
var/obj/item/organ/I = H.internal_organs_by_name[name]
|
||||
var/obj/item/organ/I = H.internal_organs_by_name[part]
|
||||
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
|
||||
|
||||
if(status == 0) //Normal organ
|
||||
@@ -496,6 +496,12 @@
|
||||
occupant.ooc_notes = MR.mind_oocnotes
|
||||
occupant.apply_vore_prefs() //Cheap hack for now to give them SOME bellies.
|
||||
|
||||
// If it was a custom sleeve (not owned by anyone), update namification sequences
|
||||
if(!occupant.original_player)
|
||||
occupant.real_name = occupant.mind.name
|
||||
occupant.name = occupant.real_name
|
||||
occupant.dna.real_name = occupant.real_name
|
||||
|
||||
//Give them a backup implant
|
||||
var/obj/item/weapon/implant/backup/new_imp = new()
|
||||
if(new_imp.implanted(occupant))
|
||||
@@ -516,7 +522,7 @@
|
||||
occupant.confused = max(occupant.confused, confuse_amount)
|
||||
occupant.eye_blurry = max(occupant.eye_blurry, blur_amount)
|
||||
|
||||
if(occupant.mind && occupant.real_name != occupant.mind.name)
|
||||
if(occupant.mind && occupant.original_player && ckey(occupant.mind.key) != occupant.original_player)
|
||||
log_and_message_admins("is now a cross-sleeved character. Body originally belonged to [occupant.real_name]. Mind is now [occupant.mind.name].",occupant)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -84,6 +84,39 @@
|
||||
prefs.save_character()
|
||||
return
|
||||
|
||||
// Saves mob's current coloration state to prefs
|
||||
// This basically needs to be the reverse of /datum/category_item/player_setup_item/general/body/copy_to_mob() ~Leshana
|
||||
/proc/apply_coloration_to_prefs(var/mob/living/carbon/human/character, var/datum/preferences/prefs)
|
||||
if(!istype(character)) return
|
||||
prefs.r_eyes = character.r_eyes
|
||||
prefs.g_eyes = character.g_eyes
|
||||
prefs.b_eyes = character.b_eyes
|
||||
prefs.h_style = character.h_style
|
||||
prefs.r_hair = character.r_hair
|
||||
prefs.g_hair = character.g_hair
|
||||
prefs.b_hair = character.b_hair
|
||||
prefs.f_style = character.f_style
|
||||
prefs.r_facial = character.r_facial
|
||||
prefs.g_facial = character.g_facial
|
||||
prefs.b_facial = character.b_facial
|
||||
prefs.r_skin = character.r_skin
|
||||
prefs.g_skin = character.g_skin
|
||||
prefs.b_skin = character.b_skin
|
||||
prefs.s_tone = character.s_tone
|
||||
prefs.h_style = character.h_style
|
||||
prefs.f_style = character.f_style
|
||||
prefs.b_type = character.b_type
|
||||
|
||||
// Saves mob's current custom species, ears, and tail state to prefs
|
||||
// This basically needs to be the reverse of /datum/category_item/player_setup_item/vore/ears/copy_to_mob() ~Leshana
|
||||
/proc/apply_ears_to_prefs(var/mob/living/carbon/human/character, var/datum/preferences/prefs)
|
||||
if(character.ear_style) prefs.ear_style = character.ear_style.type
|
||||
if(character.tail_style) prefs.tail_style = character.tail_style.type
|
||||
prefs.r_tail = character.r_tail
|
||||
prefs.b_tail = character.b_tail
|
||||
prefs.g_tail = character.g_tail
|
||||
prefs.custom_species = character.custom_species
|
||||
|
||||
// Saves mob's current organ state to prefs.
|
||||
// This basically needs to be the reverse of /datum/category_item/player_setup_item/general/body/copy_to_mob() ~Leshana
|
||||
/proc/apply_organs_to_prefs(var/mob/living/carbon/human/character, var/datum/preferences/prefs)
|
||||
|
||||
@@ -22,6 +22,14 @@ var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
/mob/living/carbon/human
|
||||
holder_type = /obj/item/weapon/holder/micro
|
||||
|
||||
// The reverse lookup of player_sizes_list, number to name.
|
||||
/proc/player_size_name(var/size_multiplier)
|
||||
// (This assumes list is sorted big->small)
|
||||
for(var/N in player_sizes_list)
|
||||
. = N // So we return the smallest if we get to the end
|
||||
if(size_multiplier >= player_sizes_list[N])
|
||||
return N
|
||||
|
||||
/**
|
||||
* Scale up the size of a mob's icon by the size_multiplier.
|
||||
* NOTE: mob/living/carbon/human/update_icons() has a more complicated system and
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,129 @@
|
||||
|
||||
<b>{{:data.temp}}</b>
|
||||
|
||||
{{if data.disk}}
|
||||
{{:helper.link('Save To Disk', 'disk', {'savetodisk' : 1}, data.activeBodyRecord ? null : 'linkOff')}}
|
||||
{{:helper.link('Load From Disk', 'folder-open', {'loadfromdisk' : 1}, data.diskStored ? null : 'linkOff')}}
|
||||
{{:helper.link('Eject Disk', 'eject', {'ejectdisk' : 1})}}
|
||||
{{/if}}
|
||||
|
||||
<!-- {{:helper.link('DEBUG: Load My Body', 'eject', {'debug_load_my_body' : 1})}} -->
|
||||
|
||||
<!-- Menu1: Main Menu -->
|
||||
{{if data.menu == 1}}
|
||||
<!-- Database -->
|
||||
<h3>Database Functions</h3>
|
||||
<div class='item'>
|
||||
{{:helper.link('View Individual Body Records', 'list', {'menu' : 2})}}
|
||||
</div>
|
||||
<div class='item'>
|
||||
{{:helper.link('View Stock Body Records', 'list', {'menu' : 3})}}
|
||||
</div>
|
||||
|
||||
<!-- Menu2: Body record list -->
|
||||
{{else data.menu == 2}}
|
||||
<h3>Current body records</h3>
|
||||
{{:helper.link('Back', 'arrowreturn-1-w', {'menu' : 1})}}
|
||||
<div class='item'>
|
||||
{{for data.bodyrecords}}
|
||||
{{:helper.link(value.name, 'document', {'view_brec' : value.recref})}}
|
||||
{{/for}}
|
||||
</div>
|
||||
|
||||
<!-- Menu3: Stock body record list -->
|
||||
{{else data.menu == 3}}
|
||||
<h3>Stock body records</h3>
|
||||
{{:helper.link('Back', 'arrowreturn-1-w', {'menu' : 1})}}
|
||||
<div class='item'>
|
||||
{{for data.stock_bodyrecords}}
|
||||
{{:helper.link(value, 'document', {'view_stock_brec' : value})}}
|
||||
{{/for}}
|
||||
</div>
|
||||
|
||||
<!-- Menu4: Specific body record -->
|
||||
{{else data.menu == 4}}
|
||||
<h3>Selected Body Record</h3>
|
||||
<div class='item'>{{:helper.link('Back', 'arrowreturn-1-w', {'menu' : 1})}}</div>
|
||||
|
||||
{{if data.activeBodyRecord}}
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Name:</div>
|
||||
<div class='itemContent'>{{:data.activeBodyRecord.real_name}}</div>
|
||||
</div>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Species:</div>
|
||||
<div class='itemContent'>{{:data.activeBodyRecord.speciesname}}</div>
|
||||
</div>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Bio. Sex:</div>
|
||||
<div class='itemContent'>{{:helper.link(data.activeBodyRecord.gender, null, {'bio_gender' : 1})}}</div>
|
||||
</div>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Synthetic:</div>
|
||||
<div class='itemContent'>{{:data.activeBodyRecord.synthetic}}</div>
|
||||
</div>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Mind compat.:</div>
|
||||
<div class='itemContentNarrow'>{{:data.activeBodyRecord.locked}}</div>
|
||||
<div class='itemContentNarrow'>{{:helper.link('View OOC Notes', null, {'boocnotes' : 1}, data.activeBodyRecord.booc ? null : 'linkOff')}}</div>
|
||||
</div>
|
||||
|
||||
<div class='statusDisplay'>
|
||||
<center>
|
||||
<img src="{{:data.previewIconUrl}}">
|
||||
</center>
|
||||
</div>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Scale:</div>
|
||||
<div class='itemContent'>{{:helper.link(data.activeBodyRecord.scale, null, {'size_multiplier' : 1})}}</div>
|
||||
</div>
|
||||
|
||||
{{props data.activeBodyRecord.styles}}
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>{{:key}}:</div>
|
||||
<div class='itemContent'>
|
||||
{{if value.styleHref}}
|
||||
<!-- Look, about the parameter magic here... just don't ask ok? -->
|
||||
{{:helper.link(value.style, null, (a={},a[value.styleHref]=1,a))}}
|
||||
{{/if}}
|
||||
{{if value.colorHref}}
|
||||
{{:helper.link(value.color, null, (a={},a[value.colorHref]=1,a))}}
|
||||
<div class="linkOff" style="background: {{:value.color}};"> </div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/props}}
|
||||
|
||||
<div class='itemGroup'>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Body Markings</div>
|
||||
<div class='itemContent'>
|
||||
{{:helper.link('Add Marking', 'plus', {'marking_style' : 1})}}
|
||||
</div>
|
||||
</div>
|
||||
{{props data.activeBodyRecord.markings}}
|
||||
<div class='item'>
|
||||
<span style='float: left;'>{{:key}} </span>
|
||||
<div style="background: {{:value}};" unselectable="on" class="linkActive link"
|
||||
data-href="{{:NanoUtility.generateHref({marking_color: key})}}"> </div>
|
||||
{{:helper.link('', 'minus', {'marking_remove' : key})}}
|
||||
</div>
|
||||
{{props}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class='item bad'>ERROR: Record not found.</div>
|
||||
{{/if}}
|
||||
|
||||
<!-- Menu6: Body OOC Notes -->
|
||||
{{else data.menu == 6}}
|
||||
<h3>Body OOC Notes (This is OOC!)</h3>
|
||||
<div class='item'>{{:helper.link('Back', 'arrowreturn-1-w', {'menu' : 4})}}</div>
|
||||
{{if data.activeBodyRecord}}
|
||||
<div class='itemLabel'>Notes:</div>
|
||||
<div class='itemContent multiLine'>{{:data.activeBodyRecord.booc}}</div>
|
||||
{{else}}
|
||||
<div class='item bad'>ERROR: Record not found.</div>
|
||||
{{/if}}
|
||||
|
||||
{{/if}}
|
||||
<pre style="display: none;">{{:JSON.stringify(data, null, 2)}}</pre>
|
||||
@@ -150,7 +150,7 @@
|
||||
<div class='item'>{{:helper.link('Back', 'arrowreturn-1-w', {'menu' : 4})}}</div>
|
||||
{{if data.activeBodyRecord}}
|
||||
<div class='itemLabel'>Notes:</div>
|
||||
<div class='itemContent'>{{:data.activeBodyRecord.booc}}</div>
|
||||
<div class='itemContent multiLine'>{{:data.activeBodyRecord.booc}}</div>
|
||||
{{else}}
|
||||
<div class='item bad'>ERROR: Record not found.</div>
|
||||
{{/if}}
|
||||
@@ -161,7 +161,7 @@
|
||||
<div class='item'>{{:helper.link('Back', 'arrowreturn-1-w', {'menu' : 5})}}</div>
|
||||
{{if data.activeMindRecord}}
|
||||
<div class='itemLabel'>Notes:</div>
|
||||
<div class='itemContent'>{{:data.activeMindRecord.mooc}}</div>
|
||||
<div class='itemContent multiLine'>{{:data.activeMindRecord.mooc}}</div>
|
||||
{{else}}
|
||||
<div class='item bad'>ERROR: Record not found.</div>
|
||||
{{/if}}
|
||||
|
||||
@@ -2157,6 +2157,7 @@
|
||||
#include "code\modules\resleeving\_defines.dm"
|
||||
#include "code\modules\resleeving\circuitboards.dm"
|
||||
#include "code\modules\resleeving\computers.dm"
|
||||
#include "code\modules\resleeving\designer.dm"
|
||||
#include "code\modules\resleeving\documents.dm"
|
||||
#include "code\modules\resleeving\implant.dm"
|
||||
#include "code\modules\resleeving\infocore.dm"
|
||||
|
||||
Reference in New Issue
Block a user