From 8f0f144202598b6fbce82968f2b7b2e36d1eca6b Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Sun, 22 Jan 2023 07:14:33 +0100 Subject: [PATCH] [MIRROR] Mannequins [MDB IGNORE] (#18869) Mannequins (#72830) ## About The Pull Request you can now craft mannequins using 25 wood or plastic they work with the mob stripping system letting you put items on em! ![image](https://user-images.githubusercontent.com/23585223/213600352-ad79cbaa-3ce0-4bf0-aa25-d31d01b5f51a.png) ![image](https://user-images.githubusercontent.com/23585223/213676239-065f266b-5874-43f1-81e6-2730e0a32fa7.png) ## Why It's Good For The Game fun stuff for CARGO FASHION showcases. ## Changelog :cl: add: You can now craft mannequins with wood or plastic. /:cl: Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com> --- .../items/stacks/sheets/sheet_types.dm | 2 + code/game/objects/structures/mannequin.dm | 276 ++++++++++++++++++ icons/mob/species/human/mannequin.dmi | Bin 0 -> 1975 bytes tgstation.dme | 1 + 4 files changed, 279 insertions(+) create mode 100644 code/game/objects/structures/mannequin.dm create mode 100644 icons/mob/species/human/mannequin.dmi diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index eee0c736662..6ecc676ab9b 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -307,6 +307,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new/datum/stack_recipe("wooden buckler", /obj/item/shield/buckler, 20, time = 4 SECONDS, category = CAT_EQUIPMENT), \ new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 5 SECONDS, category = CAT_TOOLS),\ + new/datum/stack_recipe("mannequin", /obj/structure/mannequin/wood, 25, time = 5 SECONDS, one_per_turf = TRUE, category = CAT_ENTERTAINMENT), \ new/datum/stack_recipe("tiki mask", /obj/item/clothing/mask/gas/tiki_mask, 2, category = CAT_CLOTHING), \ new/datum/stack_recipe("smoking pipe", /obj/item/clothing/mask/cigarette/pipe, 2, category = CAT_CLOTHING), \ new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 1 SECONDS, category = CAT_TOOLS),\ @@ -730,6 +731,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/cup/glass/waterbottle/empty, category = CAT_CONTAINERS), \ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/cup/glass/waterbottle/large/empty, 3, category = CAT_CONTAINERS), \ new /datum/stack_recipe("colo cups", /obj/item/reagent_containers/cup/glass/colocup, 1, category = CAT_CONTAINERS), \ + new /datum/stack_recipe("mannequin", /obj/structure/mannequin/plastic, 25, time = 5 SECONDS, one_per_turf = TRUE, category = CAT_ENTERTAINMENT), \ new /datum/stack_recipe("wet floor sign", /obj/item/clothing/suit/caution, 2, category = CAT_EQUIPMENT), \ new /datum/stack_recipe("warning cone", /obj/item/clothing/head/cone, 2, category = CAT_EQUIPMENT), \ new /datum/stack_recipe("blank wall sign", /obj/item/sign, 1, category = CAT_FURNITURE))) diff --git a/code/game/objects/structures/mannequin.dm b/code/game/objects/structures/mannequin.dm new file mode 100644 index 00000000000..05e2aa84d0e --- /dev/null +++ b/code/game/objects/structures/mannequin.dm @@ -0,0 +1,276 @@ +#define MANNEQUIN_WOOD "wood" +#define MANNEQUIN_PLASTIC "plastic" + +/// A mannequin! A structure that can display clothing on itself. +/obj/structure/mannequin + name = "mannequin" + desc = "Oh, so this is a dress-up game now." + icon = 'icons/mob/species/human/mannequin.dmi' + icon_state = "mannequin_wood_male" + density = TRUE + resistance_flags = FLAMMABLE + appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE + mouse_drag_pointer = MOUSE_ACTIVE_POINTER + pixel_y = 3 + base_pixel_y = 3 + layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE + /// Which body type we use, male or female? + var/body_type + /// Material we're used of, wood or plastic? + var/material + /// String for the underwear we use. + var/underwear_name + /// String for the undershirt we use. + var/undershirt_name + /// String for the socks we use. + var/socks_name + /// Static list of slot flags we have clothing slots for. + var/static/list/slot_flags = list( + ITEM_SLOT_HEAD, + ITEM_SLOT_EYES, + ITEM_SLOT_EARS, + ITEM_SLOT_MASK, + ITEM_SLOT_NECK, + ITEM_SLOT_BACK, + ITEM_SLOT_BELT, + ITEM_SLOT_ID, + ITEM_SLOT_ICLOTHING, + ITEM_SLOT_OCLOTHING, + ITEM_SLOT_GLOVES, + ITEM_SLOT_FEET, + ) + /// Assoc list of all item slots (turned to strings) to the items they hold. + var/list/worn_items = list() + +/obj/structure/mannequin/Initialize(mapload) + . = ..() + for(var/slot_flag in slot_flags) + worn_items["[slot_flag]"] = null + if(!body_type) + body_type = pick(MALE, FEMALE) + if(!material) + material = pick("wood", "plastic") + icon_state = "mannequin_[material]_[body_type == FEMALE ? "female" : "male"]" + AddElement(/datum/element/strippable, GLOB.strippable_mannequin_items) + AddComponent(/datum/component/simple_rotation, ROTATION_IGNORE_ANCHORED) + update_appearance() + +/obj/structure/mannequin/Destroy() + QDEL_LIST_ASSOC_VAL(worn_items) + return ..() + +/obj/structure/mannequin/atom_destruction(damage_flag) + for(var/slot_flag in worn_items) + var/obj/item/worn_item = worn_items[slot_flag] + if(worn_item) + worn_item.forceMove(drop_location()) + return ..() + +/obj/structure/mannequin/Exited(atom/movable/gone, direction) + . = ..() + for(var/slot_flag in worn_items) + if(worn_items[slot_flag] == gone) + worn_items[slot_flag] = null + update_appearance() + +/obj/structure/mannequin/wrench_act(mob/living/user, obj/item/tool) + . = ..() + default_unfasten_wrench(user, tool) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/structure/mannequin/update_overlays() + . = ..() + var/mutable_appearance/pedestal = mutable_appearance(icon, "pedestal_[material]") + pedestal.pixel_y = -3 + . += pedestal + var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[underwear_name] + if(underwear) + if(body_type == FEMALE && underwear.gender == MALE) + . += wear_female_version(underwear.icon_state, underwear.icon, BODY_LAYER, FEMALE_UNIFORM_FULL) + else + . += mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER) + var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[undershirt_name] + if(undershirt) + if(body_type == FEMALE) + . += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER) + else + . += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER) + var/datum/sprite_accessory/socks/socks = GLOB.socks_list[socks_name] + if(socks) + . += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER) + for(var/slot_flag in worn_items) + var/obj/item/worn_item = worn_items[slot_flag] + if(!worn_item) + continue + var/default_layer = 0 + var/default_icon = null + var/female_icon = NO_FEMALE_UNIFORM + switch(text2num(slot_flag)) //this kinda sucks because build worn icon kinda sucks + if(ITEM_SLOT_HEAD) + default_layer = HEAD_LAYER + default_icon = 'icons/mob/clothing/head/default.dmi' + if(ITEM_SLOT_EYES) + default_layer = GLASSES_LAYER + default_icon = 'icons/mob/clothing/eyes.dmi' + if(ITEM_SLOT_EARS) + default_layer = EARS_LAYER + default_icon = 'icons/mob/clothing/ears.dmi' + if(ITEM_SLOT_MASK) + default_layer = FACEMASK_LAYER + default_icon = 'icons/mob/clothing/mask.dmi' + if(ITEM_SLOT_NECK) + default_layer = NECK_LAYER + default_icon = 'icons/mob/clothing/neck.dmi' + if(ITEM_SLOT_BACK) + default_layer = BACK_LAYER + default_icon = 'icons/mob/clothing/back.dmi' + if(ITEM_SLOT_BELT) + default_layer = BELT_LAYER + default_icon = 'icons/mob/clothing/belt.dmi' + if(ITEM_SLOT_ID) + default_layer = ID_LAYER + default_icon = 'icons/mob/clothing/id.dmi' + if(ITEM_SLOT_ICLOTHING) + default_layer = UNIFORM_LAYER + default_icon = DEFAULT_UNIFORM_FILE + if(body_type == FEMALE && istype(worn_item, /obj/item/clothing/under)) + var/obj/item/clothing/under/worn_jumpsuit = worn_item + female_icon = worn_jumpsuit.female_sprite_flags + if(ITEM_SLOT_OCLOTHING) + default_layer = SUIT_LAYER + default_icon = DEFAULT_SUIT_FILE + if(ITEM_SLOT_GLOVES) + default_layer = GLOVES_LAYER + default_icon = 'icons/mob/clothing/hands.dmi' + if(ITEM_SLOT_FEET) + default_layer = SHOES_LAYER + default_icon = DEFAULT_SHOES_FILE + . += worn_item.build_worn_icon(default_layer, default_icon, female_uniform = female_icon) + +/obj/structure/mannequin/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + var/choice = tgui_input_list(user, "Underwear, Undershirt, or Socks?", "Changing", list("Underwear","Undershirt","Socks")) + if(!Adjacent(user)) + return + switch(choice) + if("Underwear") + var/new_undies = tgui_input_list(user, "Select the mannequin's underwear", "Changing", GLOB.underwear_list) + if(new_undies) + underwear_name = new_undies + if("Undershirt") + var/new_undershirt = tgui_input_list(user, "Select the mannequin's undershirt", "Changing", GLOB.undershirt_list) + if(new_undershirt) + undershirt_name = new_undershirt + if("Socks") + var/new_socks = tgui_input_list(user, "Select the mannequin's socks", "Changing", GLOB.socks_list) + if(new_socks) + socks_name = new_socks + update_appearance() + +/obj/structure/mannequin/wood + material = MANNEQUIN_WOOD + +/obj/structure/mannequin/plastic + material = MANNEQUIN_PLASTIC + +GLOBAL_LIST_INIT(strippable_mannequin_items, create_strippable_list(list( + /datum/strippable_item/mannequin_slot/head, + /datum/strippable_item/mannequin_slot/eyes, + /datum/strippable_item/mannequin_slot/ears, + /datum/strippable_item/mannequin_slot/mask, + /datum/strippable_item/mannequin_slot/neck, + /datum/strippable_item/mannequin_slot/back, + /datum/strippable_item/mannequin_slot/belt, + /datum/strippable_item/mannequin_slot/id, + /datum/strippable_item/mannequin_slot/uniform, + /datum/strippable_item/mannequin_slot/suit, + /datum/strippable_item/mannequin_slot/gloves, + /datum/strippable_item/mannequin_slot/feet, +))) + +/datum/strippable_item/mannequin_slot + /// The ITEM_SLOT_* to equip to. + var/item_slot + +/datum/strippable_item/mannequin_slot/get_item(atom/source) + var/obj/structure/mannequin/mannequin_source = source + return istype(mannequin_source) ? mannequin_source.worn_items["[item_slot]"] : null + +/datum/strippable_item/mannequin_slot/try_equip(atom/source, obj/item/equipping, mob/user) + . = ..() + if(!.) + return FALSE + if(!(equipping.slot_flags & item_slot)) + to_chat(user, span_warning("[equipping] won't fit!")) + return FALSE + return TRUE + +/datum/strippable_item/mannequin_slot/finish_equip(atom/source, obj/item/equipping, mob/user) + var/obj/structure/mannequin/mannequin_source = source + if(!istype(mannequin_source)) + return + if(!user.transferItemToLoc(equipping, mannequin_source) || QDELETED(equipping)) + return + mannequin_source.worn_items["[item_slot]"] = equipping + mannequin_source.update_appearance() + +/datum/strippable_item/mannequin_slot/finish_unequip(atom/source, mob/user) + var/obj/structure/mannequin/mannequin_source = source + if(!istype(mannequin_source)) + return + var/obj/item/unequipped = mannequin_source.worn_items["[item_slot]"] + user.put_in_hands(unequipped) + +/datum/strippable_item/mannequin_slot/head + key = STRIPPABLE_ITEM_HEAD + item_slot = ITEM_SLOT_HEAD + +/datum/strippable_item/mannequin_slot/eyes + key = STRIPPABLE_ITEM_EYES + item_slot = ITEM_SLOT_EYES + +/datum/strippable_item/mannequin_slot/ears + key = STRIPPABLE_ITEM_EARS + item_slot = ITEM_SLOT_EARS + +/datum/strippable_item/mannequin_slot/mask + key = STRIPPABLE_ITEM_MASK + item_slot = ITEM_SLOT_MASK + +/datum/strippable_item/mannequin_slot/neck + key = STRIPPABLE_ITEM_NECK + item_slot = ITEM_SLOT_NECK + +/datum/strippable_item/mannequin_slot/back + key = STRIPPABLE_ITEM_BACK + item_slot = ITEM_SLOT_BACK + +/datum/strippable_item/mannequin_slot/belt + key = STRIPPABLE_ITEM_BELT + item_slot = ITEM_SLOT_BELT + +/datum/strippable_item/mannequin_slot/id + key = STRIPPABLE_ITEM_ID + item_slot = ITEM_SLOT_ID + +/datum/strippable_item/mannequin_slot/uniform + key = STRIPPABLE_ITEM_JUMPSUIT + item_slot = ITEM_SLOT_ICLOTHING + +/datum/strippable_item/mannequin_slot/suit + key = STRIPPABLE_ITEM_SUIT + item_slot = ITEM_SLOT_OCLOTHING + +/datum/strippable_item/mannequin_slot/gloves + key = STRIPPABLE_ITEM_GLOVES + item_slot = ITEM_SLOT_GLOVES + +/datum/strippable_item/mannequin_slot/feet + key = STRIPPABLE_ITEM_FEET + item_slot = ITEM_SLOT_FEET + +#undef MANNEQUIN_WOOD +#undef MANNEQUIN_PLASTIC diff --git a/icons/mob/species/human/mannequin.dmi b/icons/mob/species/human/mannequin.dmi new file mode 100644 index 0000000000000000000000000000000000000000..b08b50b73c5bee6c88b04a283ceaf262af6e8c66 GIT binary patch literal 1975 zcmV;o2T1sdP)004jl0{{R3eocQU0000jP)t-sxw*M; zP&T)VXP$6Nrg&3)T0gFUTb5@+xV+5g%h1@8n5((DxtG~OUH||90d!JM zQvg8b*k%9#0H1nPSad{Xb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1Hd0*& z)rZT0$_lQ2F5r*`0P*m0#9B9Qp#T5|jY&j7RA_6X$zQC{a zME4Kq|2#l~G~Z%_!5~6DsfhQ)0F=PGq5~(9z3Kge;w}HzKK|t45Pz~OI?(Tl0DZFm zJC3*5Fsk-@bPma)(0HHwyu!Dbix-Iv0;ek87sCO}puXh?xX~DQVM(rzhs(@#7lY)4%jAx#1GZA{c^z%OSz#Q~_y2{aUna{l;_m9i%%_5cyvgm+cR7gJ=RLBC0_d|yT zU?AU%`vL0fk&x5I<{l7a{oybKf*ub!N1u%Rd?etoZy4up2&W8B5$lHe8~WcGg9U{j zhCr|*!q=tX3s3ZbU^mPK`(=fLVp06)fS(J70&Wf6cpeZO6cvJ2=N8xT%mIEE`uY?7 z0Phqx0#iWq_48xyq2r7Amd{-*7;qHd;T}E@yN(}J`1xUAA;X7-8UMWn^(-)_%D1?O z1w(x6(Rem={HVg$15|MM+)t*0&z{3(g8HCfaBES&jvQz_6MD|TI#R#5q)>?=x}=ys zzR_`{_qxNuJE>ocU_p9TkoX_cn(`pE@d*1(d61fYdV&Wi-_`LTwTVnni3Yya@F2C9 zaXODH1#5VanthwjKcW!>fn9nJ2bG_^lV@u*z5k9+u&OdhP#vnScz z7^U|`w?}vor(hnW7SGjkJ_7Hje5V(w`x<7v7?4TE1*Wnx^yg{baFE*L42Senj)#anyhZscmfi z$qO4C4^4THnyqGK(|i?luwV_oQEM;P+ZD?1I9?MTG%A!gxA;;qd9cx~X9$|KRn3Fc z+RK|;{K*aR%@9xUh_n14W{d^aA~_%xpQHoR4H|1=%p=X2~69;Er!B)vch`ldy& zvQ1N@KzWenzl={M;=6aLM6Y}&Q3;d>jePr7O4LT1D=K&~L-CjgjeLXezD%yL;KgE9 z6>soiJHdQsD~0D!sS%1NJZR)kE-uD+V7bN#ixGN^dCI zo1?zSf$s(iw)DUVJ%&7J9=^P0{hxB6OxV0~Dk@Xyn^!y+sP9;1X3x z@Xg4#uh%;wh+e3tsalZcx3e`^#XMp{1o?#zs1YRiX5<@u*Hn<^-{yRG z0|jG=+XmsE!GkovCDY5RIoQh9D|LlVn~f$w@H)bSM!v~+_IQdWd6PkSq4EFoVPSPV z*wpHHu(8$gU}LM{!RA)OgUzju2OC=*4>q^S5((JJ;y~adZ932JKz919t*L=eUc!M_ zGR2MA&}w+_34+x;_yj?@p|mwaCwNoSJcxh&+2a-d?bTRtEB}N8FCh;;#WW9|Kvs$& z4?e-{f8xQ>q3Fj5Y93r*n%mt!OK@iL;O04k*3{&|=iQ1mJor5X5xzY|u#yLxTMcdf zCk3l`u)P_N<;i&b&_J+~2RE_Ie{ak2+Q>UxVHFQPe6z<0{tXbdKJ=~zx