diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 87ab21e610..1d24074caa 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -239,198 +239,124 @@ /obj/item/proc/equipped(var/mob/user, var/slot) return +//Defines which slots correspond to which slot flags +var/list/global/slot_flags_enumeration = list( + "[slot_wear_mask]" = SLOT_MASK, + "[slot_back]" = SLOT_BACK, + "[slot_wear_suit]" = SLOT_OCLOTHING, + "[slot_gloves]" = SLOT_GLOVES, + "[slot_shoes]" = SLOT_FEET, + "[slot_belt]" = SLOT_BELT, + "[slot_glasses]" = SLOT_EYES, + "[slot_head]" = SLOT_HEAD, + "[slot_l_ear]" = SLOT_EARS|SLOT_TWOEARS, + "[slot_r_ear]" = SLOT_EARS|SLOT_TWOEARS, + "[slot_w_uniform]" = SLOT_ICLOTHING, + "[slot_wear_id]" = SLOT_ID, + "[slot_tie]" = SLOT_TIE, + ) + //the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. //If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. //Set disable_warning to 1 if you wish it to not give you outputs. +//Should probably move the bulk of this into mob code some time, as most of it is related to the definition of slots and not item-specific /obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = 0) if(!slot) return 0 if(!M) return 0 - if(ishuman(M)) - //START HUMAN - var/mob/living/carbon/human/H = M - var/list/mob_equip = list() - if(H.species.hud && H.species.hud.equip_slots) - mob_equip = H.species.hud.equip_slots + if(!ishuman(M)) return 0 + + var/mob/living/carbon/human/H = M + var/list/mob_equip = list() + if(H.species.hud && H.species.hud.equip_slots) + mob_equip = H.species.hud.equip_slots - if(H.species && !(slot in mob_equip)) + if(H.species && !(slot in mob_equip)) + return 0 + + //First check if the item can be equipped to the desired slot. + if("[slot]" in slot_flags_enumeration) + var/req_flags = slot_flags_enumeration["[slot]"] + if(!(req_flags & slot_flags)) return 0 + + //Next check that the slot is free + if(H.get_equipped_item(slot)) + return 0 + + //Next check if the slot is accessible. + var/mob/_user = disable_warning? null : H + if(!H.slot_is_accessible(slot, src, _user)) + return 0 + + //Lastly, check special rules for the desired slot. + switch(slot) + if(slot_l_ear, slot_r_ear) + var/slot_other_ear = (slot == slot_l_ear)? slot_r_ear : slot_l_ear + if( (w_class > 1) && !(slot_flags & SLOT_EARS) ) + return 0 + if( (slot_flags & SLOT_TWOEARS) && H.get_equipped_item(slot_other_ear) ) + return 0 + if(slot_wear_id) + if(!H.w_uniform && (slot_w_uniform in mob_equip)) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [name]." + return 0 + if(slot_l_store, slot_r_store) + if(!H.w_uniform && (slot_w_uniform in mob_equip)) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [name]." + return 0 + if(slot_flags & SLOT_DENYPOCKET) + return 0 + if( w_class > 2 && !(slot_flags & SLOT_POCKET) ) + return 0 + if(slot_s_store) + if(!H.wear_suit && (slot_wear_suit in mob_equip)) + if(!disable_warning) + H << "You need a suit before you can attach this [name]." + return 0 + if(!H.wear_suit.allowed) + if(!disable_warning) + usr << "You somehow have a suit with no defined allowed items for suit storage, stop that." + return 0 + if( !(istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed)) ) + return 0 + if(slot_handcuffed) + if(!istype(src, /obj/item/weapon/handcuffs)) + return 0 + if(slot_legcuffed) + if(!istype(src, /obj/item/weapon/legcuffs)) + return 0 + if(slot_in_backpack) //used entirely for equipping spawned mobs or at round start + var/allow = 0 + if(H.back && istype(H.back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = H.back + if(B.contents.len < B.storage_slots && w_class <= B.max_w_class) + allow = 1 + if(!allow) + return 0 + if(slot_tie) + if(!H.w_uniform && (slot_w_uniform in mob_equip)) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [name]." + return 0 + var/obj/item/clothing/under/uniform = H.w_uniform + if(uniform.accessories.len && !uniform.can_attach_accessory(src)) + if (!disable_warning) + H << "You already have an accessory of this type attached to your [uniform]." + return 0 + return 1 - switch(slot) - if(slot_l_hand) - if(H.l_hand) - return 0 - return 1 - if(slot_r_hand) - if(H.r_hand) - return 0 - return 1 - if(slot_wear_mask) - if(H.wear_mask) - return 0 - if(H.head && !(H.head.canremove) && (H.head.flags & HEADCOVERSMOUTH)) - if(!disable_warning) - H << "\The [H.head] is in the way." - return 0 - if( !(slot_flags & SLOT_MASK) ) - return 0 - return 1 - if(slot_back) - if(H.back) - return 0 - if( !(slot_flags & SLOT_BACK) ) - return 0 - return 1 - if(slot_wear_suit) - if(H.wear_suit) - return 0 - if( !(slot_flags & SLOT_OCLOTHING) ) - return 0 - return 1 - if(slot_gloves) - if(H.gloves) - return 0 - if( !(slot_flags & SLOT_GLOVES) ) - return 0 - return 1 - if(slot_shoes) - if(H.shoes) - return 0 - if( !(slot_flags & SLOT_FEET) ) - return 0 - return 1 - if(slot_belt) - if(H.belt) - return 0 - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - if( !(slot_flags & SLOT_BELT) ) - return - return 1 - if(slot_glasses) - if(H.glasses) - return 0 - if(H.head && !(H.head.canremove) && (H.head.flags & HEADCOVERSEYES)) - if(!disable_warning) - H << "\The [H.head] is in the way." - return 0 - if( !(slot_flags & SLOT_EYES) ) - return 0 - return 1 - if(slot_head) - if(H.head) - return 0 - if( !(slot_flags & SLOT_HEAD) ) - return 0 - return 1 - if(slot_l_ear) - if(H.l_ear) - return 0 - if( (w_class > 1) && !(slot_flags & SLOT_EARS) ) - return 0 - if( (slot_flags & SLOT_TWOEARS) && H.r_ear ) - return 0 - return 1 - if(slot_r_ear) - if(H.r_ear) - return 0 - if( (w_class > 1) && !(slot_flags & SLOT_EARS) ) - return 0 - if( (slot_flags & SLOT_TWOEARS) && H.l_ear ) - return 0 - return 1 - if(slot_w_uniform) - if(H.w_uniform) - return 0 - if(H.wear_suit && (H.wear_suit.body_parts_covered & src.body_parts_covered)) - if(!disable_warning) - H << "\The [H.wear_suit] is in the way." - return 0 - if( !(slot_flags & SLOT_ICLOTHING) ) - return 0 - return 1 - if(slot_wear_id) - if(H.wear_id) - return 0 - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - if( !(slot_flags & SLOT_ID) ) - return 0 - return 1 - if(slot_l_store) - if(H.l_store) - return 0 - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - if(slot_flags & SLOT_DENYPOCKET) - return 0 - if( w_class <= 2 || (slot_flags & SLOT_POCKET) ) - return 1 - if(slot_r_store) - if(H.r_store) - return 0 - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - if(slot_flags & SLOT_DENYPOCKET) - return 0 - if( w_class <= 2 || (slot_flags & SLOT_POCKET) ) - return 1 - return 0 - if(slot_s_store) - if(H.s_store) - return 0 - if(!H.wear_suit && (slot_wear_suit in mob_equip)) - if(!disable_warning) - H << "You need a suit before you can attach this [name]." - return 0 - if(!H.wear_suit.allowed) - if(!disable_warning) - usr << "You somehow have a suit with no defined allowed items for suit storage, stop that." - return 0 - if( istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed) ) - return 1 - return 0 - if(slot_handcuffed) - if(H.handcuffed) - return 0 - if(!istype(src, /obj/item/weapon/handcuffs)) - return 0 - return 1 - if(slot_legcuffed) - if(H.legcuffed) - return 0 - if(!istype(src, /obj/item/weapon/legcuffs)) - return 0 - return 1 - if(slot_in_backpack) - if (H.back && istype(H.back, /obj/item/weapon/storage/backpack)) - var/obj/item/weapon/storage/backpack/B = H.back - if(B.contents.len < B.storage_slots && w_class <= B.max_w_class) - return 1 - return 0 - if(slot_tie) - if(!H.w_uniform && (slot_w_uniform in mob_equip)) - if(!disable_warning) - H << "You need a jumpsuit before you can attach this [name]." - return 0 - var/obj/item/clothing/under/uniform = H.w_uniform - if(uniform.accessories.len && !uniform.can_attach_accessory(src)) - if (!disable_warning) - H << "You already have an accessory of this type attached to your [uniform]." - return 0 - if( !(slot_flags & SLOT_TIE) ) - return 0 - return 1 - return 0 //Unsupported slot - //END HUMAN +/obj/item/proc/mob_can_unequip(mob/M, slot, disable_warning = 0) + if(!slot) return 0 + if(!M) return 0 + + if(!canremove) + return 0 + if(!M.slot_is_accessible(slot, src, disable_warning? null : M)) + return 0 + return 1 /obj/item/verb/verb_pickup() set src in oview(1) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 0d20e00166..026773b9c7 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -58,6 +58,10 @@ var/list/slot_equipment_priority = list( \ slot_r_store\ ) +//Checks if a given slot can be accessed at this time, either to equip or unequip I +/mob/proc/slot_is_accessible(var/slot, var/obj/item/I, mob/user=null) + return 1 + //puts the item "W" into an appropriate slot in a human's inventory //returns 0 if it cannot, 1 if successful /mob/proc/equip_to_appropriate_slot(obj/item/W) @@ -143,7 +147,8 @@ var/list/slot_equipment_priority = list( \ W.dropped() return 0 -// Removes an item from inventory and places it in the target atom +// Removes an item from inventory and places it in the target atom. +// If canremove or other conditions need to be checked then use unEquip instead. /mob/proc/drop_from_inventory(var/obj/item/W, var/atom/Target = null) if(W) if(!Target) @@ -201,7 +206,13 @@ var/list/slot_equipment_priority = list( \ if(!I) //If there's nothing to drop, the drop is automatically successful. return 1 - if(!I.canremove && !force) + var/slot + for(var/s in slot_back to slot_tie) //kind of worries me + if(get_equipped_item(s) == I) + slot = s + break + + if(slot && !I.mob_can_unequip(src, slot)) return 0 remove_from_mob(I) @@ -220,6 +231,15 @@ var/list/slot_equipment_priority = list( \ return 1 +//Returns the item equipped to the specified slot, if any. +/mob/proc/get_equipped_item(var/slot) + switch(slot) + if(slot_l_hand) return l_hand + if(slot_r_hand) return r_hand + if(slot_back) return back + if(slot_wear_mask) return wear_mask + return null + //Outdated but still in use apparently. This should at least be a human proc. /mob/proc/get_equipped_items() var/list/items = new/list() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 5484508fe7..6ecaaa1704 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -317,6 +317,48 @@ This saves us from having to call add_fingerprint() any time something is put in return 1 +//Checks if a given slot can be accessed at this time, either to equip or unequip I +/mob/living/carbon/human/slot_is_accessible(var/slot, var/obj/item/I, mob/user=null) + var/obj/item/covering = null + var/check_flags = 0 + + switch(slot) + if(slot_wear_mask) + covering = src.head + check_flags = HEADCOVERSMOUTH + if(slot_glasses) + covering = src.head + check_flags = HEADCOVERSEYES + if(slot_gloves, slot_w_uniform) + covering = src.wear_suit + + if(covering) + if((covering.body_parts_covered & I.body_parts_covered) || (covering.flags & check_flags)) + user << "\The [covering] is in the way." + return 0 + return 1 + +/mob/living/carbon/human/get_equipped_item(var/slot) + switch(slot) + if(slot_wear_suit) return wear_suit + if(slot_gloves) return gloves + if(slot_shoes) return shoes + if(slot_belt) return belt + if(slot_glasses) return glasses + if(slot_head) return head + if(slot_l_ear) return l_ear + if(slot_r_ear) return r_ear + if(slot_w_uniform) return w_uniform + if(slot_wear_id) return wear_id + if(slot_l_store) return l_store + if(slot_r_store) return r_store + if(slot_s_store) return s_store + if(slot_handcuffed) return handcuffed + if(slot_legcuffed) return legcuffed + return ..() + +///Bizarre equip effect system below + /* MouseDrop human inventory menu */