diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index fcc2d0c91b9..72937092c4f 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -51,6 +51,7 @@ var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessor var/global/list/facial_hair_styles_male_list = list() var/global/list/facial_hair_styles_female_list = list() var/global/list/skin_styles_female_list = list() //unused +var/global/list/body_marking_styles_list = list() //stores /datum/sprite_accessory/marking indexed by name //Underwear var/datum/category_collection/underwear/global_underwear = new() @@ -141,6 +142,12 @@ var/global/list/string_slot_flags = list( facial_hair_styles_male_list += H.name facial_hair_styles_female_list += H.name + //Body markings - Initialise all /datum/sprite_accessory/marking into an list indexed by marking name + paths = typesof(/datum/sprite_accessory/marking) - /datum/sprite_accessory/marking + for(var/path in paths) + var/datum/sprite_accessory/marking/M = new path() + body_marking_styles_list[M.name] = M + //Surgery Steps - Initialize all /datum/surgery_step into a list paths = typesof(/datum/surgery_step)-/datum/surgery_step for(var/T in paths) diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index e30de18f4e2..e80dcb72270 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -84,6 +84,7 @@ var/global/list/datum/dna/gene/dna_genes[0] // New stuff var/species = "Human" + var/list/body_markings = list() // Make a copy of this strand. // USE THIS WHEN COPYING STUFF OR YOU'LL GET CORRUPTION! @@ -93,6 +94,7 @@ var/global/list/datum/dna/gene/dna_genes[0] new_dna.b_type=b_type new_dna.real_name=real_name new_dna.species=species + new_dna.body_markings=body_markings.Copy() for(var/b=1;b<=DNA_SE_LENGTH;b++) new_dna.SE[b]=SE[b] if(b<=DNA_UI_LENGTH) @@ -152,6 +154,11 @@ var/global/list/datum/dna/gene/dna_genes[0] SetUIValueRange(DNA_UI_HAIR_STYLE, hair, hair_styles_list.len, 1) SetUIValueRange(DNA_UI_BEARD_STYLE, beard, facial_hair_styles_list.len,1) + body_markings.Cut() + for(var/obj/item/organ/external/E in character.organs) + if(E.markings.len) + body_markings[E.organ_tag] = E.markings.Copy() + UpdateUI() // Set a DNA UI block's raw value. diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 98acc1d335d..2287d3477c9 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -156,6 +156,13 @@ else H.gender = MALE + //Body markings + for(var/tag in dna.body_markings) + var/obj/item/organ/external/E = H.organs_by_name[tag] + if(E) + var/list/marklist = dna.body_markings[tag] + E.markings = marklist.Copy() + //Hair var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len) if((0 < hair) && (hair <= hair_styles_list.len)) diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 43497523708..6dd278dc63b 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -8,7 +8,7 @@ obj/machinery/recharger idle_power_usage = 4 active_power_usage = 40000 //40 kW var/obj/item/charging = null - var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight, /obj/item/device/electronic_assembly) + var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric) var/icon_state_charged = "recharger2" var/icon_state_charging = "recharger1" var/icon_state_idle = "recharger0" //also when unpowered @@ -33,19 +33,19 @@ obj/machinery/recharger if(allowed) if(charging) - user << "\A [charging] is already charging here." + to_chat(user, "\A [charging] is already charging here.") return // Checks to make sure he's not in space doing it, and that the area got proper power. if(!powered()) - user << "The [name] blinks red as you try to insert the item!" + to_chat(user, "The [name] blinks red as you try to insert the item!") return if(istype(G, /obj/item/weapon/gun/energy)) var/obj/item/weapon/gun/energy/E = G if(!E.power_supply) - user << "Your gun has no power cell." + to_chat(user, "Your gun has no power cell.") return if(E.self_recharge) - user << "Your gun has no recharge port." + to_chat(user, "Your gun has no recharge port.") return if(istype(G, /obj/item/weapon/gun/energy/staff)) return @@ -65,16 +65,22 @@ obj/machinery/recharger if(!assembly.battery) to_chat(user, "The assembly doesn't have a power cell.") return + if(istype(G, /obj/item/weapon/weldingtool/electric)) + var/obj/item/weapon/weldingtool/electric/welder = G + if(!welder.power_supply) + to_chat(user, "Your welder has no power cell.") + return + user.drop_item() G.loc = src charging = G update_icon() else if(portable && istype(G, /obj/item/weapon/wrench)) if(charging) - user << "Remove [charging] first!" + to_chat(user, "Remove [charging] first!") return anchored = !anchored - user << "You [anchored ? "attached" : "detached"] the recharger." + to_chat(user, "You [anchored ? "attached" : "detached"] the recharger.") playsound(loc, 'sound/items/Ratchet.ogg', 75, 1) else if(default_deconstruction_screwdriver(user, G)) return @@ -208,8 +214,8 @@ obj/machinery/recharger name = "wall recharger" icon = 'icons/obj/stationobjs.dmi' icon_state = "wrecharger0" - active_power_usage = 25000 //25 kW , It's more specialized than the standalone recharger (guns and batons only) so make it more powerful - allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/weapon/cell/device) + active_power_usage = 25000 //25 kW , It's more specialized than the standalone recharger (guns, batons, and flashlights only) so make it more powerful + allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/flashlight, /obj/item/weapon/cell/device) icon_state_charged = "wrecharger2" icon_state_charging = "wrecharger1" icon_state_idle = "wrecharger0" diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index a4b0a02c5ab..73efffe121b 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -8,6 +8,8 @@ var/state //0 off, 1 open, 2 working, 3 dead var/uses = 2 //Calculates initial uses based on starting cell size + var/use_on_synthetic = 0 //If 1, this is only useful on FBPs, if 0, this is only useful on fleshies + var/pad_name = "defib pads" //Just the name given for some cosmetic things var/chance = 75 //Percent chance of working var/charge_cost //Set in New() based on uses var/obj/item/weapon/cell/cell //The size is mostly irrelevant, see 'uses' @@ -32,13 +34,31 @@ if(istype(onto) && Adjacent(usr) && !usr.restrained() && !usr.stat) var/mob/living/carbon/human/user = usr //<--Feel free to code clothing checks right here - user.visible_message("[user] begins applying defib pads to [onto].", - "You begin applying defib pads to [onto].") + if(can_defib(onto)) + user.visible_message("[user] begins applying [pad_name] to [onto].", + "You begin applying [pad_name] to [onto].") if(do_after(user, 100, onto)) patient = onto statechange(1,patient) - user.visible_message("[user] applies defib pads to [onto].", - "You finish applying defib pads to [onto].") + user.visible_message("[user] applies [pad_name] to [onto].", + "You finish applying [pad_name] to [onto].") + + +//can_defib() check is where all of the qualifying conditions should go +//Could probably toss in checks here for damage, organs, etc, but for now I'll leave it as just this +/obj/item/device/defib_kit/proc/can_defib(var/mob/living/carbon/human/target) + var/mob/living/carbon/human/user = usr + if(use_on_synthetic && !target.isSynthetic()) + to_chat(user, "[src] isn't designed for organics!") + return 0 + else if(!use_on_synthetic && target.isSynthetic()) + to_chat(user, "[src] isn't designed for synthetics!") + return 0 + else if(!target.isSynthetic() && ((world.time - target.timeofdeath) > (10 MINUTES)))//Can only revive organics within a few minutes + to_chat(user, "There is no spark of life in [target.name], they've been dead too long to revive this way.") + return 0 + return 1 + /obj/item/device/defib_kit/attackby(var/obj/item/A as obj, mob/living/user as mob) ..() @@ -94,7 +114,7 @@ //Patient moved too far if(patient && !(get_dist(src,patient) <= 1)) //You separated the kit and pads too far - audible_message("There's a clatter as the defib pads are yanked off of [patient].") + audible_message("There is a clatter as the [pad_name] are yanked off of [patient].") statechange(0) patient = null return @@ -111,7 +131,7 @@ patient.visible_message("[patient] convulses!") playsound(src.loc, 'sound/effects/sparks2.ogg', 75, 1) //Actual rezzing code - if(prob(chance) && ((world.time - patient.timeofdeath) < (10 MINUTES))) //Can only revive within a few minutes + if(prob(chance)) if(!patient.client && patient.mind) //Don't force the dead person to come back if they don't want to. for(var/mob/observer/dead/ghost in player_list) if(ghost.mind == patient.mind) @@ -155,3 +175,10 @@ break return + +/obj/item/device/defib_kit/jumper_kit + name = "jumper cable kit" + desc = "This Morpheus-branded FBP defib kit is a semi-automated model. Apply cables, step back, wait." + icon_state = "jumper_kit" + use_on_synthetic = 1 + pad_name = "jumper cables" diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 27ee923a1b4..ecd023320b2 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -181,6 +181,38 @@ else return ..() +/obj/item/device/flashlight/MouseDrop(obj/over_object as obj) + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + /obj/item/device/flashlight/attackby(obj/item/weapon/W, mob/user as mob) if(power_use) if(istype(W, /obj/item/weapon/cell)) diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 6d041847857..76c4f9e7688 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -87,6 +87,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM var/icon_on var/type_butt = null var/chem_volume = 0 + var/max_smoketime = 0 //Related to sprites var/smoketime = 0 var/is_pipe = 0 //Prevents a runtime with pipes var/matchmes = "USER lights NAME with FLAME" @@ -100,8 +101,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM ..() flags |= NOREACT // so it doesn't react until you light it create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15 + if(smoketime && !max_smoketime) + max_smoketime = smoketime /obj/item/clothing/mask/smokable/proc/smoke(amount) + if(smoketime > max_smoketime) + smoketime = max_smoketime smoketime -= amount if(reagents && reagents.total_volume) // check if it has any reagents at all if(ishuman(loc)) @@ -120,11 +125,29 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(location) location.hotspot_expose(700, 5) +/obj/item/clothing/mask/smokable/update_icon() + if(lit) + icon_state = "[initial(icon_state)]_on" + item_state = "[initial(item_state)]_on" + else if(smoketime < max_smoketime) + if(is_pipe) + icon_state = initial(icon_state) + item_state = initial(item_state) + else + icon_state = "[initial(icon_state)]_burnt" + item_state = "[initial(item_state)]_burnt" + if(ismob(loc)) + var/mob/living/M = loc + M.update_inv_wear_mask(0) + M.update_inv_l_hand(0) + M.update_inv_r_hand(1) + ..() + /obj/item/clothing/mask/smokable/examine(mob/user) ..() if(is_pipe) return - var/smoke_percent = round((smoketime / initial(smoketime)) * 100) + var/smoke_percent = round((smoketime / max_smoketime) * 100) switch(smoke_percent) if(90 to INFINITY) user << "[src] is still fresh." @@ -156,15 +179,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM return flags &= ~NOREACT // allowing reagents to react after being lit reagents.handle_reactions() - icon_state = icon_on - item_state = icon_on - if(ismob(loc)) - var/mob/living/M = loc - M.update_inv_wear_mask(0) - M.update_inv_l_hand(0) - M.update_inv_r_hand(1) var/turf/T = get_turf(src) T.visible_message(flavor_text) + update_icon() set_light(2, 0.25, "#E38F46") processing_objects.Add(src) @@ -205,14 +222,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/smokable/proc/quench() lit = 0 processing_objects.Remove(src) - icon_state = initial(icon_state) - item_state = initial(item_state) - - if(ismob(loc)) - var/mob/living/M = loc - M.update_inv_wear_mask(0) - M.update_inv_l_hand(0) - M.update_inv_r_hand(1) + update_icon() /obj/item/clothing/mask/smokable/attack(mob/living/carbon/human/H, mob/user, def_zone) if(lit && H == user && istype(H)) @@ -259,15 +269,15 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/smokable/cigarette name = "cigarette" desc = "A roll of tobacco and nicotine." - icon_state = "cigoff" + icon_state = "cig" + item_state = "cig" throw_speed = 0.5 - item_state = "cigoff" w_class = ITEMSIZE_TINY slot_flags = SLOT_EARS | SLOT_MASK attack_verb = list("burnt", "singed") - icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi type_butt = /obj/item/weapon/cigbutt chem_volume = 15 + max_smoketime = 300 smoketime = 300 matchmes = "USER lights their NAME with their FLAME." lightermes = "USER manages to light their NAME with FLAME." @@ -315,11 +325,11 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/smokable/cigarette/cigar name = "premium cigar" desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!" - icon_state = "cigar2off" - icon_on = "cigar2on" + icon_state = "cigar2" type_butt = /obj/item/weapon/cigbutt/cigarbutt throw_speed = 0.5 - item_state = "cigaroff" + item_state = "cigar" + max_smoketime = 1500 smoketime = 1500 chem_volume = 20 matchmes = "USER lights their NAME with their FLAME." @@ -331,14 +341,13 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/smokable/cigarette/cigar/cohiba name = "\improper Cohiba Robusto cigar" desc = "There's little more you could want from a cigar." - icon_state = "cigar2off" - icon_on = "cigar2on" + icon_state = "cigar2" /obj/item/clothing/mask/smokable/cigarette/cigar/havana name = "premium Havanian cigar" desc = "A cigar fit for only the best of the best." - icon_state = "cigar2off" - icon_on = "cigar2on" + icon_state = "cigar2" + max_smoketime = 7200 smoketime = 7200 chem_volume = 30 @@ -375,9 +384,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/smokable/pipe name = "smoking pipe" desc = "A pipe, for smoking. Made of fine, stained cherry wood." - icon_state = "pipeoff" - item_state = "pipeoff" - icon_on = "pipeon" //Note - these are in masks.dmi + icon_state = "pipe" + item_state = "pipe" smoketime = 0 chem_volume = 50 matchmes = "USER lights their NAME with their FLAME." @@ -429,6 +437,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if (smoketime) user << "[src] is already packed." return + max_smoketime = 1000 smoketime = 1000 if(G.reagents) G.reagents.trans_to_obj(src, G.reagents.total_volume) @@ -455,9 +464,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/smokable/pipe/cobpipe name = "corn cob pipe" desc = "A nicotine delivery system popularized by folksy backwoodsmen, kept popular in the modern age and beyond by space hipsters." - icon_state = "cobpipeoff" - item_state = "cobpipeoff" - icon_on = "cobpipeon" //Note - these are in masks.dmi + icon_state = "cobpipe" + item_state = "cobpipe" chem_volume = 35 ///////// diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index a5b03264d64..2f4b2f3a8ce 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -28,6 +28,38 @@ update_icon() return +/obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj) + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + /obj/item/weapon/melee/baton/loaded/New() //this one starts with a cell pre-installed. ..() bcell = new/obj/item/weapon/cell/device/weapon(src) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 8e039ee2dac..7c5ac1ee551 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -297,6 +297,38 @@ M.update_inv_l_hand() M.update_inv_r_hand() +/obj/item/weapon/weldingtool/MouseDrop(obj/over_object as obj) + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + //Sets the welding state of the welding tool. If you see W.welding = 1 anywhere, please change it to W.setWelding(1) //so that the welding tool updates accordingly /obj/item/weapon/weldingtool/proc/setWelding(var/set_welding, var/mob/M) diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm index 050ec316382..23b42457508 100644 --- a/code/modules/client/preference_setup/general/01_basic.dm +++ b/code/modules/client/preference_setup/general/01_basic.dm @@ -130,7 +130,11 @@ datum/preferences/proc/set_biological_gender(var/gender) return ..() /datum/category_item/player_setup_item/general/basic/proc/get_genders() - var/datum/species/S = all_species[pref.species] + var/datum/species/S + if(pref.species) + S = all_species[pref.species] + else + S = all_species["Human"] var/list/possible_genders = S.genders if(!pref.organ_data || pref.organ_data[BP_TORSO] != "cyborg") return possible_genders diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 079713c7eae..3e239badc7a 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -28,6 +28,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["disabilities"] >> pref.disabilities S["organ_data"] >> pref.organ_data S["rlimb_data"] >> pref.rlimb_data + S["body_markings"] >> pref.body_markings pref.preview_icon = null /datum/category_item/player_setup_item/general/body/save_character(var/savefile/S) @@ -51,6 +52,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["disabilities"] << pref.disabilities S["organ_data"] << pref.organ_data S["rlimb_data"] << pref.rlimb_data + S["body_markings"] << pref.body_markings /datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) if(!pref.species || !(pref.species in playable_species)) @@ -75,6 +77,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.disabilities = sanitize_integer(pref.disabilities, 0, 65535, initial(pref.disabilities)) if(!pref.organ_data) pref.organ_data = list() if(!pref.rlimb_data) pref.rlimb_data = list() + if(!pref.body_markings) pref.body_markings = list() + else pref.body_markings &= body_marking_styles_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) @@ -123,6 +127,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O I.robotize() else if(status == "digital") I.digitize() + + for(var/N in character.organs_by_name) + var/obj/item/organ/external/O = character.organs_by_name[N] + O.markings.Cut() + + for(var/M in pref.body_markings) + var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[M] + var/mark_color = "[pref.body_markings[M]]" + + for(var/BP in mark_datum.body_parts) + var/obj/item/organ/external/O = character.organs_by_name[BP] + if(O) + O.markings[M] = list("color" = mark_color, "datum" = mark_datum) + return /datum/category_item/player_setup_item/general/body/content(var/mob/user) @@ -251,6 +269,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(has_flag(mob_species, HAS_SKIN_COLOR)) . += "
Body Color
" . += "Change Color
__

" + + . += "
Body Markings +
" + for(var/M in pref.body_markings) + . += "[M] - Color" + . += "
__
" + . += "
" + . = jointext(.,null) /datum/category_item/player_setup_item/general/body/proc/has_flag(var/datum/species/mob_species, var/flag) @@ -289,7 +314,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(!(pref.biological_gender in mob_species.genders)) pref.set_biological_gender(mob_species.genders[1]) - //grab one of the valid hair styles for the newly chosen species var/list/valid_hairstyles = list() for(var/hairstyle in hair_styles_list) @@ -334,6 +358,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.s_tone = 0 reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case. + pref.body_markings.Cut() // Basically same as above. var/min_age = get_min_age() var/max_age = get_max_age() @@ -421,6 +446,32 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.f_style = new_f_style return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["marking_style"]) + var/list/usable_markings = pref.body_markings.Copy() ^ body_marking_styles_list.Copy() + for(var/M in usable_markings) + var/datum/sprite_accessory/S = usable_markings[M] + if(!S.species_allowed.len) + continue + else if(!(pref.species in S.species_allowed)) + usable_markings -= M + + var/new_marking = input(user, "Choose a body marking:", "Character Preference") as null|anything in usable_markings + if(new_marking && CanUseTopic(user)) + pref.body_markings[new_marking] = "#000000" //New markings start black + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["marking_remove"]) + var/M = href_list["marking_remove"] + pref.body_markings -= M + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["marking_color"]) + var/M = href_list["marking_color"] + var/mark_color = input(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]) as color|null + if(mark_color && CanUseTopic(user)) + pref.body_markings[M] = "[mark_color]" + return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["reset_limbs"]) reset_limbs() return TOPIC_REFRESH_UPDATE_PREVIEW diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm index de8e06419e8..2c602bcc6d2 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm @@ -356,6 +356,22 @@ ..() gear_tweaks = list(gear_tweak_free_color_choice) -/datum/gear/suit/miscellaneous/redandblackjacket - display_name = "red and black jacket" - path = /obj/item/clothing/suit/storage/toggle/redandblackjacket \ No newline at end of file +/datum/gear/suit/miscellaneous/sec_dep_jacket + display_name = "department jacket, security" + path = /obj/item/clothing/suit/storage/toggle/sec_dep_jacket + +/datum/gear/suit/miscellaneous/engi_dep_jacket + display_name = "department jacket, engineering" + path = /obj/item/clothing/suit/storage/toggle/engi_dep_jacket + +/datum/gear/suit/miscellaneous/supply_dep_jacket + display_name = "department jacket, supply" + path = /obj/item/clothing/suit/storage/toggle/supply_dep_jacket + +/datum/gear/suit/miscellaneous/sci_dep_jacket + display_name = "department jacket, science" + path = /obj/item/clothing/suit/storage/toggle/sci_dep_jacket + +/datum/gear/suit/miscellaneous/med_dep_jacket + display_name = "department jacket, medical" + path = /obj/item/clothing/suit/storage/toggle/med_dep_jacket \ No newline at end of file diff --git a/code/modules/client/preference_setup/preference_setup.dm b/code/modules/client/preference_setup/preference_setup.dm index f72ff0645c0..b3c253647ef 100644 --- a/code/modules/client/preference_setup/preference_setup.dm +++ b/code/modules/client/preference_setup/preference_setup.dm @@ -263,13 +263,14 @@ /datum/category_item/player_setup_item/proc/get_FBP_type() if(!is_FBP()) return 0 // Not a robot. - switch(pref.organ_data["brain"]) - if("assisted") - return PREF_FBP_CYBORG - if("mechanical") - return PREF_FBP_POSI - if("digital") - return PREF_FBP_SOFTWARE + if(O_BRAIN in pref.organ_data) + switch(pref.organ_data[O_BRAIN]) + if("assisted") + return PREF_FBP_CYBORG + if("mechanical") + return PREF_FBP_POSI + if("digital") + return PREF_FBP_SOFTWARE return 0 //Something went wrong! /datum/category_item/player_setup_item/proc/get_min_age() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 710c072e949..d1d51c52dbf 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -88,6 +88,8 @@ datum/preferences var/list/rlimb_data = list() var/list/player_alt_titles = new() // the default name of a job like "Medical Doctor" + var/list/body_markings = list() // "name" = "#rgbcolor" + var/list/flavor_texts = list() var/list/flavour_texts_robot = list() diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index dd732d0f7c3..00ea3308928 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -574,12 +574,6 @@ obj/item/clothing/suit/kimono icon_state = "smw_hoodie" item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black") -/obj/item/clothing/suit/storage/toggle/redandblackjacket - name = "red and black jacket" - desc = "A cool red and black jacket to keep you stylish and cozy." - icon_state = "redandblackjacket" - flags_inv = HIDEHOLSTER - /obj/item/clothing/suit/whitedress name = "white dress" desc = "A fancy white dress." @@ -776,6 +770,44 @@ obj/item/clothing/suit/kimono name = "brown varsity jacket" icon_state = "varsity_brown" +/* + * Department Jackets + */ +/obj/item/clothing/suit/storage/toggle/sec_dep_jacket + name = "department jacket, security" + desc = "A cozy jacket in security's colors. Show your department pride!" + icon_state = "sec_dep_jacket" + item_state_slots = list(slot_r_hand_str = "sec_dep_jacket", slot_l_hand_str = "sec_dep_jacket") + flags_inv = HIDEHOLSTER + +/obj/item/clothing/suit/storage/toggle/engi_dep_jacket + name = "department jacket, engineering" + desc = "A cozy jacket in engineering's colors. Show your department pride!" + icon_state = "engi_dep_jacket" + item_state_slots = list(slot_r_hand_str = "engi_dep_jacket", slot_l_hand_str = "engi_dep_jacket") + flags_inv = HIDEHOLSTER + +/obj/item/clothing/suit/storage/toggle/supply_dep_jacket + name = "department jacket, supply" + desc = "A cozy jacket in supply's colors. Show your department pride!" + icon_state = "supply_dep_jacket" + item_state_slots = list(slot_r_hand_str = "supply_dep_jacket", slot_l_hand_str = "supply_dep_jacket") + flags_inv = HIDEHOLSTER + +/obj/item/clothing/suit/storage/toggle/sci_dep_jacket + name = "department jacket, science" + desc = "A cozy jacket in science's colors. Show your department pride!" + icon_state = "sci_dep_jacket" + item_state_slots = list(slot_r_hand_str = "sci_dep_jacket", slot_l_hand_str = "sci_dep_jacket") + flags_inv = HIDEHOLSTER + +/obj/item/clothing/suit/storage/toggle/med_dep_jacket + name = "department jacket, medical" + desc = "A cozy jacket in medical's colors. Show your department pride!" + icon_state = "med_dep_jacket" + item_state_slots = list(slot_r_hand_str = "med_dep_jacket", slot_l_hand_str = "med_dep_jacket") + flags_inv = HIDEHOLSTER + /* * Track Jackets */ diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a6267a8d00e..a84a2889dc5 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -268,6 +268,8 @@ var/global/list/damage_icon_parts = list() icon_key += "[rgb(part.h_col[1],part.h_col[2],part.h_col[3])]" else icon_key += "#000000" + for(var/M in part.markings) + icon_key += "[M][part.markings[M]["color"]]" if(part.robotic >= ORGAN_ROBOT) icon_key += "2[part.model ? "-[part.model]": ""]" diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index ca1e8358992..089a0befacb 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -983,6 +983,197 @@ species_allowed = list("Teshari") gender = NEUTER +/* +//////////////////////////// +/ =--------------------= / +/ == Body Markings == / +/ =--------------------= / +//////////////////////////// +*/ +/datum/sprite_accessory/marking + icon = 'icons/mob/human_races/markings.dmi' + do_colouration = 1 //Almost all of them have it, COLOR_ADD + + //Empty list is unrestricted. Should only restrict the ones that make NO SENSE on other species, + //like Tajara inner-ear coloring overlay stuff. + species_allowed = list() + + var/body_parts = list() //A list of bodyparts this covers, in organ_tag defines + //Reminder: BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD + + tat_heart + name = "Tattoo (Heart, Torso)" + icon_state = "tat_heart" + body_parts = list(BP_TORSO) + + tat_hive + name = "Tattoo (Hive, Back)" + icon_state = "tat_hive" + body_parts = list(BP_TORSO) + + tat_nightling + name = "Tattoo (Nightling, Back)" + icon_state = "tat_nightling" + body_parts = list(BP_TORSO) + + tat_campbell + name = "Tattoo (Campbell, R.Arm)" + icon_state = "tat_campbell" + body_parts = list(BP_R_ARM) + + tat_tiger + name = "Tattoo (Tiger Stripes, Body)" + icon_state = "tat_campbell" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN) + + taj_paw_socks + name = "Socks Coloration (Taj)" + icon_state = "taj_pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + species_allowed = list("Tajara") + + una_paw_socks + name = "Socks Coloration (Una)" + icon_state = "una_pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + species_allowed = list("Unathi") + + paw_socks + name = "Socks Coloration (Generic)" + icon_state = "pawsocks" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND) + + paw_socks_belly + name = "Socks+Belly Coloration (Generic)" + icon_state = "pawsocksbelly" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO) + + belly_hands_feet + name = "Hands/Feet/Belly Color (Minor)" + icon_state = "bellyhandsfeetsmall" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO) + + hands_feet_belly_full + name = "Hands/Feet/Belly Color (Major)" + icon_state = "bellyhandsfeet" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_GROIN,BP_TORSO) + + patches + name = "Color Patches" + icon_state = "patches" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN) + + patchesface + name = "Color Patches (Face)" + icon_state = "patchesface" + body_parts = list(BP_HEAD) + + bands + name = "Color Bands" + icon_state = "bands" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN) + + bandsface + name = "Color Bands (Face)" + icon_state = "bandsface" + body_parts = list(BP_HEAD) + + tiger_stripes + name = "Tiger Stripes" + icon_state = "tiger" + body_parts = list(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_TORSO,BP_GROIN) + species_allowed = list("Tajara") //There's a tattoo for non-cats + + tigerhead + name = "Tiger Stripes (Head, Minor)" + icon_state = "tigerhead" + body_parts = list(BP_HEAD) + + tigerface + name = "Tiger Stripes (Head, Major)" + icon_state = "tigerface" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") //There's a tattoo for non-cats + + backstripe + name = "Back Stripe" + icon_state = "backstripe" + body_parts = list(BP_TORSO) + + //Taj specific stuff + taj_belly + name = "Belly Fur (Taj)" + icon_state = "taj_belly" + body_parts = list(BP_TORSO) + species_allowed = list("Tajara") + + taj_bellyfull + name = "Belly Fur Wide (Taj)" + icon_state = "taj_bellyfull" + body_parts = list(BP_TORSO) + species_allowed = list("Tajara") + + taj_earsout + name = "Outer Ear (Taj)" + icon_state = "taj_earsout" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_earsin + name = "Inner Ear (Taj)" + icon_state = "taj_earsin" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_nose + name = "Nose Color (Taj)" + icon_state = "taj_nose" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_crest + name = "Chest Fur Crest (Taj)" + icon_state = "taj_crest" + body_parts = list(BP_TORSO) + species_allowed = list("Tajara") + + taj_muzzle + name = "Muzzle Color (Taj)" + icon_state = "taj_muzzle" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_face + name = "Cheeks Color (Taj)" + icon_state = "taj_face" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + taj_all + name = "All Taj Head (Taj)" + icon_state = "taj_all" + body_parts = list(BP_HEAD) + species_allowed = list("Tajara") + + //Una specific stuff + una_face + name = "Face Color (Una)" + icon_state = "una_face" + body_parts = list(BP_HEAD) + species_allowed = list("Unathi") + + una_facelow + name = "Face Color Low (Una)" + icon_state = "una_facelow" + body_parts = list(BP_HEAD) + species_allowed = list("Unathi") + + una_scutes + name = "Scutes (Una)" + icon_state = "una_scutes" + body_parts = list(BP_TORSO) + species_allowed = list("Unathi") + //skin styles - WIP //going to have to re-integrate this with surgery //let the icon_state hold an icon preview for now diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index f37fb3b9b8a..e3fabe82f55 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -39,6 +39,7 @@ var/list/h_col // hair colour var/body_hair // Icon blend for body hair if any. var/mob/living/applied_pressure + var/list/markings = list() // Markings (body_markings) to apply to the icon // Wound and structural data. var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 3c975067a2d..4e381d47ad6 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -69,6 +69,15 @@ var/global/list/limb_icon_cache = list() overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) + //Head markings, duplicated (sadly) below. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" + if(owner.f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style] if(facial_hair_style && facial_hair_style.species_allowed && (species.get_bodytype(owner) in facial_hair_style.species_allowed)) @@ -119,6 +128,15 @@ var/global/list/limb_icon_cache = list() mob_icon = new /icon(species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") apply_colouration(mob_icon) + //Body markings, does not include head, duplicated (sadly) above. + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" + if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" if(!limb_icon_cache[cache_key]) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 98dd1f987c4..75d574ed632 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -223,6 +223,38 @@ attached_lock.stored_dna = list() return 1 +/obj/item/weapon/gun/MouseDrop(obj/over_object as obj) + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + /obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0) if(!user || !target) return diff --git a/html/changelog.html b/html/changelog.html index 068437c9d5b..83e24ec6bf8 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,16 @@ -->
+

30 March 2017

+

Anewbe updated:

+ +

MagmaRam updated:

+ +

28 March 2017

Anewbe updated: