diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 04abf50e362..f778386bb88 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -17,11 +17,11 @@ var/list/stealthminID = list() //reference list with IDs that store ckeys, var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player var/global/list/mob_list = list() //List of all mobs, including clientless -var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless +var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless var/global/list/spirits = list() //List of all the spirits, including Masks var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player -var/global/list/respawnable_list = list() //List of all mobs, dead or in mindless creatures that still be respawned. +var/global/list/respawnable_list = list() //List of all mobs, dead or in mindless creatures that still be respawned. var/global/list/simple_animal_list = list() //List of all simple animals, including clientless var/global/list/med_hud_users = list() diff --git a/code/game/alternate_appearance.dm b/code/game/alternate_appearance.dm new file mode 100644 index 00000000000..005876e8ccc --- /dev/null +++ b/code/game/alternate_appearance.dm @@ -0,0 +1,155 @@ +/* + Alternate Appearances! By RemieRichards + A framework for replacing an atom (and it's overlays) with an override = 1 image, that's less shit! + Example uses: + * hallucinating all mobs looking like skeletons + * people wearing cardborg suits appearing as Standard Cyborgs to the other Silicons + * !!use your imagination!! + +*/ + + +//This datum is built on-the-fly by some of the procs below +//no need to instantiate it +/datum/alternate_appearance + var/key = "" + var/image/img + var/list/viewers = list() + var/atom/owner = null + + +/* + Displays the alternate_appearance + displayTo - a list of MOBS to show this appearance to +*/ +/datum/alternate_appearance/proc/display_to(list/displayTo) + if(!displayTo || !displayTo.len) + return + for(var/m in displayTo) + var/mob/M = m + if(!M.viewing_alternate_appearances) + M.viewing_alternate_appearances = list() + viewers |= M + M.viewing_alternate_appearances[key] = src + if(M.client) + M.client.images |= img + +/* + Hides the alternate_appearance + hideFrom - optional list of MOBS to hide it from the list's mobs specifically +*/ +/datum/alternate_appearance/proc/hide(list/hideFrom) + var/list/hiding = viewers + if(hideFrom) + hiding = hideFrom + + for(var/m in hiding) + var/mob/M = m + if(M.client) + M.client.images -= img + if(M.viewing_alternate_appearances && M.viewing_alternate_appearances.len) + M.viewing_alternate_appearances -= key + if(!M.viewing_alternate_appearances.len) + M.viewing_alternate_appearances = null + viewers -= M + + +/* + Removes the alternate_appearance from its owner's alternate_appearances list, hiding it also +*/ +/datum/alternate_appearance/proc/remove() + hide() + if(owner && owner.alternate_appearances) + owner.alternate_appearances -= key + if(!owner.alternate_appearances.len) + owner.alternate_appearances = null + + +/datum/alternate_appearance/Destroy() + remove() + return ..() + + + +/atom + var/list/alternate_appearances //the alternate appearances we own + var/list/viewing_alternate_appearances //the alternate appearances we're viewing, stored here to reestablish them after Logout()s + //these lists are built/destroyed as necessary, so atoms aren't all lugging around lists full of datums + +/* + Builds an alternate_appearance datum for the supplied args, optionally displaying it straight away + key - the key to the assoc list of key = /datum/alternate_appearances + img - the image file to be the "alternate appearance" + WORKS BEST IF: + * it has override = 1 set + * the image's loc is the atom that will use the appearance (otherwise... it's not exactly an alt appearance of this atom is it?) + displayTo - optional list of MOBS to display to immediately + + Example: + var/image/I = image(icon = 'disguise.dmi', icon_state = "disguise", loc = src) + I.override = 1 + add_alt_appearance("super_secret_disguise", I, players) + +*/ +/atom/proc/add_alt_appearance(key, img, list/displayTo = list()) + if(!key || !img) + return + if(!alternate_appearances) + alternate_appearances = list() + + var/datum/alternate_appearance/AA = new() + AA.img = img + AA.key = key + AA.owner = src + + alternate_appearances[key] = AA + if(displayTo && displayTo.len) + display_alt_appearance(key, displayTo) + + +////////////// +// WRAPPERS // +////////////// + +/* + Removes an alternate_appearance from src's alternate_appearances list + Wrapper for: alternate_appearance/remove() + key - the key to the assoc list of key = /datum/alternate_appearance +*/ +/atom/proc/remove_alt_appearance(key) + if(alternate_appearances) + if(alternate_appearances[key]) + var/datum/alternate_appearance/AA = alternate_appearances[key] + qdel(AA) + + +/* + Displays an alternate appearance from src's alternate_appearances list + Wrapper for: alternate_appearance/display_to() + key - the key to the assoc list of key = /datum/alternate_appearance + displayTo - a list of MOBS to show this appearance to +*/ +/atom/proc/display_alt_appearance(key, list/displayTo) + if(!alternate_appearances || !key) + return + var/datum/alternate_appearance/AA = alternate_appearances[key] + if(!AA || !AA.img) + return + AA.display_to(displayTo) + + +/* + Hides an alternate appearance from src's alternate_appearances list + Wrapper for: alternate_appearance/hide() + key - the key to the assoc list of key = /datum/alternate_appearance + hideFrom - optional list of MOBS to hide it from the list's mobs specifically +*/ +/atom/proc/hide_alt_appearance(key, list/hideFrom) + if(!alternate_appearances || !key) + return + var/datum/alternate_appearance/AA = alternate_appearances[key] + if(!AA) + return + AA.hide(hideFrom) + + diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1bd5b9d602f..d13ce8b0bfa 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -67,6 +67,12 @@ return 0 /atom/Destroy() + if(alternate_appearances) + for(var/aakey in alternate_appearances) + var/datum/alternate_appearance/AA = alternate_appearances[aakey] + qdel(AA) + alternate_appearances = null + if(reagents) qdel(reagents) reagents = null diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index a44225b2d34..1e6ef08edf6 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -89,14 +89,6 @@ item_state = "greenbandana" flags_inv = 0 -/obj/item/clothing/head/cardborg - name = "cardborg helmet" - desc = "A helmet made out of a box." - icon_state = "cardborg_h" - item_state = "cardborg_h" - flags = HEADCOVERSEYES | HEADCOVERSMOUTH - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - /obj/item/clothing/head/justice name = "justice hat" desc = "Fight for what's righteous!" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index e1bfc0c1282..071c6032722 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -5,7 +5,7 @@ * Ushanka * Pumpkin head * Kitty ears - * + * Cardborg Disguise */ /* @@ -207,4 +207,24 @@ var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "mouseyinner") mob.Blend(earbit, ICON_OVERLAY) - icon_override = mob \ No newline at end of file + icon_override = mob + +/obj/item/clothing/head/cardborg + name = "cardborg helmet" + desc = "A helmet made out of a box." + icon_state = "cardborg_h" + item_state = "cardborg_h" + flags = HEADCOVERSEYES | HEADCOVERSMOUTH + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + +/obj/item/clothing/head/cardborg/equipped(mob/living/user, slot) + ..() + if(ishuman(user) && slot == slot_head) + var/mob/living/carbon/human/H = user + if(istype(H.wear_suit, /obj/item/clothing/suit/cardborg)) + var/obj/item/clothing/suit/cardborg/CB = H.wear_suit + CB.disguise(user, src) + +/obj/item/clothing/head/cardborg/dropped(mob/living/user) + ..() + user.remove_alt_appearance("standard_borg_disguise") diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index f1a8865418c..c8b62d446be 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -199,6 +199,26 @@ body_parts_covered = UPPER_TORSO|LOWER_TORSO flags_inv = HIDEJUMPSUIT +/obj/item/clothing/suit/cardborg/equipped(mob/living/user, slot) + ..() + if(slot == slot_wear_suit) + disguise(user) + +/obj/item/clothing/suit/cardborg/dropped(mob/living/user) + ..() + user.remove_alt_appearance("standard_borg_disguise") + +/obj/item/clothing/suit/cardborg/proc/disguise(mob/living/carbon/human/H, obj/item/clothing/head/cardborg/borghead) + if(istype(H)) + if(!borghead) + borghead = H.head + if(istype(borghead, /obj/item/clothing/head/cardborg)) //why is this done this way? because equipped() is called BEFORE THE ITEM IS IN THE SLOT WHYYYY + var/image/I = image(icon = 'icons/mob/robots.dmi' , icon_state = "robot", loc = H) + I.override = 1 + I.overlays += image(icon = 'icons/mob/robots.dmi' , icon_state = "eyes-robot") //gotta look realistic + H.add_alt_appearance("standard_borg_disguise", I, silicon_mob_list+H) //you look like a robot to robots! (including yourself because you're totally a robot) + + /obj/item/clothing/suit/poncho name = "poncho" desc = "Your classic, non-racist poncho." diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 54fc8aac90d..84235f90979 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -70,6 +70,12 @@ //readd this mob's HUDs (antag, med, etc) reload_huds() + if(viewing_alternate_appearances && viewing_alternate_appearances.len) + for(var/aakey in viewing_alternate_appearances) + var/datum/alternate_appearance/AA = viewing_alternate_appearances[aakey] + if(AA) + AA.display_to(list(src)) + CallHook("Login", list("client" = src.client, "mob" = src)) // Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget(). diff --git a/paradise.dme b/paradise.dme index 75cdb9919c3..c0eacf96797 100644 --- a/paradise.dme +++ b/paradise.dme @@ -306,6 +306,7 @@ #include "code\defines\procs\radio.dm" #include "code\defines\procs\records.dm" #include "code\defines\procs\statistics.dm" +#include "code\game\alternate_appearance.dm" #include "code\game\asteroid.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm"