diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm index 3c006073304c..6f2a34e50ea5 100644 --- a/code/datums/components/forensics.dm +++ b/code/datums/components/forensics.dm @@ -192,4 +192,4 @@ return if(isitem(parent)) var/obj/item/I = parent - I.AddElement(/datum/element/decal/blood, initial(I.icon) || I.icon, initial(I.icon_state) || I.icon_state, _color = get_blood_dna_color(blood_DNA)) + I.AddElement(/datum/element/decal/blood, I.icon, I.icon_state, _color = get_blood_dna_color(blood_DNA)) diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index 85f75bef2416..0a3ca8ce59a3 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -6,9 +6,11 @@ . = ..() RegisterSignal(target, COMSIG_ATOM_GET_EXAMINE_NAME, PROC_REF(get_examine_name), TRUE) + RegisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), PROC_REF(redraw), TRUE) /datum/element/decal/blood/Detach(atom/source, force) UnregisterSignal(source, COMSIG_ATOM_GET_EXAMINE_NAME) + UnregisterSignal(source, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) return ..() /datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha, source) @@ -30,3 +32,11 @@ override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a" override[EXAMINE_POSITION_BEFORE] = " blood-stained " return COMPONENT_EXNAME_CHANGED + +///this is probably quite bad, let me know if you have a better solution for this -S +/datum/element/decal/blood/proc/redraw(datum/source, mob/user) + SIGNAL_HANDLER + + var/atom/bloodsource = source + Detach(source) + bloodsource.AddElement(/datum/element/decal/blood, bloodsource.icon, bloodsource.icon_state, _color = get_blood_dna_color(bloodsource.return_blood_DNA())) diff --git a/code/datums/elements/world_icon.dm b/code/datums/elements/world_icon.dm new file mode 100644 index 000000000000..bcb0129c6c68 --- /dev/null +++ b/code/datums/elements/world_icon.dm @@ -0,0 +1,121 @@ +///////////////////////////////////////////////////////////// +////////// WORLD ICON ELEMENT DIRECTORY ////////// +///////////////////////////////////////////////////////////// +//PORTED FROM MOJAVE SUN// + +// Slap onto something to give it a world icon that differs from the inventory one (allows for realistically sized objects and all that) // +// To fix 25/06/2021 : Blood Decals, Mutable Overlays and other baked in bitch ass overlays that need to be remade when the icon changes // +// Fixed 07/05/2022: Now you can deal with the above by handling everything with attached_proc instead +// Fixed 12/04/2023: Icon states, Needs major tuning up by someone who can properly make it work + +/datum/element/world_icon + id_arg_index = 2 + element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH + //If we want COMPLEX world icon behavior, this proc will handle icon updating when the item is NOT in the inventory. + //I just assumed that the default update_icon is for inventory sprites because ss13 basically focuses on how the sprites + //look on your hand, not how they realistically look in the world. + var/attached_proc + /// Only used if attached_proc doesn't exist, simply changes the icon of target to this when it's in the inventory + var/inventory_icon + /// Only used if attached_proc doesn't exist, simply changes the icon of target to this when it's NOT in the inventory + var/world_icon + /// Only used when inventory state icon is different from original + var/inventory_icon_state + /// Only used when world state icon is different from original, pretty much just the original "icon_state" but if you for some reason need to flip the standard icon states for this element around you can use this + var/world_icon_state + +/datum/element/world_icon/Attach(obj/item/target, attached_proc, world_icon, inventory_icon, world_icon_state, inventory_icon_state) + . = ..() + if(!istype(target)) + return ELEMENT_INCOMPATIBLE + + src.attached_proc = attached_proc + src.world_icon = world_icon + src.world_icon_state = world_icon_state + src.inventory_icon = inventory_icon + src.inventory_icon_state = inventory_icon_state + RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON, PROC_REF(update_icon)) + RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(update_icon_state)) + RegisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_STORAGE_ENTERED, COMSIG_ITEM_DROPPED, COMSIG_STORAGE_EXITED), PROC_REF(inventory_updated)) + target.update_appearance(UPDATE_ICON) + target.update_appearance(UPDATE_ICON_STATE) + +/datum/element/world_icon/Detach(obj/item/source) + . = ..() + UnregisterSignal(source, COMSIG_ATOM_UPDATE_ICON) + UnregisterSignal(source, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(update_icon_state)) + UnregisterSignal(source, list(COMSIG_ITEM_EQUIPPED, COMSIG_STORAGE_ENTERED, COMSIG_ITEM_DROPPED, COMSIG_STORAGE_EXITED)) + source.update_appearance(UPDATE_ICON) + source.update_appearance(UPDATE_ICON_STATE) + +/datum/element/world_icon/proc/update_icon(obj/item/source, updates) + SIGNAL_HANDLER + + if((source.item_flags & IN_INVENTORY) || (source.loc && SEND_SIGNAL(source.loc, COMSIG_CONTAINS_STORAGE))) + if(attached_proc) + return + return default_inventory_icon(source) + + if(attached_proc) + return call(source, attached_proc)(updates) + else + return default_world_icon(source) + +/datum/element/world_icon/proc/update_icon_state(obj/item/source, updates) + SIGNAL_HANDLER + + if((source.item_flags & IN_INVENTORY) || (source.loc && SEND_SIGNAL(source.loc, COMSIG_CONTAINS_STORAGE))) + if(attached_proc) + return + return default_inventory_icon_state(source) + + if(attached_proc) + return call(source, attached_proc)(updates) + else + return default_world_icon_state(source) + +/datum/element/world_icon/proc/inventory_updated(obj/item/source) + SIGNAL_HANDLER + + source.update_appearance(UPDATE_ICON) + source.update_appearance(UPDATE_ICON_STATE) + +/datum/element/world_icon/proc/default_inventory_icon(obj/item/source) + SIGNAL_HANDLER + + source.icon = inventory_icon + +/datum/element/world_icon/proc/default_world_icon(obj/item/source) + SIGNAL_HANDLER + + source.icon = world_icon + +/datum/element/world_icon/proc/default_inventory_icon_state(obj/item/source) + SIGNAL_HANDLER + + if(!inventory_icon_state) + source.icon_state = source.icon_state + return + + INVOKE_ASYNC(src, PROC_REF(check_inventory_state), source) + +/datum/element/world_icon/proc/default_world_icon_state(obj/item/source) + SIGNAL_HANDLER + + if(!world_icon_state) + source.icon_state = source.icon_state + return + + INVOKE_ASYNC(src, PROC_REF(check_world_icon_state), source) + +/datum/element/world_icon/proc/check_inventory_state(obj/item/source) + SIGNAL_HANDLER + + inventory_icon_state = source.inventory_state + source.icon_state = inventory_icon_state + +/datum/element/world_icon/proc/check_world_icon_state(obj/item/source) + SIGNAL_HANDLER + + world_icon_state = source.world_state + source.icon_state = world_icon_state diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 75cc7c0556fb..7e64ce658e8b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -202,6 +202,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb var/canMouseDown = FALSE + //for setting world icons on the go + var/inventory_state + var/world_state + /obj/item/Initialize() if(attack_verb) @@ -518,12 +522,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /obj/item/proc/equipped(mob/user, slot, initial = FALSE) SHOULD_CALL_PARENT(1) visual_equipped(user, slot, initial) - SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot) for(var/X in actions) var/datum/action/A = X if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot. A.Grant(user) item_flags |= IN_INVENTORY + SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot) if(!initial) if(equip_sound && (slot_flags & slot)) playsound(src, equip_sound, EQUIP_SOUND_VOLUME, TRUE, ignore_walls = FALSE) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 1475ae88f8dd..c8c9a0f96b96 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -179,6 +179,7 @@ /obj/item/kitchen/knife/combat name = "combat knife" + icon = 'icons/obj/world/melee.dmi' icon_state = "combatknife" item_state = "combatknife" desc = "A military combat utility survival knife." @@ -188,6 +189,10 @@ attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut") bayonet = TRUE +/obj/item/kitchen/knife/combat/Initialize() + . = ..() + AddElement(/datum/element/world_icon, null, icon, 'icons/obj/kitchen.dmi') + /obj/item/kitchen/knife/combat/survival name = "survival knife" icon_state = "survivalknife" diff --git a/icons/obj/world/melee.dmi b/icons/obj/world/melee.dmi new file mode 100644 index 000000000000..ff8e2114e827 Binary files /dev/null and b/icons/obj/world/melee.dmi differ diff --git a/shiptest.dme b/shiptest.dme index 9721797c050a..0bd5680e7417 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -655,6 +655,7 @@ #include "code\datums\elements\update_icon_blocker.dm" #include "code\datums\elements\update_icon_updates_onmob.dm" #include "code\datums\elements\waddling.dm" +#include "code\datums\elements\world_icon.dm" #include "code\datums\elements\decals\_decals.dm" #include "code\datums\elements\decals\blood.dm" #include "code\datums\helper_datums\events.dm"