diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index b522d7e7c64..7d29322163d 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1010,6 +1010,46 @@ var/global/floorIsLava = 0 var/datum/seed/S = plant_controller.seeds[seedtype] S.harvest(usr,0,0,1) +/datum/admins/proc/spawn_custom_item() + set category = "Debug" + set desc = "Spawn a custom item." + set name = "Spawn Custom Item" + + if(!check_rights(R_SPAWN)) return + + var/owner = input("Select a ckey.", "Spawn Custom Item") as null|anything in custom_items + if(!owner|| !custom_items[owner]) + return + + var/list/possible_items = custom_items[owner] + var/datum/custom_item/item_to_spawn = input("Select an item to spawn.", "Spawn Custom Item") as null|anything in possible_items + if(!item_to_spawn) + return + + item_to_spawn.spawn_item(get_turf(usr)) + +/datum/admins/proc/check_custom_items() + + set category = "Debug" + set desc = "Check the custom item list." + set name = "Check Custom Items" + + if(!check_rights(R_SPAWN)) return + + if(!custom_items) + usr << "Custom item list is null." + return + + if(!custom_items.len) + usr << "Custom item list not populated." + return + + for(var/assoc_key in custom_items) + usr << "[assoc_key] has:" + var/list/current_items = custom_items[assoc_key] + for(var/datum/custom_item/item in current_items) + usr << "- name: [item.name] icon: [item.item_icon] path: [item.item_path] desc: [item.item_desc]" + /datum/admins/proc/spawn_plant() set category = "Debug" set desc = "Spawn a spreading plant effect." diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 877b29b0b1b..c22fc85466b 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -115,6 +115,8 @@ var/list/admin_verbs_fun = list( ) var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_fruit, + /datum/admins/proc/spawn_custom_item, + /datum/admins/proc/check_custom_items, /datum/admins/proc/spawn_plant, /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ /client/proc/respawn_character, diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index a8ee25c896e..c021f715edf 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -2,11 +2,6 @@ // Remember to change 'icon = 'icons/obj/custom_items.dmi'' for items not using /obj/item/fluff as a base // Clothing item_state doesn't use custom_items.dmi. Just add them to the normal clothing files. -/obj/item/fluff // so that they don't spam up the object tree - icon = 'icons/obj/custom_items.dmi' - w_class = 1.0 - - /////////////////////////////// 50_n00b - R.A.N.G.E.'s blue dress ////////////////////////// /obj/item/clothing/suit/fluff/b_dress diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index 966e789c5de..55ee25a5954 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -6,102 +6,146 @@ /var/list/custom_items = list() +/datum/custom_item + var/assoc_key + var/character_name + var/item_icon + var/item_desc + var/name = "unnamed item" + var/item_path = /obj/item + var/req_access = 0 + var/list/req_titles = list() + +/datum/custom_item/proc/spawn_item(var/newloc) + var/obj/item/citem = new item_path(newloc) + apply_to_item(citem) + return citem + +/datum/custom_item/proc/apply_to_item(var/obj/item/item) + if(!item) + return + if(name) + item.name = name + if(item_desc) + item.desc = item_desc + if(item_icon) + item.icon = 'icons/obj/custom_items.dmi' + item.icon_override = 'icons/mob/custom_items.dmi' + item.icon_state = item_icon + return item + //parses the config file into the above listlist /hook/startup/proc/loadCustomItems() - var/custom_items_file = file2text("config/custom_items.txt") - var/list/file_list = text2list(custom_items_file, "\n") - for(var/line in file_list) - if(findtext(line, "#", 1, 2)) + + var/datum/custom_item/current_data + for(var/line in text2list(file2text("config/custom_items.txt"), "\n")) + + line = trim(line) + if(line == "" || !line || findtext(line, "#", 1, 2) || findtext(line, "}", 1, 2)) continue - var/list/Entry = text2list(line, ":") - for(var/i = 1 to Entry.len) - Entry[i] = trim(Entry[i]) + if(findtext(line, "{", 1, 2) || findtext(line, "}", 1, 2)) // New block! + if(current_data && current_data.assoc_key) + if(!custom_items[current_data.assoc_key]) + custom_items[current_data.assoc_key] = list() + var/list/L = custom_items[current_data.assoc_key] + L |= current_data + current_data = null - if(Entry.len < 3) - continue; + var/split = findtext(line,":") + if(!split) + continue + var/field = trim(copytext(line,1,split)) + var/field_data = trim(copytext(line,(split+1))) + if(!field || !field_data) + continue - if(!custom_items[Entry[1]]) - custom_items[Entry[1]] = list() - custom_items[Entry[1]] += Entry + if(!current_data) + current_data = new() + + switch(field) + if("ckey") + current_data.assoc_key = lowertext(field_data) + if("character_name") + current_data.character_name = lowertext(field_data) + if("item_path") + current_data.item_path = text2path(field_data) + if("item_name") + current_data.name = field_data + if("item_icon") + if(field_data in icon_states('icons/obj/custom_items.dmi')) + current_data.item_icon = field_data + if("item_desc") + current_data.item_desc = field_data + if("req_access") + current_data.req_access = field_data + if("req_titles") + current_data.req_titles = text2list(field_data,", ") return 1 //gets the relevant list for the key from the listlist if it exists, check to make sure they are meant to have it and then calls the giving function /proc/EquipCustomItems(mob/living/carbon/human/M) + return + var/list/key_list = custom_items[M.ckey] if(!key_list || key_list.len < 1) return - for(var/list/Entry in key_list) - if(Entry.len < 3) - continue; + for(var/datum/custom_item/citem in key_list) - if(Entry[1] != M.ckey || Entry[2] != "" || Entry[2] != M.real_name) + // Check for requisite ckey and character name. + if(citem.assoc_key != M.ckey || citem.character_name != M.real_name) continue - //required access/job - var/obj/item/weapon/card/id/ID = M.wear_id //should be an id even though pdas can also be there, due to this being run at spawn, before there is a chance to change it - if(Entry.len>=4 && length(Entry[4]) > 0) - var/required_access = 0; - required_access = text2num(Entry[4]) + // Check for required access. + var/obj/item/weapon/card/id/current_id = M.wear_id + if(citem.req_access && !(istype(current_id) && (citem.req_access in current_id.access))) + continue - if(!required_access) - var/list/JobTitles = text2list(Entry[4]) - var/ok = 0 - var/CurrentTitle = M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role - for(var/title in JobTitles) - if(title == CurrentTitle) - ok = 1 - if(ok == 0) - continue + // Check for required job title. + var/has_title + var/current_title = M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role + for(var/title in citem.req_titles) + if(title == current_title) + has_title = 1 + break + if(!has_title) + continue - else if(required_access != 0) - if(!(required_access in ID.access)) - continue + // ID cards and PDAs are applied directly to the existing object rather than spawned fresh. + var/obj/item/existing_item + if(citem.item_path == /obj/item/weapon/card/id && istype(current_id)) //Set earlier. + existing_item = M.wear_id + else if(citem.item_path == /obj/item/device/pda) + existing_item = locate(/obj/item/device/pda) in M.contents - //the else looks redundant and that it should probably be not an else and just not have the if, but then if there was a name/desc/icon_state set then all the items would get the same one, and i dont want the config file to be wider than it already has to be - if(findtext(Entry[3], ",")) - var/list/Paths = text2list(Entry[3], ",") - for(var/P in Paths) - //ids make the standard id be different, instead of spawning a new one (because clunky as fuck) - if(P == "/obj/item/weapon/card/id") - continue - PlaceCustomItem(M, P) + // Spawn and equip the item. + if(existing_item) + citem.apply_to_item(existing_item) else - var/obj/item/Item - if(Entry[3] == "/obj/item/weapon/card/id") - Item = ID - else - Item = PlaceCustomItem(M,Entry[3]) - if(!istype(Item)) - continue - if(Entry.len < 5) - continue - if(Entry[5] != "") - Item.name = Entry[5] - if(istype(Item, /obj/item/weapon/card/id)) - Item.name += "[M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role]" - if(Entry.len < 6) - continue - if(Entry[6] != "") - Item.desc = Entry[6] + place_custom_item(M,citem) + return -//actually sticks the item on the person -/proc/PlaceCustomItem(mob/living/carbon/human/M, var/path) - if(!path) return +// Places the item on the target mob. +/proc/place_custom_item(mob/living/carbon/human/M, var/datum/custom_item/citem) - var/obj/item/Item = new path() + if(!citem) return + var/obj/item/newitem = citem.spawn_item() - if(M.equip_to_appropriate_slot(Item)) - return Item - if(istype(M.back,/obj/item/weapon/storage) && M.back:contents.len < M.back:storage_slots) // Try to place it in something on the mob's back - Item.loc = M.back - return Item - else - for(var/obj/item/weapon/storage/S in M.contents) // Try to place it in any item that can store stuff, on the mob. - if (S.contents.len < S.storage_slots) - Item.loc = S - return Item - Item.loc = get_turf(M.loc) - return Item \ No newline at end of file + if(M.equip_to_appropriate_slot(newitem)) + return newitem + + if(istype(M.back,/obj/item/weapon/storage)) + var/obj/item/weapon/storage/backpack = M.back + if(backpack.contents.len < backpack.storage_slots) + newitem.loc = M.back + return newitem + + // Try to place it in any item that can store stuff, on the mob. + for(var/obj/item/weapon/storage/S in M.contents) + if (S.contents.len < S.storage_slots) + newitem.loc = S + return newitem + newitem.loc = get_turf(M.loc) + return newitem \ No newline at end of file diff --git a/config/example/custom_items.txt b/config/example/custom_items.txt index 86c6bd31c01..e4bf80e29ca 100644 --- a/config/example/custom_items.txt +++ b/config/example/custom_items.txt @@ -1,14 +1,29 @@ -# custom items for people and shit in here -# basic: -# ckey: name: /path/to/obj -# additional options -# ckey: name: /path/to/obj: required access OR job title: item name: description: icon state -# required access is one of the numbers from -# if required access is 0 or blank then always gets it -# job title means if the item wants chemist but they are pharmacist then it wont do it (can be comma separated to have multiple, eg Chemist, Pharmacist if it's for both jobs -# yes they have to be in that order, and if you want a custom description you need to have a custom name too -# you can leave any othe than the ckey and path blank if you want and it will use the default for whatever the item is -# paths can be comma separated, but you wont be able to set custom name/desc/icon in this file, it will have to be done via an item definition (in code/modules/customitems/item_defines.dm) or by having multiple entries in this config -# unless its an id, because fuck code duplication -# if icon state is set then the icon had better be in icons/obj/custom_items.dmi otherwise it'll be invisible -# also # at the start means the line is a comment \ No newline at end of file +## +# Custom items go here. They are modifications of existing paths; look at the example for details. +# Item will spawn if the target has one of the req_titles and if their on-spawn ID has the required access level. +# req_access is going to be a shit to maintain since the config file can't grab constants and has to use integers, use it minimally. +# Separate titles with a single comma and a space (', ') or they'll bork. +# +# EX: +# { +# ckey: zuhayr +# character_name: Jane Doe +# item_path: /obj/item/toy/plushie +# item_name: ugly plush toy +# item_icon: flagmask +# item_desc: It's truly hideous. +# req_titles: Assistant, Security Officer +# req_access: 1 +# } +## + +{ +ckey: zuhayr +character_name: Jane Doe +item_path: /obj/item/toy/plushie +item_name: ugly plush toy +item_icon: flagmask +item_desc: It's truly hideous. +req_titles: Assistant, Security Officer +req_access: 1 +} diff --git a/icons/mob/custom_items.dmi b/icons/mob/custom_items.dmi new file mode 100644 index 00000000000..e69de29bb2d