From 084eae04657d384098e2efe7fac148ebf97d583e Mon Sep 17 00:00:00 2001 From: Sun-Soaked <45698967+Sun-Soaked@users.noreply.github.com> Date: Fri, 31 May 2024 02:46:11 -0400 Subject: [PATCH] World Icons (#2279) ## About The Pull Request Ports world icons from Mojave 13. This is an element that allows for tiny, size-accurate versions of object sprites in a roundabout way. ~~Drafted since spritainers want more coverage before merging~~ UNDRAFTED by request of a spritainer. God weeps ### //MAKING A SUPER BASIC WORLD ICON IMPLEMENTATION GUIDE: FOR REAL. NO VIRUS. 100% ORGANIC// - Place the Element in an Init below The Item In Question `/obj/item/Initialize()` ` . = ..()` ` AddElement(/datum/element/world_icon, null, icon, 'icon')` - Fill in info. Put the ORIGINAL ICON in the addelement's `'icon'` slot (yeah, this element layers the "original" sprite on top of the worldicon one, using it as the default. It just be like that sometimes) `/obj/item/kitchen/knife/combat/Initialize()` ` . = ..()` ` AddElement(/datum/element/world_icon, null, icon, 'icons/obj/kitchen.dmi')` - Put the directory to your NEW, WORLD ICON in the item's normal icon var `icon = 'icons/obj/world/melee.dmi'` The world icon and icon adjustment vars on obj/item should allow for implementation in places where an object's Icon has to frequently change. ## Why It's Good For The Game Just a little guy ## Changelog :cl: add: World icon element. add: World icons for combat knives. /:cl: --------- Signed-off-by: Sun-Soaked <45698967+Sun-Soaked@users.noreply.github.com> Co-authored-by: Sun-Soaked <45698967+MemedHams@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> --- code/datums/components/forensics.dm | 2 +- code/datums/elements/decals/blood.dm | 10 +++ code/datums/elements/world_icon.dm | 121 +++++++++++++++++++++++++++ code/game/objects/items.dm | 6 +- code/game/objects/items/kitchen.dm | 5 ++ icons/obj/world/melee.dmi | Bin 0 -> 474 bytes shiptest.dme | 1 + 7 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 code/datums/elements/world_icon.dm create mode 100644 icons/obj/world/melee.dmi 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 0000000000000000000000000000000000000000..ff8e2114e82750930ad8ac463473092dc6af961d GIT binary patch literal 474 zcmV<00VV#4P)&PA)DSCj8=-HezF+an%cTZ1SE-y4ABQG8v zAWho)ZvX%Q0d!JMQvg8b*k%9#0E>E5Sad{Xb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1 zht_cWbS{T>|G@f)A_VcUs5GH|SmS0{R32 z_wPJ3+^66nkLxK+L3o3NLtvi29*U^{r9p*u^IyEqslQ8gm`6Xy!T)O$i{-kB4?Is# zfuFG;Em#m|EJ%a}BEKkkp+5`!>n-)?2>DVA?$2mUwNyCY48mOEEtU&s1+g3hImG0$ Qm;e9(07*qoM6N<$f-6_cMF0Q* literal 0 HcmV?d00001 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"