Files
CHOMPStation2/code/modules/customitems/item_spawning.dm
2021-05-31 17:30:12 +00:00

239 lines
8.1 KiB
Plaintext

// Switch this out to use a database at some point. Each ckey is
// associated with a list of custom item datums. When the character
// spawns, the list is checked and all appropriate datums are spawned.
// See config/example/custom_items.txt for a more detailed overview
// of how the config system works.
// CUSTOM ITEM ICONS:
// Inventory icons must be in CUSTOM_ITEM_OBJ with state name [item_icon].
// On-mob icons must be in CUSTOM_ITEM_MOB with state name [item_icon].
// Inhands must be in CUSTOM_ITEM_MOB as [icon_state]_l and [icon_state]_r.
// Mech kits must have mech icons in CUSTOM_ITEM_OBJ under [kit_icon].
// Broken must be [kit_icon]-broken and open must be [kit_icon]-open.
// Voidsuits and hooded kits must also have hardsuit icons in CUSTOM_ITEM_MOB as [kit_icon]_suit
// and [kit_icon]_helmet, and in CUSTOM_ITEM_OBJ as [kit_icon]_suit.
// If hooded, have [kit_icon]_suit_t in both files for the hood-up version.
// If not using the default overlay, have [kit_icon]_light in both files for custom light overlays.
/var/list/custom_items = list()
/datum/custom_item
var/assoc_key
var/character_name
var/inherit_inhands = 1 //if unset, and inhands are not provided, then the inhand overlays will be invisible.
var/item_icon
var/item_desc
var/name
var/item_path = /obj/item
var/req_access = 0
var/list/req_titles = list()
var/kit_name
var/kit_desc
var/kit_icon
var/additional_data //for modular modkits, item path; for mech modkits, allowed mechs; for voidsuit modkits, light overlays
/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)
if(!istype(item))
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
return
else
if(inherit_inhands)
apply_inherit_inhands(item)
else
item.item_state_slots = null
item.item_icons = null
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
item.item_state = null
item.icon_override = CUSTOM_ITEM_MOB
var/obj/item/clothing/under/U = item
if(istype(U))
U.worn_state = U.icon_state
U.update_rolldown_status()
// Kits are dumb so this is going to have to be hardcoded/snowflake.
if(istype(item, /obj/item/device/kit))
var/obj/item/device/kit/K = item
K.set_info(kit_name, kit_desc, kit_icon, additional_data = additional_data)
return item
/datum/custom_item/proc/apply_inherit_inhands(var/obj/item/item)
var/list/new_item_icons = list()
var/list/new_item_state_slots = list()
var/list/available_states = cached_icon_states(CUSTOM_ITEM_MOB)
//If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots
//Then use icon_override to make every other slot use the custom sprites by default.
//This has to be done before we touch any of item's vars
if(!("[item_icon]_l" in available_states))
new_item_state_slots[slot_l_hand_str] = get_state(item, slot_l_hand_str, "_l")
new_item_icons[slot_l_hand_str] = get_icon(item, slot_l_hand_str, 'icons/mob/items/lefthand.dmi')
if(!("[item_icon]_r" in available_states))
new_item_state_slots[slot_r_hand_str] = get_state(item, slot_r_hand_str, "_r")
new_item_icons[slot_r_hand_str] = get_icon(item, slot_r_hand_str, 'icons/mob/items/righthand.dmi')
item.item_state_slots = new_item_state_slots
item.item_icons = new_item_icons
//this has to mirror the way update_inv_*_hand() selects the state
/datum/custom_item/proc/get_state(var/obj/item/item, var/slot_str, var/hand_str)
var/t_state
if(item.item_state_slots && item.item_state_slots[slot_str])
t_state = item.item_state_slots[slot_str]
else if(item.item_state)
t_state = item.item_state
else
t_state = item.icon_state
if(item.icon_override)
t_state += hand_str
return t_state
//this has to mirror the way update_inv_*_hand() selects the icon
/datum/custom_item/proc/get_icon(var/obj/item/item, var/slot_str, var/icon/hand_icon)
var/icon/t_icon
if(item.icon_override)
t_icon = item.icon_override
else if(item.item_icons && (slot_str in item.item_icons))
t_icon = item.item_icons[slot_str]
else
t_icon = hand_icon
return t_icon
// Parses the config file into the custom_items list.
/hook/startup/proc/load_custom_items()
var/datum/custom_item/current_data
for(var/line in splittext(file2text("config/custom_items.txt"), "\n"))
line = trim(line)
if(line == "" || !line || findtext(line, "#", 1, 2))
continue
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
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(!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")
current_data.item_icon = field_data
if("inherit_inhands")
current_data.inherit_inhands = text2num(field_data)
if("item_desc")
current_data.item_desc = field_data
if("req_access")
current_data.req_access = text2num(field_data)
if("req_titles")
current_data.req_titles = splittext(field_data,", ")
if("kit_name")
current_data.kit_name = field_data
if("kit_desc")
current_data.kit_desc = field_data
if("kit_icon")
current_data.kit_icon = field_data
if("additional_data")
current_data.additional_data = 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/equip_custom_items(mob/living/carbon/human/M)
var/list/key_list = custom_items[M.ckey]
if(!key_list || key_list.len < 1)
return
for(var/datum/custom_item/citem in key_list)
// Check for requisite ckey and character name.
if((lowertext(citem.assoc_key) != lowertext(M.ckey)) || (lowertext(citem.character_name) != lowertext(M.real_name)))
log_debug("Custom Item: [key_name(M)] Ckey or Char name does not match.")
continue
// Check for required access.
var/obj/item/weapon/card/id/current_id = M.wear_id
if(citem.req_access && citem.req_access > 0) // These are numbers, not lists
if(!(istype(current_id) && (citem.req_access in current_id.access)))
log_debug("Custom Item: [key_name(M)] Does not have required access.")
continue
// Check for required job title.
if(citem.req_titles && citem.req_titles.len > 0)
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)
log_debug("Custom Item: [key_name(M)] Does not have required job.")
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
else if(citem.item_path == /obj/item/weapon/storage/backpack)
existing_item = locate(/obj/item/weapon/storage/backpack) in M.contents
// Spawn and equip the item.
if(existing_item)
citem.apply_to_item(existing_item)
else
place_custom_item(M,citem)
// Places the item on the target mob.
/proc/place_custom_item(mob/living/carbon/human/M, var/datum/custom_item/citem)
if(!citem) return
var/obj/item/newitem = citem.spawn_item()
if(M.equip_to_appropriate_slot(newitem))
return newitem
if(M.equip_to_storage(newitem))
return newitem
newitem.loc = get_turf(M.loc)
return newitem