TGUI Stripping (#22131)
* strippable * readds whitespace * corrects my Initialize placement * fix typo * change icons to 64px/32px * makes it look good
@@ -310,7 +310,7 @@
|
||||
#define WIZARD_AGE_MIN 30 //youngest a wizard can be
|
||||
#define APPRENTICE_AGE_MIN 29 //youngest an apprentice can be
|
||||
#define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up
|
||||
#define POCKET_STRIP_DELAY 40 //time taken (in deciseconds) to search somebody's pockets
|
||||
#define POCKET_STRIP_DELAY (4 SECONDS) //time taken to search somebody's pockets
|
||||
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
|
||||
|
||||
#define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases
|
||||
|
||||
@@ -55,14 +55,14 @@
|
||||
#define LAVAPROTECT (1<<0)
|
||||
/// SUIT and HEAD items which stop pressure damage.
|
||||
/// To stop you taking all pressure damage you must have both a suit and head item with these flags. First one is high pressure (fires), second one is low (space).
|
||||
#define STOPSHIGHPRESSURE (1<<1)
|
||||
#define STOPSHIGHPRESSURE (1<<1)
|
||||
#define STOPSLOWPRESSURE (1<<2)
|
||||
/// Blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
|
||||
#define BLOCK_GAS_SMOKE_EFFECT (1<<3)
|
||||
/// Mask allows internals
|
||||
#define MASKINTERNALS (1<<4)
|
||||
/// Prevents from slipping on wet floors, in space etc
|
||||
#define NOSLIP (1<<5)
|
||||
#define NOSLIP (1<<5)
|
||||
/// Prevents from slipping on frozen floors
|
||||
#define NOSLIP_ICE (1<<6)
|
||||
/// Prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag.
|
||||
@@ -71,7 +71,7 @@
|
||||
/// The voicebox in this clothing can be toggled.
|
||||
#define VOICEBOX_TOGGLABLE (1<<8)
|
||||
/// The voicebox is currently turned off.
|
||||
#define VOICEBOX_DISABLED (1<<9)
|
||||
#define VOICEBOX_DISABLED (1<<9)
|
||||
/// Prevents you from feeling sad if you shower in them
|
||||
#define SHOWEROKAY (1<<10)
|
||||
/// Allows helmets and glasses to scan reagents.
|
||||
@@ -82,6 +82,8 @@
|
||||
#define HEADINTERNALS (1<<13)
|
||||
/// Clothes that use large icons, for applying the proper overlays like blood
|
||||
#define LARGE_WORN_ICON (1<<14)
|
||||
/// Clothes that cause a larger notification when placed on a person.
|
||||
#define DANGEROUS_OBJECT (1<<15)
|
||||
|
||||
#define STOPSPRESSUREDAMAGE (STOPSHIGHPRESSURE | STOPSLOWPRESSURE) //covers both high and low pressure
|
||||
|
||||
|
||||
31
code/__DEFINES/strippable.dm
Normal file
@@ -0,0 +1,31 @@
|
||||
// All of these must be matched in StripMenu.js.
|
||||
#define STRIPPABLE_ITEM_HEAD "head"
|
||||
#define STRIPPABLE_ITEM_BACK "back"
|
||||
#define STRIPPABLE_ITEM_MASK "mask"
|
||||
#define STRIPPABLE_ITEM_NECK "neck"
|
||||
#define STRIPPABLE_ITEM_EYES "eyes"
|
||||
#define STRIPPABLE_ITEM_EARS "ears"
|
||||
#define STRIPPABLE_ITEM_JUMPSUIT "jumpsuit"
|
||||
#define STRIPPABLE_ITEM_SUIT "suit"
|
||||
#define STRIPPABLE_ITEM_GLOVES "gloves"
|
||||
#define STRIPPABLE_ITEM_FEET "shoes"
|
||||
#define STRIPPABLE_ITEM_SUIT_STORAGE "suit_storage"
|
||||
#define STRIPPABLE_ITEM_ID "id"
|
||||
#define STRIPPABLE_ITEM_BELT "belt"
|
||||
#define STRIPPABLE_ITEM_LPOCKET "left_pocket"
|
||||
#define STRIPPABLE_ITEM_RPOCKET "right_pocket"
|
||||
#define STRIPPABLE_ITEM_LHAND "left_hand"
|
||||
#define STRIPPABLE_ITEM_RHAND "right_hand"
|
||||
#define STRIPPABLE_ITEM_HANDCUFFS "handcuffs"
|
||||
#define STRIPPABLE_ITEM_LEGCUFFS "legcuffs"
|
||||
#define STRIPPABLE_ITEM_CORGI_COLLAR "corgi_collar"
|
||||
#define STRIPPABLE_ITEM_PARROT_HEADSET "parrot_headset"
|
||||
|
||||
/// This slot is not obscured.
|
||||
#define STRIPPABLE_OBSCURING_NONE 0
|
||||
|
||||
/// This slot is completely obscured, and cannot be accessed.
|
||||
#define STRIPPABLE_OBSCURING_COMPLETELY 1
|
||||
|
||||
/// This slot can't be seen, but can be accessed.
|
||||
#define STRIPPABLE_OBSCURING_HIDDEN 2
|
||||
@@ -41,7 +41,7 @@
|
||||
*/
|
||||
|
||||
///Initialize the lazylist
|
||||
#define LAZYINITLIST(L) if (!L) L = list()
|
||||
#define LAZYINITLIST(L) if (!L) { L = list(); }
|
||||
///If the provided list is empty, set it to null
|
||||
#define UNSETEMPTY(L) if (L && !length(L)) L = null
|
||||
///Remove an item from the list, set the list to null if empty
|
||||
@@ -76,6 +76,11 @@
|
||||
///Returns the list if it's actually a valid list, otherwise will initialize it
|
||||
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
|
||||
#define reverseList(L) reverseRange(L.Copy())
|
||||
/// Performs an insertion on the given lazy list with the given key and value. If the value already exists, a new one will not be made.
|
||||
#define LAZYORASSOCLIST(lazy_list, key, value) \
|
||||
LAZYINITLIST(lazy_list); \
|
||||
LAZYINITLIST(lazy_list[key]); \
|
||||
lazy_list[key] |= value;
|
||||
///Adds to the item K the value V, if the list is null it will initialize it
|
||||
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += V;
|
||||
///Removes the value V from the item K, if the item K is empty will remove it from the list, if the list is empty will set the list to null
|
||||
|
||||
491
code/datums/elements/strippable.dm
Normal file
@@ -0,0 +1,491 @@
|
||||
/// An element for atoms that, when dragged and dropped onto a mob, opens a strip panel.
|
||||
/datum/element/strippable
|
||||
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH
|
||||
argument_hash_start_idx = 2
|
||||
|
||||
/// An assoc list of keys to /datum/strippable_item
|
||||
var/list/items
|
||||
|
||||
/// A proc path that returns TRUE/FALSE if we should show the strip panel for this entity.
|
||||
/// If it does not exist, the strip menu will always show.
|
||||
/// Will be called with (mob/user).
|
||||
var/should_strip_proc_path
|
||||
|
||||
/// An existing strip menus
|
||||
var/list/strip_menus
|
||||
|
||||
/datum/element/strippable/Attach(datum/target, list/items, should_strip_proc_path)
|
||||
. = ..()
|
||||
if (!isatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(target, COMSIG_MOUSEDROP_ONTO, PROC_REF(mouse_drop_onto))
|
||||
|
||||
src.items = items
|
||||
src.should_strip_proc_path = should_strip_proc_path
|
||||
|
||||
/datum/element/strippable/Detach(datum/source, force)
|
||||
. = ..()
|
||||
|
||||
UnregisterSignal(source, COMSIG_MOUSEDROP_ONTO)
|
||||
|
||||
if (!isnull(strip_menus))
|
||||
QDEL_NULL(strip_menus[source])
|
||||
|
||||
/datum/element/strippable/proc/mouse_drop_onto(datum/source, atom/over, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (user == source)
|
||||
return
|
||||
|
||||
if (over != user)
|
||||
return
|
||||
|
||||
// Cyborgs buckle people by dragging them onto them, unless in combat mode.
|
||||
if (iscyborg(user))
|
||||
var/mob/living/silicon/robot/cyborg_user = user
|
||||
if (!cyborg_user.combat_mode)
|
||||
return
|
||||
|
||||
if (!isnull(should_strip_proc_path) && !call(source, should_strip_proc_path)(user))
|
||||
return
|
||||
|
||||
var/datum/strip_menu/strip_menu
|
||||
|
||||
if (isnull(strip_menu))
|
||||
strip_menu = new(source, src)
|
||||
LAZYSET(strip_menus, source, strip_menu)
|
||||
|
||||
INVOKE_ASYNC(strip_menu, TYPE_PROC_REF(/datum,ui_interact), user)
|
||||
|
||||
/// A representation of an item that can be stripped down
|
||||
/datum/strippable_item
|
||||
/// The STRIPPABLE_ITEM_* key
|
||||
var/key
|
||||
|
||||
/// Should we warn about dangerous clothing?
|
||||
var/warn_dangerous_clothing = TRUE
|
||||
|
||||
/// Gets the item from the given source.
|
||||
/datum/strippable_item/proc/get_item(atom/source)
|
||||
|
||||
/// Tries to equip the item onto the given source.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/// This should be used for checking if an item CAN be equipped.
|
||||
/// It should not perform the equipping itself.
|
||||
/datum/strippable_item/proc/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (HAS_TRAIT(equipping, TRAIT_NODROP))
|
||||
to_chat(user, "<span class='warning'>You can't put [equipping] on [source], it's stuck to your hand!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/// Start the equipping process. This is the proc you should yield in.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/datum/strippable_item/proc/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (warn_dangerous_clothing && isclothing(source))
|
||||
var/obj/item/clothing/clothing = source
|
||||
if(clothing.clothing_flags & DANGEROUS_OBJECT)
|
||||
source.visible_message(
|
||||
"<span class='danger'>[user] tries to put [equipping] on [source].</span>",
|
||||
"<span class='userdanger'>[user] tries to put [equipping] on you.</span>",
|
||||
ignored_mobs = user,
|
||||
)
|
||||
else
|
||||
source.visible_message(
|
||||
"<span class='notice'>[user] tries to put [equipping] on [source].</span>",
|
||||
"<span class='notice'>[user] tries to put [equipping] on you.</span>",
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
to_chat(user, "<span class='notice'>You try to put [equipping] on [source]...</span>")
|
||||
|
||||
var/log = "[key_name(source)] is having [equipping] put on them by [key_name(user)]"
|
||||
source.log_message(log, LOG_ATTACK, color="red")
|
||||
user.log_message(log, LOG_ATTACK, color="red", log_globally=FALSE)
|
||||
|
||||
return TRUE
|
||||
|
||||
/// The proc that places the item on the source. This should not yield.
|
||||
/datum/strippable_item/proc/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
/// Tries to unequip the item from the given source.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/// This should be used for checking if it CAN be unequipped.
|
||||
/// It should not perform the unequipping itself.
|
||||
/datum/strippable_item/proc/try_unequip(atom/source, mob/user)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
if (ismob(source))
|
||||
var/mob/mob_source = source
|
||||
if (!item.canStrip(user, mob_source))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Start the unequipping process. This is the proc you should yield in.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/datum/strippable_item/proc/start_unequip(atom/source, mob/user)
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
if (HAS_TRAIT(item, TRAIT_NO_STRIP))
|
||||
return FALSE
|
||||
|
||||
source.visible_message(
|
||||
"<span class='warning'>[user] tries to remove [source]'s [item].</span>",
|
||||
"<span class='userdanger'>[user] tries to remove your [item].</span>",
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
to_chat(user, "<span class='danger'>You try to remove [source]'s [item]...</span>")
|
||||
source.log_message("[key_name(source)] is being stripped of [item] by [key_name(src)]", LOG_ATTACK, color="red")
|
||||
user.log_message("[key_name(source)] is being stripped of [item] by [key_name(src)]", LOG_ATTACK, color="red", log_globally=FALSE)
|
||||
item.add_fingerprint(src)
|
||||
|
||||
return TRUE
|
||||
|
||||
/// The proc that unequips the item from the source. This should not yield.
|
||||
/datum/strippable_item/proc/finish_unequip(atom/source, mob/user)
|
||||
|
||||
/// Returns a STRIPPABLE_OBSCURING_* define to report on whether or not this is obscured.
|
||||
/datum/strippable_item/proc/get_obscuring(atom/source)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
return STRIPPABLE_OBSCURING_NONE
|
||||
|
||||
/// Returns the ID of this item's strippable action.
|
||||
/// Return `null` if there is no alternate action.
|
||||
/// Any return value of this must be in StripMenu.
|
||||
/datum/strippable_item/proc/get_alternate_action(atom/source, mob/user)
|
||||
return null
|
||||
|
||||
/// Performs an alternative action on this strippable_item.
|
||||
/// `has_alternate_action` needs to be TRUE.
|
||||
/datum/strippable_item/proc/alternate_action(atom/source, mob/user)
|
||||
|
||||
/// Returns whether or not this item should show.
|
||||
/datum/strippable_item/proc/should_show(atom/source, mob/user)
|
||||
return TRUE
|
||||
|
||||
/// A preset for equipping items onto mob slots
|
||||
/datum/strippable_item/mob_item_slot
|
||||
/// The ITEM_SLOT_* to equip to.
|
||||
var/item_slot
|
||||
|
||||
/datum/strippable_item/mob_item_slot/get_item(atom/source)
|
||||
if (!ismob(source))
|
||||
return null
|
||||
|
||||
var/mob/mob_source = source
|
||||
return mob_source.get_item_by_slot(item_slot)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
if (!equipping.mob_can_equip(
|
||||
source,
|
||||
user,
|
||||
item_slot,
|
||||
disable_warning = TRUE,
|
||||
bypass_equip_delay_self = TRUE,
|
||||
))
|
||||
to_chat(user, "<span class='warning'>\The [equipping] doesn't fit in that place!</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
if (!do_after(user, get_equip_delay(equipping), source))
|
||||
return FALSE
|
||||
|
||||
if (!equipping.mob_can_equip(
|
||||
source,
|
||||
user,
|
||||
item_slot,
|
||||
disable_warning = TRUE,
|
||||
bypass_equip_delay_self = TRUE,
|
||||
))
|
||||
return FALSE
|
||||
|
||||
if (!user.temporarilyRemoveItemFromInventory(equipping))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/mob_source = source
|
||||
mob_source.equip_to_slot(equipping, item_slot)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/get_obscuring(atom/source)
|
||||
if (iscarbon(source))
|
||||
var/mob/living/carbon/carbon_source = source
|
||||
return (carbon_source.check_obscured_slots() & item_slot) \
|
||||
? STRIPPABLE_OBSCURING_COMPLETELY \
|
||||
: STRIPPABLE_OBSCURING_NONE
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/start_unequip(atom/source, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
return start_unequip_mob(get_item(source), source, user)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/finish_unequip(atom/source, mob/user)
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
return finish_unequip_mob(item, source, user)
|
||||
|
||||
/// Returns the delay of equipping this item to a mob
|
||||
/datum/strippable_item/mob_item_slot/proc/get_equip_delay(obj/item/equipping)
|
||||
return equipping.equip_delay_other
|
||||
|
||||
/// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob.
|
||||
/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay)
|
||||
if (!do_after(user, strip_delay || item.strip_delay, source, interaction_key = REF(item)))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// A utility function for `/datum/strippable_item`s to finish unequipping an item from a mob.
|
||||
/proc/finish_unequip_mob(obj/item/item, mob/source, mob/user)
|
||||
if (!item.doStrip(user, source))
|
||||
return FALSE
|
||||
|
||||
source.log_message("[key_name(source)] has been stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red")
|
||||
user.log_message("[key_name(source)] has been stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red", log_globally=FALSE)
|
||||
|
||||
// Updates speed in case stripped speed affecting item
|
||||
source.update_movespeed()
|
||||
|
||||
/// A representation of the stripping UI
|
||||
/datum/strip_menu
|
||||
/// The owner who has the element /datum/element/strippable
|
||||
var/atom/movable/owner
|
||||
|
||||
/// The strippable element itself
|
||||
var/datum/element/strippable/strippable
|
||||
|
||||
/// A lazy list of user mobs to a list of strip menu keys that they're interacting with
|
||||
var/list/interactions
|
||||
|
||||
/datum/strip_menu/New(atom/movable/owner, datum/element/strippable/strippable)
|
||||
. = ..()
|
||||
src.owner = owner
|
||||
src.strippable = strippable
|
||||
|
||||
/datum/strip_menu/Destroy()
|
||||
owner = null
|
||||
strippable = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/strip_menu/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, "StripMenu")
|
||||
ui.open()
|
||||
|
||||
/datum/strip_menu/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/simple/inventory),
|
||||
)
|
||||
|
||||
/datum/strip_menu/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/items = list()
|
||||
|
||||
for (var/strippable_key in strippable.items)
|
||||
var/datum/strippable_item/item_data = strippable.items[strippable_key]
|
||||
|
||||
if (!item_data.should_show(owner, user))
|
||||
continue
|
||||
|
||||
var/list/result
|
||||
|
||||
if(strippable_key in LAZYACCESS(interactions, user))
|
||||
LAZYSET(result, "interacting", TRUE)
|
||||
|
||||
var/obscuring = item_data.get_obscuring(owner)
|
||||
if (obscuring != STRIPPABLE_OBSCURING_NONE)
|
||||
LAZYSET(result, "obscured", obscuring)
|
||||
items[strippable_key] = result
|
||||
continue
|
||||
|
||||
var/obj/item/item = item_data.get_item(owner)
|
||||
if (isnull(item) || (HAS_TRAIT(item, TRAIT_NO_STRIP)))
|
||||
items[strippable_key] = result
|
||||
continue
|
||||
|
||||
LAZYINITLIST(result)
|
||||
|
||||
result["icon"] = icon2base64(icon(item.icon, item.icon_state))
|
||||
result["name"] = item.name
|
||||
result["alternate"] = item_data.get_alternate_action(owner, user)
|
||||
|
||||
items[strippable_key] = result
|
||||
|
||||
data["items"] = items
|
||||
|
||||
// While most `\the`s are implicit, this one is not.
|
||||
// In this case, `\The` would otherwise be used.
|
||||
// This doesn't match with what it's used for, which is to say "Stripping the alien drone",
|
||||
// as opposed to "Stripping The alien drone".
|
||||
// Human names will still show without "the", as they are proper nouns.
|
||||
data["name"] = "\the [owner]"
|
||||
|
||||
return data
|
||||
|
||||
/datum/strip_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if (.)
|
||||
return
|
||||
|
||||
. = TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
switch (action)
|
||||
if ("use")
|
||||
var/key = params["key"]
|
||||
var/datum/strippable_item/strippable_item = strippable.items[key]
|
||||
|
||||
if (isnull(strippable_item))
|
||||
return
|
||||
|
||||
if (!strippable_item.should_show(owner, user))
|
||||
return
|
||||
|
||||
if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return
|
||||
|
||||
var/item = strippable_item.get_item(owner)
|
||||
if (isnull(item))
|
||||
var/obj/item/held_item = user.get_active_held_item()
|
||||
if (isnull(held_item))
|
||||
return
|
||||
|
||||
if (strippable_item.try_equip(owner, held_item, user))
|
||||
LAZYORASSOCLIST(interactions, user, key)
|
||||
|
||||
// Yielding call
|
||||
var/should_finish = strippable_item.start_equip(owner, held_item, user)
|
||||
|
||||
LAZYREMOVEASSOC(interactions, user, key)
|
||||
|
||||
if (!should_finish)
|
||||
return
|
||||
|
||||
if (QDELETED(src) || QDELETED(owner))
|
||||
return
|
||||
|
||||
// They equipped an item in the meantime
|
||||
if (!isnull(strippable_item.get_item(owner)))
|
||||
return
|
||||
|
||||
if (!user.Adjacent(owner))
|
||||
return
|
||||
|
||||
strippable_item.finish_equip(owner, held_item, user)
|
||||
else if (strippable_item.try_unequip(owner, user))
|
||||
LAZYORASSOCLIST(interactions, user, key)
|
||||
|
||||
var/should_unequip = strippable_item.start_unequip(owner, user)
|
||||
|
||||
LAZYREMOVEASSOC(interactions, user, key)
|
||||
|
||||
// Yielding call
|
||||
if (!should_unequip)
|
||||
return
|
||||
|
||||
if (QDELETED(src) || QDELETED(owner))
|
||||
return
|
||||
|
||||
// They changed the item in the meantime
|
||||
if (strippable_item.get_item(owner) != item)
|
||||
return
|
||||
|
||||
if (!user.Adjacent(owner))
|
||||
return
|
||||
|
||||
strippable_item.finish_unequip(owner, user)
|
||||
if ("alt")
|
||||
var/key = params["key"]
|
||||
var/datum/strippable_item/strippable_item = strippable.items[key]
|
||||
|
||||
if (isnull(strippable_item))
|
||||
return
|
||||
|
||||
if (!strippable_item.should_show(owner, user))
|
||||
return
|
||||
|
||||
if (strippable_item.get_obscuring(owner) == STRIPPABLE_OBSCURING_COMPLETELY)
|
||||
return
|
||||
|
||||
var/item = strippable_item.get_item(owner)
|
||||
if (isnull(item))
|
||||
return
|
||||
|
||||
if (isnull(strippable_item.get_alternate_action(owner, user)))
|
||||
return
|
||||
|
||||
LAZYORASSOCLIST(interactions, user, key)
|
||||
|
||||
// Potentially yielding
|
||||
strippable_item.alternate_action(owner, user)
|
||||
|
||||
LAZYREMOVEASSOC(interactions, user, key)
|
||||
|
||||
/datum/strip_menu/ui_host(mob/user)
|
||||
return owner
|
||||
|
||||
/datum/strip_menu/ui_status(mob/user, datum/ui_state/state)
|
||||
. = ..()
|
||||
|
||||
if (isliving(user))
|
||||
var/mob/living/living_user = user
|
||||
|
||||
if (
|
||||
. == UI_UPDATE \
|
||||
&& user.stat == CONSCIOUS \
|
||||
&& living_user.body_position == LYING_DOWN \
|
||||
&& user.Adjacent(owner)
|
||||
)
|
||||
return UI_INTERACTIVE
|
||||
|
||||
/// Creates an assoc list of keys to /datum/strippable_item
|
||||
/proc/create_strippable_list(types)
|
||||
var/list/strippable_items = list()
|
||||
|
||||
for (var/strippable_type in types)
|
||||
var/datum/strippable_item/strippable_item = new strippable_type
|
||||
strippable_items[strippable_item.key] = strippable_item
|
||||
|
||||
return strippable_items
|
||||
@@ -1038,7 +1038,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
/obj/item/proc/canStrip(mob/stripper, mob/owner)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return !HAS_TRAIT(src, TRAIT_NODROP)
|
||||
return !HAS_TRAIT(src, TRAIT_NODROP) && !(item_flags & ABSTRACT)
|
||||
|
||||
/obj/item/proc/doStrip(mob/stripper, mob/owner)
|
||||
return owner.dropItemToGround(src)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30)
|
||||
addtimer(CALLBACK(user, TYPE_PROC_REF(/mob/living, dropItemToGround), src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
|
||||
|
||||
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
@@ -97,7 +97,7 @@
|
||||
max_heat_protection_temperature = initial(max_heat_protection_temperature)
|
||||
min_cold_protection_temperature = initial(min_cold_protection_temperature)
|
||||
|
||||
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
@@ -160,7 +160,7 @@
|
||||
max_heat_protection_temperature = initial(max_heat_protection_temperature)
|
||||
min_cold_protection_temperature = initial(min_cold_protection_temperature)
|
||||
|
||||
/obj/item/clothing/gloves/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/gloves/clockwork/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
@@ -210,7 +210,7 @@
|
||||
else
|
||||
clothing_flags &= ~NOSLIP
|
||||
|
||||
/obj/item/clothing/shoes/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/shoes/clockwork/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
@@ -427,7 +427,7 @@
|
||||
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
|
||||
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
|
||||
continue
|
||||
#endif
|
||||
@@ -481,7 +481,7 @@
|
||||
I.Blend(c, ICON_MULTIPLY)
|
||||
|
||||
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
|
||||
|
||||
|
||||
if(!sprites[imgid])
|
||||
Insert(imgid, I)
|
||||
|
||||
@@ -720,3 +720,24 @@
|
||||
//glass door no overlay
|
||||
icon = icon(airlocks[airlock_name] , "closed" , SOUTH)
|
||||
Insert(sanitize_css_class_name("[airlock_name]Glass"), icon)
|
||||
|
||||
/datum/asset/simple/inventory
|
||||
assets = list(
|
||||
"inventory-glasses.png" = 'icons/UI_Icons/inventory_midnight/glasses.png',
|
||||
"inventory-head.png" = 'icons/UI_Icons/inventory_midnight/head.png',
|
||||
"inventory-neck.png" = 'icons/UI_Icons/inventory_midnight/neck.png',
|
||||
"inventory-mask.png" = 'icons/UI_Icons/inventory_midnight/mask.png',
|
||||
"inventory-ears.png" = 'icons/UI_Icons/inventory_midnight/ears.png',
|
||||
"inventory-uniform.png" = 'icons/UI_Icons/inventory_midnight/uniform.png',
|
||||
"inventory-suit.png" = 'icons/UI_Icons/inventory_midnight/suit.png',
|
||||
"inventory-gloves.png" = 'icons/UI_Icons/inventory_midnight/gloves.png',
|
||||
"inventory-hand_l.png" = 'icons/UI_Icons/inventory_midnight/hand_l.png',
|
||||
"inventory-hand_r.png" = 'icons/UI_Icons/inventory_midnight/hand_r.png',
|
||||
"inventory-shoes.png" = 'icons/UI_Icons/inventory_midnight/shoes.png',
|
||||
"inventory-suit_storage.png" = 'icons/UI_Icons/inventory_midnight/suit_storage.png',
|
||||
"inventory-id.png" = 'icons/UI_Icons/inventory_midnight/id.png',
|
||||
"inventory-belt.png" = 'icons/UI_Icons/inventory_midnight/belt.png',
|
||||
"inventory-back.png" = 'icons/UI_Icons/inventory_midnight/back.png',
|
||||
"inventory-pocket.png" = 'icons/UI_Icons/inventory_midnight/pocket.png',
|
||||
"inventory-collar.png" = 'icons/UI_Icons/inventory_midnight/collar.png',
|
||||
)
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
.= ..()
|
||||
AddComponent(/datum/component/squeak, list('sound/effects/collarbell1.ogg'=1,'sound/effects/collarbell2.ogg'=1), 50, 100, 2)
|
||||
|
||||
/obj/item/clothing/neck/petcollar/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/neck/petcollar/mob_can_equip(mob/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(ishuman(M))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -743,7 +743,7 @@
|
||||
armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 60, ACID = 30, ELECTRIC = 100)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/clown
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot)
|
||||
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(!..() || !ishuman(M))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
@@ -330,7 +330,7 @@
|
||||
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP) && !force)
|
||||
return FALSE
|
||||
|
||||
|
||||
if((SEND_SIGNAL(I, COMSIG_ITEM_PRE_UNEQUIP, force, newloc, no_move, invdrop, silent) & COMPONENT_ITEM_BLOCK_UNEQUIP) && !force)
|
||||
return FALSE
|
||||
|
||||
@@ -407,14 +407,13 @@
|
||||
|
||||
|
||||
/mob/living/carbon/proc/check_obscured_slots(transparent_protection)
|
||||
var/list/obscured = list()
|
||||
var/obscured = NONE
|
||||
var/hidden_slots = NONE
|
||||
|
||||
for(var/obj/item/I in get_equipped_items())
|
||||
hidden_slots |= I.flags_inv
|
||||
hidden_slots |= I.flags_prot
|
||||
for(var/obj/item/equipped_item in get_equipped_items())
|
||||
hidden_slots |= equipped_item.flags_inv
|
||||
if(transparent_protection)
|
||||
hidden_slots |= I.transparent_protection
|
||||
hidden_slots |= equipped_item.transparent_protection
|
||||
|
||||
if(hidden_slots & HIDENECK)
|
||||
obscured |= ITEM_SLOT_NECK
|
||||
@@ -462,7 +461,7 @@
|
||||
to_chat(M, span_warning("You are unable to equip that!"))
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
/mob/verb/quick_equip()
|
||||
set name = "quick-equip"
|
||||
set hidden = TRUE
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
|
||||
limb_destroyer = 1
|
||||
hud_type = /datum/hud/alien
|
||||
var/obj/item/r_store = null
|
||||
var/obj/item/l_store = null
|
||||
var/caste = ""
|
||||
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
|
||||
var/leap_on_click = 0
|
||||
@@ -18,49 +16,16 @@
|
||||
bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien,
|
||||
/obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien)
|
||||
|
||||
GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list(
|
||||
/datum/strippable_item/hand/left,
|
||||
/datum/strippable_item/hand/right,
|
||||
/datum/strippable_item/mob_item_slot/handcuffs,
|
||||
/datum/strippable_item/mob_item_slot/legcuffs,
|
||||
)))
|
||||
|
||||
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
|
||||
return handcuffed
|
||||
|
||||
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
var/list/dat = list()
|
||||
dat += {"
|
||||
<HTML><HEAD><meta charset='UTF-8'></HEAD><BODY>
|
||||
<HR>
|
||||
<span class='big bold'>[name]</span>
|
||||
<HR>"}
|
||||
for(var/i in 1 to held_items.len)
|
||||
var/obj/item/I = get_item_for_held_index(i)
|
||||
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=[REF(src)];item=[ITEM_SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a>"
|
||||
dat += "<BR><A href='?src=[REF(src)];pouches=1'>Empty Pouches</A>"
|
||||
|
||||
if(handcuffed)
|
||||
dat += "<BR><A href='?src=[REF(src)];item=[ITEM_SLOT_HANDCUFFED]'>Handcuffed</A>"
|
||||
if(legcuffed)
|
||||
dat += "<BR><A href='?src=[REF(src)];item=[ITEM_SLOT_LEGCUFFED]'>Legcuffed</A>"
|
||||
|
||||
dat += {"
|
||||
<BR>
|
||||
<BR><A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
|
||||
</BODY></HTML>
|
||||
"}
|
||||
user << browse(dat.Join(), "window=mob[REF(src)];size=325x500")
|
||||
onclose(user, "mob[REF(src)]")
|
||||
|
||||
|
||||
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
|
||||
//strip panel
|
||||
if(href_list["pouches"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
visible_message(span_danger("[usr] tries to empty [src]'s pouches."), \
|
||||
span_userdanger("[usr] tries to empty [src]'s pouches."))
|
||||
if(do_after(usr, POCKET_STRIP_DELAY * 0.5, src))
|
||||
dropItemToGround(r_store)
|
||||
dropItemToGround(l_store)
|
||||
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
|
||||
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
|
||||
..(I, cuff_break = INSTANT_CUFFBREAK)
|
||||
|
||||
@@ -53,9 +53,6 @@
|
||||
// now constructs damage icon for each organ from mask * damage field
|
||||
|
||||
|
||||
/mob/living/carbon/alien/larva/show_inv(mob/user)
|
||||
return
|
||||
|
||||
/mob/living/carbon/alien/larva/toggle_throw_mode()
|
||||
return
|
||||
|
||||
|
||||
@@ -214,68 +214,8 @@
|
||||
return 0
|
||||
|
||||
|
||||
/mob/living/carbon/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
var/dat = {"
|
||||
<HTML><HEAD><meta charset='UTF-8'></HEAD><BODY>
|
||||
<HR>
|
||||
<B><FONT size=3>[name]</FONT></B>
|
||||
<HR>
|
||||
<BR><B>Head:</B> <A href='?src=[REF(src)];item=[ITEM_SLOT_HEAD]'>[(head && !(head.item_flags & ABSTRACT)) ? head : "Nothing"]</A>"}
|
||||
|
||||
var/list/obscured = check_obscured_slots()
|
||||
|
||||
if(ITEM_SLOT_NECK in obscured)
|
||||
dat += "<BR><B>Neck:</B> Obscured"
|
||||
else
|
||||
dat += "<BR><B>Neck:</B> <A href='?src=[REF(src)];item=[ITEM_SLOT_NECK]'>[(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? (wear_neck) : "Nothing"]</A>"
|
||||
|
||||
if(ITEM_SLOT_MASK in obscured)
|
||||
dat += "<BR><B>Mask:</B> Obscured"
|
||||
else
|
||||
dat += "<BR><B>Mask:</B> <A href='?src=[REF(src)];item=[ITEM_SLOT_MASK]'>[(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "Nothing"]</a>"
|
||||
|
||||
for(var/i in 1 to held_items.len)
|
||||
var/obj/item/I = get_item_for_held_index(i)
|
||||
dat += "<BR><B>[get_held_index_name(i)]:</B> </td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "Nothing"]</a>"
|
||||
|
||||
dat += "<BR><B>Back:</B> <A href='?src=[REF(src)];item=[ITEM_SLOT_BACK]'>[back ? back : "Nothing"]</A>"
|
||||
|
||||
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
|
||||
dat += "<BR><A href='?src=[REF(src)];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
||||
|
||||
if(handcuffed)
|
||||
dat += "<BR><A href='?src=[REF(src)];item=[ITEM_SLOT_HANDCUFFED]'>Handcuffed</A>"
|
||||
if(legcuffed)
|
||||
dat += "<BR><A href='?src=[REF(src)];item=[ITEM_SLOT_LEGCUFFED]'>Legcuffed</A>"
|
||||
|
||||
dat += {"
|
||||
<BR>
|
||||
<BR><A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
|
||||
</BODY></HTML>
|
||||
"}
|
||||
user << browse(dat, "window=mob[REF(src)];size=325x500")
|
||||
onclose(user, "mob[REF(src)]")
|
||||
|
||||
/mob/living/carbon/Topic(href, href_list)
|
||||
..()
|
||||
//strip panel
|
||||
if(href_list["internal"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
var/slot = text2num(href_list["internal"])
|
||||
var/obj/item/ITEM = get_item_by_slot(slot)
|
||||
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & MASKINTERNALS))
|
||||
visible_message(span_danger("[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name]."), \
|
||||
span_userdanger("[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name]."))
|
||||
if(do_after(usr, POCKET_STRIP_DELAY, src, interaction_key = REF(ITEM)))
|
||||
if(internal)
|
||||
cutoff_internals()
|
||||
else if(ITEM && istype(ITEM, /obj/item/tank))
|
||||
if((wear_mask && (wear_mask.clothing_flags & MASKINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
open_internals(ITEM)
|
||||
|
||||
visible_message(span_danger("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name]."), \
|
||||
span_userdanger("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name]."))
|
||||
|
||||
// Embed Stuff
|
||||
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
|
||||
|
||||
132
code/modules/mob/living/carbon/carbon_stripping.dm
Normal file
@@ -0,0 +1,132 @@
|
||||
/datum/strippable_item/mob_item_slot/head
|
||||
key = STRIPPABLE_ITEM_HEAD
|
||||
item_slot = ITEM_SLOT_HEAD
|
||||
|
||||
/datum/strippable_item/mob_item_slot/back
|
||||
key = STRIPPABLE_ITEM_BACK
|
||||
item_slot = ITEM_SLOT_BACK
|
||||
|
||||
/datum/strippable_item/mob_item_slot/back/get_alternate_action(atom/source, mob/user)
|
||||
return get_strippable_alternate_action_internals(get_item(source), source)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/mask
|
||||
key = STRIPPABLE_ITEM_MASK
|
||||
item_slot = ITEM_SLOT_MASK
|
||||
|
||||
/datum/strippable_item/mob_item_slot/neck
|
||||
key = STRIPPABLE_ITEM_NECK
|
||||
item_slot = ITEM_SLOT_NECK
|
||||
|
||||
/datum/strippable_item/mob_item_slot/handcuffs
|
||||
key = STRIPPABLE_ITEM_HANDCUFFS
|
||||
item_slot = ITEM_SLOT_HANDCUFFED
|
||||
|
||||
/datum/strippable_item/mob_item_slot/handcuffs/should_show(atom/source, mob/user)
|
||||
if (!iscarbon(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/carbon_source = source
|
||||
return !isnull(carbon_source.handcuffed)
|
||||
|
||||
// You shouldn't be able to equip things to handcuff slots.
|
||||
/datum/strippable_item/mob_item_slot/handcuffs/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
return FALSE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/legcuffs
|
||||
key = STRIPPABLE_ITEM_LEGCUFFS
|
||||
item_slot = ITEM_SLOT_LEGCUFFED
|
||||
|
||||
/datum/strippable_item/mob_item_slot/legcuffs/should_show(atom/source, mob/user)
|
||||
if (!iscarbon(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/carbon_source = source
|
||||
return !isnull(carbon_source.legcuffed)
|
||||
|
||||
// You shouldn't be able to equip things to legcuff slots.
|
||||
/datum/strippable_item/mob_item_slot/legcuffs/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
return FALSE
|
||||
|
||||
/// A strippable item for a hand
|
||||
/datum/strippable_item/hand
|
||||
// Putting dangerous clothing in our hand is fine.
|
||||
warn_dangerous_clothing = FALSE
|
||||
|
||||
/// Which hand?
|
||||
var/hand_index
|
||||
|
||||
/datum/strippable_item/hand/get_item(atom/source)
|
||||
if (!ismob(source))
|
||||
return null
|
||||
|
||||
var/mob/mob_source = source
|
||||
return mob_source.get_item_for_held_index(hand_index)
|
||||
|
||||
/datum/strippable_item/hand/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/mob_source = source
|
||||
|
||||
if (!mob_source.can_put_in_hand(equipping, hand_index))
|
||||
to_chat(src, "<span class='warning'>\The [equipping] doesn't fit in that place!</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/hand/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/mob_source = source
|
||||
|
||||
if (!do_after(user, equipping.equip_delay_other, source))
|
||||
return FALSE
|
||||
|
||||
if (!mob_source.can_put_in_hand(equipping, hand_index))
|
||||
return FALSE
|
||||
|
||||
if (!user.temporarilyRemoveItemFromInventory(equipping))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/hand/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (!iscarbon(source))
|
||||
return FALSE
|
||||
|
||||
var/mob/mob_source = source
|
||||
mob_source.put_in_hand(equipping, hand_index)
|
||||
|
||||
/datum/strippable_item/hand/start_unequip(atom/source, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
return start_unequip_mob(get_item(source), source, user)
|
||||
|
||||
/datum/strippable_item/hand/finish_unequip(atom/source, mob/user)
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
if (!ismob(source))
|
||||
return FALSE
|
||||
|
||||
return finish_unequip_mob(item, source, user)
|
||||
|
||||
/datum/strippable_item/hand/left
|
||||
key = STRIPPABLE_ITEM_LHAND
|
||||
hand_index = 1
|
||||
|
||||
/datum/strippable_item/hand/right
|
||||
key = STRIPPABLE_ITEM_RHAND
|
||||
hand_index = 2
|
||||
@@ -36,6 +36,7 @@
|
||||
AddComponent(/datum/component/personal_crafting)
|
||||
AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
|
||||
AddComponent(/datum/component/bloodysoles/feet, FOOTPRINT_SPRITE_SHOES)
|
||||
AddElement(/datum/element/strippable, GLOB.strippable_human_items, TYPE_PROC_REF(/mob/living/carbon/human,should_strip))
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
||||
)
|
||||
@@ -153,115 +154,6 @@
|
||||
. += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]"
|
||||
|
||||
|
||||
/mob/living/carbon/human/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask)
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/list/dat = list()
|
||||
|
||||
dat += "<table>"
|
||||
for(var/i in 1 to held_items.len)
|
||||
var/obj/item/I = get_item_for_held_index(i)
|
||||
dat += "<tr><td><B>[get_held_index_name(i)]:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_HANDS];hand_index=[i]'>[(I && !(I.item_flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a></td></tr>"
|
||||
dat += "<tr><td> </td></tr>"
|
||||
|
||||
dat += "<tr><td><B>Back:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_BACK]'>[(back && !(back.item_flags & ABSTRACT)) ? back : "<font color=grey>Empty</font>"]</A>"
|
||||
if(has_breathable_mask && istype(back, /obj/item/tank))
|
||||
dat += " <A href='?src=[REF(src)];internal=[ITEM_SLOT_BACK]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
||||
|
||||
dat += "</td></tr><tr><td> </td></tr>"
|
||||
|
||||
dat += "<tr><td><B>Head:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_HEAD]'>[(head && !(head.item_flags & ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_MASK in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Mask:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_MASK]'>[(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_NECK in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Neck:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Neck:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_NECK]'>[(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_EYES in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Eyes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Eyes:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_EYES]'>[(glasses && !(glasses.item_flags & ABSTRACT)) ? glasses : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_EARS in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Ears:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Ears:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_EARS]'>[(ears && !(ears.item_flags & ABSTRACT)) ? ears : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
dat += "<tr><td> </td></tr>"
|
||||
|
||||
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_OCLOTHING]'>[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
if(wear_suit)
|
||||
if(ITEM_SLOT_SUITSTORE in obscured)
|
||||
dat += "<tr><td><font color=grey> ↳<B>Suit Storage:</B></font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td> ↳<B>Suit Storage:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_SUITSTORE]'>[(s_store && !(s_store.item_flags & ABSTRACT)) ? s_store : "<font color=grey>Empty</font>"]</A>"
|
||||
if(has_breathable_mask && istype(s_store, /obj/item/tank))
|
||||
dat += " <A href='?src=[REF(src)];internal=[ITEM_SLOT_SUITSTORE]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
||||
dat += "</td></tr>"
|
||||
else
|
||||
dat += "<tr><td><font color=grey> ↳<B>Suit Storage:</B></font></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_FEET in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Shoes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Shoes:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_FEET]'>[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_GLOVES in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Gloves:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Gloves:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_GLOVES]'>[(gloves && !(gloves.item_flags & ABSTRACT)) ? gloves : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
if(ITEM_SLOT_ICLOTHING in obscured)
|
||||
dat += "<tr><td><font color=grey><B>Uniform:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><B>Uniform:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_ICLOTHING]'>[(w_uniform && !(w_uniform.item_flags & ABSTRACT)) ? w_uniform : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
|
||||
// Yogs start - taking an axe at this stupid handmade-HTML garbo code
|
||||
var/obj/item/bodypart/chest = get_bodypart(BODY_ZONE_CHEST) // This is a lil verbose but the lint demands it
|
||||
var/is_ipc_or_something = (chest?.status == BODYPART_ROBOTIC)
|
||||
var/can_be_nakey = is_ipc_or_something || (dna && dna.species.nojumpsuit)
|
||||
if((ITEM_SLOT_ICLOTHING in obscured) || (w_uniform == null && !can_be_nakey))
|
||||
dat += "<tr><td><font color=grey> ↳<B>Pockets:</B></font></td></tr>"
|
||||
dat += "<tr><td><font color=grey> ↳<B>ID:</B></font></td></tr>"
|
||||
dat += "<tr><td><font color=grey> ↳<B>Belt:</B></font></td></tr>"
|
||||
else
|
||||
var/funny_arrow_character = ""
|
||||
if(!can_be_nakey) // The funny arrow only really makes sense if this creature *needs* the uniform in order to hold these things.
|
||||
// Less so when we're an IPC or something.
|
||||
funny_arrow_character = " ↳"
|
||||
dat += "<tr><td>[funny_arrow_character]<B>Belt:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_BELT]'>[(belt && !(belt.item_flags & ABSTRACT)) ? belt : "<font color=grey>Empty</font>"]</A>"
|
||||
if(has_breathable_mask && istype(belt, /obj/item/tank))
|
||||
dat += " <A href='?src=[REF(src)];internal=[ITEM_SLOT_BELT]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
||||
dat += "</td></tr>"
|
||||
dat += "<tr><td>[funny_arrow_character]<B>Pockets:</B></td><td><A href='?src=[REF(src)];pockets=left'>[(l_store && !(l_store.item_flags & ABSTRACT)) ? "Left (Full)" : "<font color=grey>Left (Empty)</font>"]</A>"
|
||||
dat += " <A href='?src=[REF(src)];pockets=right'>[(r_store && !(r_store.item_flags & ABSTRACT)) ? "Right (Full)" : "<font color=grey>Right (Empty)</font>"]</A></td></tr>"
|
||||
dat += "<tr><td>[funny_arrow_character]<B>ID:</B></td><td><A href='?src=[REF(src)];item=[ITEM_SLOT_ID]'>[(wear_id && !(wear_id.item_flags & ABSTRACT)) ? wear_id : "<font color=grey>Empty</font>"]</A></td></tr>"
|
||||
// Yogs end - garbo code axe
|
||||
// yogs start - show bandaged parts
|
||||
for (var/obj/item/bodypart/org in bodyparts)
|
||||
if (org.bandaged)
|
||||
dat += "<tr><td><i>[org.name]</i> wrapped with:</td><td><a href='byond://?src=\ref[src];unwrap=\ref[org.bandaged]'>[org.bandaged]</a></td></tr>"
|
||||
// yogs end
|
||||
|
||||
if(handcuffed)
|
||||
dat += "<tr><td><B>Handcuffed:</B> <A href='?src=[REF(src)];item=[ITEM_SLOT_HANDCUFFED]'>Remove</A></td></tr>"
|
||||
if(legcuffed)
|
||||
dat += "<tr><td><A href='?src=[REF(src)];item=[ITEM_SLOT_LEGCUFFED]'>Legcuffed</A></td></tr>"
|
||||
|
||||
dat += {"</table>
|
||||
<A href='?src=[REF(user)];mach_close=mob[REF(src)]'>Close</A>
|
||||
"}
|
||||
|
||||
var/datum/browser/popup = new(user, "mob[REF(src)]", "[src]", 440, 510)
|
||||
popup.set_content(dat.Join())
|
||||
popup.open()
|
||||
|
||||
// called when something steps onto a human
|
||||
// this could be made more general, but for now just handle mulebot
|
||||
/mob/living/carbon/human/proc/on_entered(datum/source, atom/movable/AM, ...)
|
||||
@@ -307,40 +199,6 @@
|
||||
to_chat(usr, span_warning("You can't reach that! Something is covering it."))
|
||||
return
|
||||
|
||||
if(href_list["pockets"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) //TODO: Make it match (or intergrate it into) strippanel so you get 'item cannot fit here' warnings if mob_can_equip fails
|
||||
var/pocket_side = href_list["pockets"]
|
||||
var/pocket_id = (pocket_side == "right" ? ITEM_SLOT_RPOCKET : ITEM_SLOT_LPOCKET)
|
||||
var/obj/item/pocket_item = (pocket_id == ITEM_SLOT_RPOCKET ? r_store : l_store)
|
||||
var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty
|
||||
|
||||
var/delay_denominator = 1
|
||||
if(pocket_item && !(pocket_item.item_flags & ABSTRACT))
|
||||
if(HAS_TRAIT(pocket_item, TRAIT_NODROP))
|
||||
to_chat(usr, span_warning("You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!"))
|
||||
to_chat(usr, span_notice("You try to empty [src]'s [pocket_side] pocket."))
|
||||
else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.item_flags & ABSTRACT))
|
||||
to_chat(usr, span_notice("You try to place [place_item] into [src]'s [pocket_side] pocket."))
|
||||
delay_denominator = 4
|
||||
else
|
||||
return
|
||||
|
||||
if(do_after(usr, POCKET_STRIP_DELAY/delay_denominator, src, interaction_key = REF(pocket_item))) //placing an item into the pocket is 4 times faster
|
||||
if(pocket_item)
|
||||
if(pocket_item == (pocket_id == ITEM_SLOT_RPOCKET ? r_store : l_store)) //item still in the pocket we search
|
||||
dropItemToGround(pocket_item)
|
||||
if(usr.IsAdvancedToolUser())
|
||||
usr.put_in_hands(pocket_item)
|
||||
else
|
||||
if(place_item)
|
||||
if(place_item.mob_can_equip(src, usr, pocket_id, FALSE, TRUE))
|
||||
usr.temporarilyRemoveItemFromInventory(place_item, TRUE)
|
||||
equip_to_slot(place_item, pocket_id, TRUE)
|
||||
//do nothing otherwise
|
||||
//updating inv screen after handled by living/Topic()
|
||||
else
|
||||
// Display a warning if the user mocks up
|
||||
to_chat(src, span_warning("You feel your [pocket_side] pocket being fumbled with!"))
|
||||
|
||||
///////HUDs///////
|
||||
if(href_list["hud"])
|
||||
if(ishuman(usr))
|
||||
|
||||
215
code/modules/mob/living/carbon/human/human_stripping.dm
Normal file
@@ -0,0 +1,215 @@
|
||||
#define INTERNALS_TOGGLE_DELAY (4 SECONDS)
|
||||
#define POCKET_EQUIP_DELAY (1 SECONDS)
|
||||
|
||||
GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
|
||||
/datum/strippable_item/mob_item_slot/head,
|
||||
/datum/strippable_item/mob_item_slot/back,
|
||||
/datum/strippable_item/mob_item_slot/mask,
|
||||
/datum/strippable_item/mob_item_slot/neck,
|
||||
/datum/strippable_item/mob_item_slot/eyes,
|
||||
/datum/strippable_item/mob_item_slot/ears,
|
||||
/datum/strippable_item/mob_item_slot/jumpsuit,
|
||||
/datum/strippable_item/mob_item_slot/suit,
|
||||
/datum/strippable_item/mob_item_slot/gloves,
|
||||
/datum/strippable_item/mob_item_slot/feet,
|
||||
/datum/strippable_item/mob_item_slot/suit_storage,
|
||||
/datum/strippable_item/mob_item_slot/id,
|
||||
/datum/strippable_item/mob_item_slot/belt,
|
||||
/datum/strippable_item/mob_item_slot/pocket/left,
|
||||
/datum/strippable_item/mob_item_slot/pocket/right,
|
||||
/datum/strippable_item/hand/left,
|
||||
/datum/strippable_item/hand/right,
|
||||
/datum/strippable_item/mob_item_slot/handcuffs,
|
||||
/datum/strippable_item/mob_item_slot/legcuffs,
|
||||
)))
|
||||
|
||||
/mob/living/carbon/human/proc/should_strip(mob/user)
|
||||
if (user.pulling != src || user.grab_state != GRAB_AGGRESSIVE)
|
||||
return TRUE
|
||||
|
||||
if (ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
return !human_user.can_be_firemanned(src)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/eyes
|
||||
key = STRIPPABLE_ITEM_EYES
|
||||
item_slot = ITEM_SLOT_EYES
|
||||
|
||||
/datum/strippable_item/mob_item_slot/ears
|
||||
key = STRIPPABLE_ITEM_EARS
|
||||
item_slot = ITEM_SLOT_EARS
|
||||
|
||||
/datum/strippable_item/mob_item_slot/jumpsuit
|
||||
key = STRIPPABLE_ITEM_JUMPSUIT
|
||||
item_slot = ITEM_SLOT_ICLOTHING
|
||||
|
||||
/datum/strippable_item/mob_item_slot/jumpsuit/get_alternate_action(atom/source, mob/user)
|
||||
var/obj/item/clothing/under/jumpsuit = get_item(source)
|
||||
if (!istype(jumpsuit))
|
||||
return null
|
||||
return jumpsuit?.can_adjust ? "adjust_jumpsuit" : null
|
||||
|
||||
/datum/strippable_item/mob_item_slot/jumpsuit/alternate_action(atom/source, mob/user)
|
||||
var/obj/item/clothing/under/jumpsuit = get_item(source)
|
||||
if (!istype(jumpsuit))
|
||||
return null
|
||||
to_chat(source, "<span class='notice'>[user] is trying to adjust your [jumpsuit.name].")
|
||||
if (!do_after(user, jumpsuit.strip_delay * 0.5, source))
|
||||
return
|
||||
to_chat(source, "<span class='notice'>[user] successfully adjusted your [jumpsuit.name].")
|
||||
jumpsuit.toggle_jumpsuit_adjust()
|
||||
|
||||
if (!ismob(source))
|
||||
return
|
||||
|
||||
var/mob/mob_source = source
|
||||
mob_source.update_inv_w_uniform()
|
||||
mob_source.update_body()
|
||||
|
||||
/datum/strippable_item/mob_item_slot/suit
|
||||
key = STRIPPABLE_ITEM_SUIT
|
||||
item_slot = ITEM_SLOT_OCLOTHING
|
||||
|
||||
/datum/strippable_item/mob_item_slot/gloves
|
||||
key = STRIPPABLE_ITEM_GLOVES
|
||||
item_slot = ITEM_SLOT_GLOVES
|
||||
|
||||
/datum/strippable_item/mob_item_slot/feet
|
||||
key = STRIPPABLE_ITEM_FEET
|
||||
item_slot = ITEM_SLOT_FEET
|
||||
|
||||
/datum/strippable_item/mob_item_slot/feet/get_alternate_action(atom/source, mob/user)
|
||||
return null
|
||||
|
||||
/datum/strippable_item/mob_item_slot/feet/alternate_action(atom/source, mob/user)
|
||||
return
|
||||
|
||||
/datum/strippable_item/mob_item_slot/suit_storage
|
||||
key = STRIPPABLE_ITEM_SUIT_STORAGE
|
||||
item_slot = ITEM_SLOT_SUITSTORE
|
||||
|
||||
/datum/strippable_item/mob_item_slot/suit_storage/get_alternate_action(atom/source, mob/user)
|
||||
return get_strippable_alternate_action_internals(get_item(source), source)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/suit_storage/alternate_action(atom/source, mob/user)
|
||||
return strippable_alternate_action_internals(get_item(source), source, user)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/id
|
||||
key = STRIPPABLE_ITEM_ID
|
||||
item_slot = ITEM_SLOT_ID
|
||||
|
||||
/datum/strippable_item/mob_item_slot/belt
|
||||
key = STRIPPABLE_ITEM_BELT
|
||||
item_slot = ITEM_SLOT_BELT
|
||||
|
||||
/datum/strippable_item/mob_item_slot/belt/get_alternate_action(atom/source, mob/user)
|
||||
return get_strippable_alternate_action_internals(get_item(source), source)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/belt/alternate_action(atom/source, mob/user)
|
||||
return strippable_alternate_action_internals(get_item(source), source, user)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket
|
||||
/// Which pocket we're referencing. Used for visible text.
|
||||
var/pocket_side
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/get_obscuring(atom/source)
|
||||
return isnull(get_item(source)) \
|
||||
? STRIPPABLE_OBSCURING_NONE \
|
||||
: STRIPPABLE_OBSCURING_HIDDEN
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/get_equip_delay(obj/item/equipping)
|
||||
return POCKET_EQUIP_DELAY
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
warn_owner(source)
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/start_unequip(atom/source, mob/user)
|
||||
var/obj/item/item = get_item(source)
|
||||
if (isnull(item))
|
||||
return FALSE
|
||||
|
||||
to_chat(user, "<span class='notice'>You try to empty [source]'s [pocket_side] pocket.</span>")
|
||||
|
||||
var/log_message = "[key_name(source)] is being pickpocketed of [item] by [key_name(user)] ([pocket_side])"
|
||||
source.log_message(log_message, LOG_ATTACK, color="red")
|
||||
user.log_message(log_message, LOG_ATTACK, color="red", log_globally=FALSE)
|
||||
item.add_fingerprint(src)
|
||||
|
||||
var/result = start_unequip_mob(item, source, user, POCKET_STRIP_DELAY)
|
||||
|
||||
if (!result)
|
||||
warn_owner(source)
|
||||
|
||||
return result
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/proc/warn_owner(atom/owner)
|
||||
to_chat(owner, "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>")
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/left
|
||||
key = STRIPPABLE_ITEM_LPOCKET
|
||||
item_slot = ITEM_SLOT_LPOCKET
|
||||
pocket_side = "left"
|
||||
|
||||
/datum/strippable_item/mob_item_slot/pocket/right
|
||||
key = STRIPPABLE_ITEM_RPOCKET
|
||||
item_slot = ITEM_SLOT_RPOCKET
|
||||
pocket_side = "right"
|
||||
|
||||
/proc/get_strippable_alternate_action_internals(obj/item/item, atom/source)
|
||||
if (!iscarbon(source))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/carbon_source = source
|
||||
|
||||
var/obj/item/clothing/mask = carbon_source.wear_mask
|
||||
if (!istype(mask))
|
||||
return
|
||||
|
||||
if ((mask.clothing_flags & MASKINTERNALS) && istype(item, /obj/item/tank))
|
||||
return isnull(carbon_source.internal) ? "enable_internals" : "disable_internals"
|
||||
|
||||
/proc/strippable_alternate_action_internals(obj/item/item, atom/source, mob/user)
|
||||
var/obj/item/tank/tank = item
|
||||
if (!istype(tank))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/carbon_source = source
|
||||
if (!istype(carbon_source))
|
||||
return
|
||||
|
||||
var/obj/item/clothing/mask = carbon_source.wear_mask
|
||||
if (!istype(mask) || !(mask.clothing_flags & MASKINTERNALS))
|
||||
return
|
||||
|
||||
carbon_source.visible_message(
|
||||
"<span class='danger'>[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name].</span>",
|
||||
"<span class='userdanger'>[user] tries to [isnull(carbon_source.internal) ? "open": "close"] the valve on your [item.name].</span>",
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
to_chat(user, "<span class='notice'>You try to [isnull(carbon_source.internal) ? "open": "close"] the valve on [source]'s [item.name]...</span>")
|
||||
|
||||
if(!do_after(user, INTERNALS_TOGGLE_DELAY, carbon_source))
|
||||
return
|
||||
|
||||
if(carbon_source.internal)
|
||||
carbon_source.close_internals()
|
||||
// This isn't meant to be FALSE, it correlates to the icon's name.
|
||||
else if (!QDELETED(item))
|
||||
if(!carbon_source.try_open_internals(item))
|
||||
return
|
||||
|
||||
carbon_source.visible_message(
|
||||
span_danger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on [source]'s [item.name]."),
|
||||
span_userdanger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on your [item.name]."),
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
to_chat(user, "<span class='notice'>You [isnull(carbon_source.internal) ? "close" : "open"] the valve on [source]'s [item.name].</span>")
|
||||
|
||||
#undef INTERNALS_TOGGLE_DELAY
|
||||
#undef POCKET_EQUIP_DELAY
|
||||
@@ -885,11 +885,6 @@
|
||||
if(what.doStrip(src, who))
|
||||
log_combat(src, who, "stripped [what] off")
|
||||
|
||||
if(Adjacent(who)) //update inventory window
|
||||
who.show_inv(src)
|
||||
else
|
||||
src << browse(null,"window=mob[REF(who)]")
|
||||
|
||||
// The src mob is trying to place an item on someone
|
||||
// Override if a certain mob should be behave differently when placing items (can't, for example)
|
||||
/mob/living/stripPanelEquip(obj/item/what, mob/who, where)
|
||||
@@ -921,11 +916,6 @@
|
||||
else
|
||||
who.equip_to_slot(what, where, TRUE)
|
||||
|
||||
if(Adjacent(who)) //update inventory window
|
||||
who.show_inv(src)
|
||||
else
|
||||
src << browse(null,"window=mob[REF(who)]")
|
||||
|
||||
/mob/living/singularity_pull(S, current_size)
|
||||
..()
|
||||
if(current_size >= STAGE_SIX) //your puny magboots/wings/whatever will not save you against supermatter singularity
|
||||
@@ -1207,7 +1197,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
|
||||
var/datum/status_effect/fire_handler/fire_handler = has_status_effect(/datum/status_effect/fire_handler)
|
||||
if(fire_handler)
|
||||
fire_handler.update_overlay()
|
||||
|
||||
|
||||
/**
|
||||
* Extinguish all fire on the mob
|
||||
*
|
||||
@@ -1700,7 +1690,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
|
||||
// if(!resting)
|
||||
// get_up()
|
||||
set_resting(FALSE)
|
||||
|
||||
|
||||
/mob/living/proc/move_to_error_room()
|
||||
var/obj/effect/landmark/error/error_landmark = locate(/obj/effect/landmark/error) in GLOB.landmarks_list
|
||||
if(error_landmark)
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
/mob/living/simple_animal/pet/dog/corgi/Initialize(mapload)
|
||||
. = ..()
|
||||
regenerate_icons()
|
||||
AddElement(/datum/element/strippable, GLOB.strippable_corgi_items)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -143,19 +144,164 @@
|
||||
..(gibbed)
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
|
||||
/datum/strippable_item/corgi_head,
|
||||
/datum/strippable_item/corgi_back,
|
||||
/datum/strippable_item/corgi_collar,
|
||||
/datum/strippable_item/corgi_id,
|
||||
)))
|
||||
|
||||
|
||||
/datum/strippable_item/corgi_head
|
||||
key = STRIPPABLE_ITEM_HEAD
|
||||
|
||||
/datum/strippable_item/corgi_head/get_item(atom/source)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
user.set_machine(src)
|
||||
|
||||
return corgi_source.inventory_head
|
||||
|
||||
var/dat = "<HTML><HEAD><meta charset='UTF-8'></HEAD><BODY><div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
dat += "<br><B>Head:</B> <A href='?src=[REF(src)];[inventory_head ? "remove_inv=head'>[inventory_head]" : "add_inv=head'>Nothing"]</A>"
|
||||
dat += "<br><B>Back:</B> <A href='?src=[REF(src)];[inventory_back ? "remove_inv=back'>[inventory_back]" : "add_inv=back'>Nothing"]</A>"
|
||||
dat += "<br><B>Collar:</B> <A href='?src=[REF(src)];[pcollar ? "remove_inv=collar'>[pcollar]" : "add_inv=collar'>Nothing"]</A></BODY></HTML>"
|
||||
/datum/strippable_item/corgi_head/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
user << browse(dat, "window=mob[REF(src)];size=325x500")
|
||||
onclose(user, "mob[REF(src)]")
|
||||
corgi_source.place_on_head(equipping, user)
|
||||
|
||||
/datum/strippable_item/corgi_head/finish_unequip(atom/source, obj/item/equipping, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
user.put_in_hands(corgi_source.inventory_head)
|
||||
corgi_source.inventory_head = null
|
||||
corgi_source.update_corgi_fluff()
|
||||
corgi_source.regenerate_icons()
|
||||
|
||||
/datum/strippable_item/corgi_back
|
||||
key = STRIPPABLE_ITEM_BACK
|
||||
|
||||
/datum/strippable_item/corgi_back/get_item(atom/source)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
return corgi_source.inventory_back
|
||||
|
||||
/datum/strippable_item/corgi_back/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
if (!ispath(equipping.dog_fashion, /datum/dog_fashion/back))
|
||||
to_chat(user, "<span class='warning'>You set [equipping] on [source]'s back, but it falls off!</span>")
|
||||
equipping.forceMove(source.drop_location())
|
||||
if (prob(25))
|
||||
step_rand(equipping)
|
||||
dance_rotate(source, set_original_dir = TRUE)
|
||||
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/corgi_back/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
equipping.forceMove(corgi_source)
|
||||
corgi_source.inventory_back = equipping
|
||||
corgi_source.update_corgi_fluff()
|
||||
corgi_source.regenerate_icons()
|
||||
|
||||
/datum/strippable_item/corgi_back/finish_unequip(atom/source, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
user.put_in_hands(corgi_source.inventory_back)
|
||||
corgi_source.inventory_back = null
|
||||
corgi_source.update_corgi_fluff()
|
||||
corgi_source.regenerate_icons()
|
||||
|
||||
/datum/strippable_item/corgi_collar
|
||||
key = STRIPPABLE_ITEM_CORGI_COLLAR
|
||||
|
||||
/datum/strippable_item/corgi_collar/get_item(atom/source)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
return corgi_source.pcollar
|
||||
|
||||
/datum/strippable_item/corgi_collar/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
if (!istype(equipping, /obj/item/clothing/neck/petcollar))
|
||||
to_chat(user, "<span class='warning'>That's not a collar.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/corgi_collar/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
corgi_source.add_collar(equipping, user)
|
||||
corgi_source.update_corgi_fluff()
|
||||
|
||||
/datum/strippable_item/corgi_collar/finish_unequip(atom/source, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
user.put_in_hands(corgi_source.pcollar)
|
||||
corgi_source.pcollar = null
|
||||
corgi_source.update_corgi_fluff()
|
||||
corgi_source.regenerate_icons()
|
||||
|
||||
/datum/strippable_item/corgi_id
|
||||
key = STRIPPABLE_ITEM_ID
|
||||
|
||||
/datum/strippable_item/corgi_id/get_item(atom/source)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
return corgi_source.access_card
|
||||
|
||||
/datum/strippable_item/corgi_id/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
if (!istype(equipping, /obj/item/card/id))
|
||||
to_chat(user, "<span class='warning'>You can't pin [equipping] to [source]!</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/corgi_id/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
equipping.forceMove(source)
|
||||
corgi_source.access_card = equipping
|
||||
|
||||
/datum/strippable_item/corgi_id/finish_unequip(atom/source, mob/user)
|
||||
var/mob/living/simple_animal/pet/dog/corgi/corgi_source = source
|
||||
if (!istype(corgi_source))
|
||||
return
|
||||
|
||||
user.put_in_hands(corgi_source.access_card)
|
||||
corgi_source.access_card = null
|
||||
corgi_source.update_corgi_fluff()
|
||||
corgi_source.regenerate_icons()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, type)
|
||||
var/armorval = 0
|
||||
@@ -198,102 +344,6 @@
|
||||
..()
|
||||
update_corgi_fluff()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
|
||||
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
usr << browse(null, "window=mob[REF(src)]")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if(BODY_ZONE_HEAD)
|
||||
if(inventory_head)
|
||||
usr.put_in_hands(inventory_head)
|
||||
inventory_head = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
else
|
||||
to_chat(usr, span_danger("There is nothing to remove from its [remove_from]."))
|
||||
return
|
||||
if("back")
|
||||
if(inventory_back)
|
||||
usr.put_in_hands(inventory_back)
|
||||
inventory_back = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
else
|
||||
to_chat(usr, span_danger("There is nothing to remove from its [remove_from]."))
|
||||
return
|
||||
if("collar")
|
||||
if(pcollar)
|
||||
usr.put_in_hands(pcollar)
|
||||
pcollar = null
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
|
||||
show_inv(usr)
|
||||
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
var/add_to = href_list["add_inv"]
|
||||
|
||||
switch(add_to)
|
||||
if("collar")
|
||||
var/obj/item/clothing/neck/petcollar/P = usr.get_active_held_item()
|
||||
if(!istype(P))
|
||||
to_chat(usr,span_warning("That's not a collar."))
|
||||
return
|
||||
add_collar(P, usr)
|
||||
update_corgi_fluff()
|
||||
|
||||
if(BODY_ZONE_HEAD)
|
||||
place_on_head(usr.get_active_held_item(),usr)
|
||||
|
||||
if("back")
|
||||
if(inventory_back)
|
||||
to_chat(usr, span_warning("It's already wearing something!"))
|
||||
return
|
||||
else
|
||||
var/obj/item/item_to_add = usr.get_active_held_item()
|
||||
|
||||
if(!item_to_add)
|
||||
usr.visible_message("[usr] pets [src].",span_notice("You rest your hand on [src]'s back for a moment."))
|
||||
return
|
||||
|
||||
if(!usr.temporarilyRemoveItemFromInventory(item_to_add))
|
||||
to_chat(usr, span_warning("\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s back!"))
|
||||
return
|
||||
|
||||
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
|
||||
item_to_add.afterattack(src,usr,1)
|
||||
return
|
||||
|
||||
//The objects that corgis can wear on their backs.
|
||||
var/allowed = FALSE
|
||||
if(ispath(item_to_add.dog_fashion, /datum/dog_fashion/back))
|
||||
allowed = TRUE
|
||||
|
||||
if(!allowed)
|
||||
to_chat(usr, span_warning("You set [item_to_add] on [src]'s back, but it falls off!"))
|
||||
item_to_add.forceMove(drop_location())
|
||||
if(prob(25))
|
||||
step_rand(item_to_add)
|
||||
for(var/i in list(1,2,4,8,4,8,4,dir))
|
||||
setDir(i)
|
||||
sleep(0.1 SECONDS)
|
||||
return
|
||||
|
||||
item_to_add.forceMove(src)
|
||||
src.inventory_back = item_to_add
|
||||
update_corgi_fluff()
|
||||
regenerate_icons()
|
||||
|
||||
show_inv(usr)
|
||||
else
|
||||
return ..()
|
||||
|
||||
//Corgis are supposed to be simpler, so only a select few objects can actually be put
|
||||
//to be compatible with them. The objects are below.
|
||||
//Many hats added, Some will probably be removed, just want to see which ones are popular.
|
||||
@@ -301,10 +351,6 @@
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user)
|
||||
|
||||
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
|
||||
INVOKE_ASYNC(item_to_add, TYPE_PROC_REF(/obj/item, afterattack), src, user, 1)
|
||||
return
|
||||
|
||||
if(inventory_head)
|
||||
if(user)
|
||||
to_chat(user, span_warning("You can't put more than one hat on [src]!"))
|
||||
@@ -342,9 +388,8 @@
|
||||
item_to_add.forceMove(drop_location())
|
||||
if(prob(25))
|
||||
step_rand(item_to_add)
|
||||
for(var/i in list(1,2,4,8,4,8,4,dir))
|
||||
setDir(i)
|
||||
sleep(0.1 SECONDS)
|
||||
dance_rotate(src, set_original_dir = TRUE)
|
||||
return FALSE
|
||||
|
||||
return valid
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
/mob/living/simple_animal/parrot/proc/toggle_mode,
|
||||
/mob/living/simple_animal/parrot/proc/perch_mob_player))
|
||||
|
||||
AddElement(/datum/element/strippable, GLOB.strippable_parrot_items)
|
||||
|
||||
/mob/living/simple_animal/parrot/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -172,91 +173,95 @@
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
return 0
|
||||
/*
|
||||
* Inventory
|
||||
*/
|
||||
/mob/living/simple_animal/parrot/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
|
||||
var/dat = "<HTML><HEAD><meta charset='UTF-8'></HEAD><BODY><div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
dat += "<br><B>Headset:</B> <A href='?src=[REF(src)];[ears ? "remove_inv=ears'>[ears]" : "add_inv=ears'>Nothing"]</A></BODY></HTML>"
|
||||
GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
|
||||
/datum/strippable_item/parrot_headset,
|
||||
)))
|
||||
|
||||
user << browse(dat, "window=mob[REF(src)];size=325x500")
|
||||
onclose(user, "window=mob[REF(src)]")
|
||||
/datum/strippable_item/parrot_headset
|
||||
key = STRIPPABLE_ITEM_PARROT_HEADSET
|
||||
|
||||
/datum/strippable_item/parrot_headset/get_item(atom/source)
|
||||
var/mob/living/simple_animal/parrot/parrot_source = source
|
||||
return istype(parrot_source) ? parrot_source.ears : null
|
||||
|
||||
/datum/strippable_item/parrot_headset/try_equip(atom/source, obj/item/equipping, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
if (!istype(equipping, /obj/item/radio/headset))
|
||||
to_chat(user, "<span class='warning'>[equipping] won't fit!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/Topic(href, href_list)
|
||||
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
usr << browse(null, "window=mob[REF(src)]")
|
||||
usr.unset_machine()
|
||||
// There is no delay for putting a headset on a parrot.
|
||||
/datum/strippable_item/parrot_headset/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/parrot_headset/finish_equip(atom/source, obj/item/equipping, mob/user)
|
||||
var/obj/item/radio/headset/radio = equipping
|
||||
if (!istype(radio))
|
||||
return
|
||||
var/mob/living/simple_animal/parrot/parrot_source = source
|
||||
if (!istype(parrot_source))
|
||||
return
|
||||
if (!user.transferItemToLoc(radio, source))
|
||||
return
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if("ears")
|
||||
if(!ears)
|
||||
to_chat(usr, span_warning("There is nothing to remove from its [remove_from]!"))
|
||||
return
|
||||
if(!stat)
|
||||
say("[available_channels.len ? "[pick(available_channels)] " : null]BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
ears.forceMove(drop_location())
|
||||
ears = null
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext_char(possible_phrase, 2, 3) in GLOB.department_radio_keys)
|
||||
possible_phrase = copytext_char(possible_phrase, 3)
|
||||
parrot_source.ears = radio
|
||||
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
var/add_to = href_list["add_inv"]
|
||||
if(!usr.get_active_held_item())
|
||||
to_chat(usr, span_warning("You have nothing in your hand to put on its [add_to]!"))
|
||||
return
|
||||
switch(add_to)
|
||||
if("ears")
|
||||
if(ears)
|
||||
to_chat(usr, span_warning("It's already wearing something!"))
|
||||
return
|
||||
else
|
||||
var/obj/item/item_to_add = usr.get_active_held_item()
|
||||
if(!item_to_add)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You fit [radio] onto [source].</span>")
|
||||
|
||||
if( !istype(item_to_add, /obj/item/radio/headset) )
|
||||
to_chat(usr, span_warning("This object won't fit!"))
|
||||
return
|
||||
parrot_source.available_channels.Cut()
|
||||
|
||||
var/obj/item/radio/headset/headset_to_add = item_to_add
|
||||
for (var/channel in radio.channels)
|
||||
var/channel_to_add
|
||||
|
||||
if(!usr.transferItemToLoc(headset_to_add, src))
|
||||
return
|
||||
ears = headset_to_add
|
||||
to_chat(usr, span_notice("You fit the headset onto [src]."))
|
||||
switch (channel)
|
||||
if (RADIO_CHANNEL_ENGINEERING)
|
||||
channel_to_add = RADIO_TOKEN_ENGINEERING
|
||||
if (RADIO_CHANNEL_COMMAND)
|
||||
channel_to_add = RADIO_TOKEN_COMMAND
|
||||
if (RADIO_CHANNEL_SECURITY)
|
||||
channel_to_add = RADIO_TOKEN_SECURITY
|
||||
if (RADIO_CHANNEL_SCIENCE)
|
||||
channel_to_add = RADIO_TOKEN_SCIENCE
|
||||
if (RADIO_CHANNEL_MEDICAL)
|
||||
channel_to_add = RADIO_TOKEN_MEDICAL
|
||||
if (RADIO_CHANNEL_SUPPLY)
|
||||
channel_to_add = RADIO_TOKEN_SUPPLY
|
||||
if (RADIO_CHANNEL_SERVICE)
|
||||
channel_to_add = RADIO_TOKEN_SERVICE
|
||||
|
||||
LAZYCLEARLIST(available_channels)
|
||||
for(var/ch in headset_to_add.channels)
|
||||
switch(ch)
|
||||
if(RADIO_CHANNEL_ENGINEERING)
|
||||
available_channels.Add(RADIO_TOKEN_ENGINEERING)
|
||||
if(RADIO_CHANNEL_COMMAND)
|
||||
available_channels.Add(RADIO_TOKEN_COMMAND)
|
||||
if(RADIO_CHANNEL_SECURITY)
|
||||
available_channels.Add(RADIO_TOKEN_SECURITY)
|
||||
if(RADIO_CHANNEL_SCIENCE)
|
||||
available_channels.Add(RADIO_TOKEN_SCIENCE)
|
||||
if(RADIO_CHANNEL_MEDICAL)
|
||||
available_channels.Add(RADIO_TOKEN_MEDICAL)
|
||||
if(RADIO_CHANNEL_SUPPLY)
|
||||
available_channels.Add(RADIO_TOKEN_SUPPLY)
|
||||
if(RADIO_CHANNEL_SERVICE)
|
||||
available_channels.Add(RADIO_TOKEN_SERVICE)
|
||||
if (channel_to_add)
|
||||
parrot_source.available_channels += channel_to_add
|
||||
|
||||
if(headset_to_add.translate_binary)
|
||||
available_channels.Add(MODE_TOKEN_BINARY)
|
||||
else
|
||||
return ..()
|
||||
if (radio.translate_binary)
|
||||
parrot_source.available_channels.Add(MODE_TOKEN_BINARY)
|
||||
|
||||
/datum/strippable_item/parrot_headset/start_unequip(atom/source, mob/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
var/mob/living/simple_animal/parrot/parrot_source = source
|
||||
if (!istype(parrot_source))
|
||||
return
|
||||
|
||||
if (!parrot_source.stat)
|
||||
parrot_source.say("[parrot_source.available_channels.len ? "[pick(parrot_source.available_channels)] " : null]BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/strippable_item/parrot_headset/finish_unequip(atom/source, mob/user)
|
||||
var/mob/living/simple_animal/parrot/parrot_source = source
|
||||
if (!istype(parrot_source))
|
||||
return
|
||||
|
||||
parrot_source.ears.forceMove(parrot_source.drop_location())
|
||||
parrot_source.ears = null
|
||||
|
||||
/*
|
||||
* Attack responces
|
||||
|
||||
@@ -499,10 +499,6 @@
|
||||
SEND_SIGNAL(src, COMSIG_MOB_RESET_PERSPECTIVE)
|
||||
return TRUE
|
||||
|
||||
/// Show the mob's inventory to another mob
|
||||
/mob/proc/show_inv(mob/user)
|
||||
return
|
||||
|
||||
/**
|
||||
* Examine a mob
|
||||
*
|
||||
@@ -809,10 +805,6 @@
|
||||
unset_machine()
|
||||
src << browse(null, t1)
|
||||
|
||||
if(href_list["refresh"])
|
||||
if(machine && in_range(src, usr))
|
||||
show_inv(machine)
|
||||
|
||||
|
||||
if(href_list["item"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
var/slot = text2num(href_list["item"])
|
||||
@@ -829,12 +821,6 @@
|
||||
else
|
||||
usr.stripPanelEquip(what,src,slot)
|
||||
|
||||
if(usr.machine == src)
|
||||
if(Adjacent(usr))
|
||||
show_inv(usr)
|
||||
else
|
||||
usr << browse(null,"window=mob[REF(src)]")
|
||||
|
||||
// The src mob is trying to strip an item from someone
|
||||
// Defined in living.dm
|
||||
/mob/proc/stripPanelUnequip(obj/item/what, mob/who)
|
||||
@@ -859,12 +845,6 @@
|
||||
if(isAI(M))
|
||||
return
|
||||
|
||||
/mob/MouseDrop_T(atom/dropping, atom/user)
|
||||
. = ..()
|
||||
if(ismob(dropping) && dropping != user && user == src)
|
||||
var/mob/M = dropping
|
||||
M.show_inv(user)
|
||||
|
||||
/**
|
||||
* Handle the result of a click drag onto this mob
|
||||
*
|
||||
@@ -1035,7 +1015,7 @@
|
||||
is_magic_blocked = TRUE
|
||||
if((casted_magic_flags & MAGIC_RESISTANCE_HOLY) && HAS_TRAIT(src, TRAIT_HOLY))
|
||||
is_magic_blocked = TRUE
|
||||
|
||||
|
||||
if(is_magic_blocked && charge_cost > 0 && !HAS_TRAIT(src, TRAIT_RECENTLY_BLOCKED_MAGIC))
|
||||
on_block_magic_effects(casted_magic_flags, antimagic_sources)
|
||||
|
||||
@@ -1270,7 +1250,7 @@
|
||||
return
|
||||
for(var/atom/movable/screen/plane_master/rendering_plate/lighting/light as anything in hud_used.get_true_plane_masters(RENDER_PLANE_LIGHTING))
|
||||
light.set_light_cutoff(lighting_cutoff, lighting_color_cutoffs)
|
||||
|
||||
|
||||
///Update the mouse pointer of the attached client in this mob
|
||||
/mob/proc/update_mouse_pointer()
|
||||
if (!client)
|
||||
|
||||
BIN
icons/UI_Icons/inventory_midnight/act_drop.png
Normal file
|
After Width: | Height: | Size: 506 B |
BIN
icons/UI_Icons/inventory_midnight/act_equip.png
Normal file
|
After Width: | Height: | Size: 451 B |
BIN
icons/UI_Icons/inventory_midnight/act_resist.png
Normal file
|
After Width: | Height: | Size: 508 B |
BIN
icons/UI_Icons/inventory_midnight/act_rest.png
Normal file
|
After Width: | Height: | Size: 519 B |
BIN
icons/UI_Icons/inventory_midnight/act_rest0.png
Normal file
|
After Width: | Height: | Size: 519 B |
BIN
icons/UI_Icons/inventory_midnight/act_throw_off.png
Normal file
|
After Width: | Height: | Size: 502 B |
BIN
icons/UI_Icons/inventory_midnight/act_throw_on.png
Normal file
|
After Width: | Height: | Size: 502 B |
BIN
icons/UI_Icons/inventory_midnight/area_edit.png
Normal file
|
After Width: | Height: | Size: 596 B |
BIN
icons/UI_Icons/inventory_midnight/back.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/UI_Icons/inventory_midnight/belt.png
Normal file
|
After Width: | Height: | Size: 1022 B |
BIN
icons/UI_Icons/inventory_midnight/chem_scan.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
icons/UI_Icons/inventory_midnight/collar.png
Normal file
|
After Width: | Height: | Size: 835 B |
BIN
icons/UI_Icons/inventory_midnight/combat.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/UI_Icons/inventory_midnight/combat_off.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
icons/UI_Icons/inventory_midnight/craft.png
Normal file
|
After Width: | Height: | Size: 518 B |
BIN
icons/UI_Icons/inventory_midnight/disarm.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
icons/UI_Icons/inventory_midnight/ears.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/UI_Icons/inventory_midnight/gabrielle.png
Normal file
|
After Width: | Height: | Size: 575 B |
BIN
icons/UI_Icons/inventory_midnight/glasses.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/UI_Icons/inventory_midnight/gloves.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/UI_Icons/inventory_midnight/grab.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/UI_Icons/inventory_midnight/hand_l.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
icons/UI_Icons/inventory_midnight/hand_r.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
icons/UI_Icons/inventory_midnight/harm.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
icons/UI_Icons/inventory_midnight/head.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/UI_Icons/inventory_midnight/help.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
icons/UI_Icons/inventory_midnight/id.png
Normal file
|
After Width: | Height: | Size: 654 B |
BIN
icons/UI_Icons/inventory_midnight/lhandactive.png
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
icons/UI_Icons/inventory_midnight/markus.png
Normal file
|
After Width: | Height: | Size: 568 B |
BIN
icons/UI_Icons/inventory_midnight/mask.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/UI_Icons/inventory_midnight/med_scan.png
Normal file
|
After Width: | Height: | Size: 444 B |
BIN
icons/UI_Icons/inventory_midnight/nanite_scan.png
Normal file
|
After Width: | Height: | Size: 569 B |
BIN
icons/UI_Icons/inventory_midnight/neck.png
Normal file
|
After Width: | Height: | Size: 835 B |
BIN
icons/UI_Icons/inventory_midnight/pai_setup.png
Normal file
|
After Width: | Height: | Size: 671 B |
BIN
icons/UI_Icons/inventory_midnight/pocket.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
icons/UI_Icons/inventory_midnight/pull.png
Normal file
|
After Width: | Height: | Size: 505 B |
BIN
icons/UI_Icons/inventory_midnight/reserved.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
icons/UI_Icons/inventory_midnight/rhandactive.png
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
icons/UI_Icons/inventory_midnight/running.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
icons/UI_Icons/inventory_midnight/scroll_down.png
Normal file
|
After Width: | Height: | Size: 557 B |
BIN
icons/UI_Icons/inventory_midnight/scroll_up.png
Normal file
|
After Width: | Height: | Size: 523 B |
BIN
icons/UI_Icons/inventory_midnight/shoes.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/UI_Icons/inventory_midnight/suit.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/UI_Icons/inventory_midnight/suit_storage.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
icons/UI_Icons/inventory_midnight/swap_1.png
Normal file
|
After Width: | Height: | Size: 473 B |
BIN
icons/UI_Icons/inventory_midnight/swap_1_m.png
Normal file
|
After Width: | Height: | Size: 467 B |
BIN
icons/UI_Icons/inventory_midnight/swap_2.png
Normal file
|
After Width: | Height: | Size: 506 B |
BIN
icons/UI_Icons/inventory_midnight/talk_wheel.png
Normal file
|
After Width: | Height: | Size: 509 B |
BIN
icons/UI_Icons/inventory_midnight/template.png
Normal file
|
After Width: | Height: | Size: 478 B |
BIN
icons/UI_Icons/inventory_midnight/template_active.png
Normal file
|
After Width: | Height: | Size: 470 B |
BIN
icons/UI_Icons/inventory_midnight/template_small.png
Normal file
|
After Width: | Height: | Size: 522 B |
BIN
icons/UI_Icons/inventory_midnight/template_tiny.png
Normal file
|
After Width: | Height: | Size: 415 B |
BIN
icons/UI_Icons/inventory_midnight/toggle.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/UI_Icons/inventory_midnight/uniform.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/UI_Icons/inventory_midnight/walking.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
icons/UI_Icons/inventory_midnight/wound_scan.png
Normal file
|
After Width: | Height: | Size: 699 B |
BIN
icons/UI_Icons/inventory_midnight/zone_sel.png
Normal file
|
After Width: | Height: | Size: 844 B |
413
tgui/packages/tgui/interfaces/StripMenu.tsx
Normal file
@@ -0,0 +1,413 @@
|
||||
import { range } from "common/collections";
|
||||
import { BooleanLike } from "common/react";
|
||||
import { resolveAsset } from "../assets";
|
||||
import { useBackend } from "../backend";
|
||||
import { Box, Button, Icon, Stack } from "../components";
|
||||
import { Window } from "../layouts";
|
||||
|
||||
const ROWS = 5;
|
||||
const COLUMNS = 6;
|
||||
|
||||
const BUTTON_DIMENSIONS = "50px";
|
||||
|
||||
type GridSpotKey = string;
|
||||
|
||||
const getGridSpotKey = (spot: [number, number]): GridSpotKey => {
|
||||
return `${spot[0]}/${spot[1]}`;
|
||||
};
|
||||
|
||||
type AlternateAction = {
|
||||
icon: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
const ALTERNATE_ACTIONS: Record<string, AlternateAction> = {
|
||||
knot: {
|
||||
icon: "shoe-prints",
|
||||
text: "Knot",
|
||||
},
|
||||
|
||||
untie: {
|
||||
icon: "shoe-prints",
|
||||
text: "Untie",
|
||||
},
|
||||
|
||||
unknot: {
|
||||
icon: "shoe-prints",
|
||||
text: "Unknot",
|
||||
},
|
||||
|
||||
enable_internals: {
|
||||
icon: "mask-ventilator",
|
||||
text: "Enable internals",
|
||||
},
|
||||
|
||||
disable_internals: {
|
||||
icon: "wind",
|
||||
text: "Disable internals",
|
||||
},
|
||||
|
||||
adjust_jumpsuit: {
|
||||
icon: "tshirt",
|
||||
text: "Adjust jumpsuit",
|
||||
},
|
||||
};
|
||||
|
||||
const SLOTS: Record<
|
||||
string,
|
||||
{
|
||||
displayName: string;
|
||||
gridSpot: GridSpotKey;
|
||||
image?: string;
|
||||
additionalComponent?: JSX.Element;
|
||||
}
|
||||
> = {
|
||||
eyes: {
|
||||
displayName: "eyewear",
|
||||
gridSpot: getGridSpotKey([0, 1]),
|
||||
image: "inventory-glasses.png",
|
||||
},
|
||||
|
||||
head: {
|
||||
displayName: "headwear",
|
||||
gridSpot: getGridSpotKey([0, 2]),
|
||||
image: "inventory-head.png",
|
||||
},
|
||||
|
||||
neck: {
|
||||
displayName: "neckwear",
|
||||
gridSpot: getGridSpotKey([1, 1]),
|
||||
image: "inventory-neck.png",
|
||||
},
|
||||
|
||||
mask: {
|
||||
displayName: "mask",
|
||||
gridSpot: getGridSpotKey([1, 2]),
|
||||
image: "inventory-mask.png",
|
||||
},
|
||||
|
||||
corgi_collar: {
|
||||
displayName: "collar",
|
||||
gridSpot: getGridSpotKey([1, 2]),
|
||||
image: "inventory-collar.png",
|
||||
},
|
||||
|
||||
ears: {
|
||||
displayName: "earwear",
|
||||
gridSpot: getGridSpotKey([1, 3]),
|
||||
image: "inventory-ears.png",
|
||||
},
|
||||
|
||||
parrot_headset: {
|
||||
displayName: "headset",
|
||||
gridSpot: getGridSpotKey([1, 3]),
|
||||
image: "inventory-ears.png",
|
||||
},
|
||||
|
||||
handcuffs: {
|
||||
displayName: "handcuffs",
|
||||
gridSpot: getGridSpotKey([1, 4]),
|
||||
},
|
||||
|
||||
legcuffs: {
|
||||
displayName: "legcuffs",
|
||||
gridSpot: getGridSpotKey([1, 5]),
|
||||
},
|
||||
|
||||
jumpsuit: {
|
||||
displayName: "uniform",
|
||||
gridSpot: getGridSpotKey([2, 1]),
|
||||
image: "inventory-uniform.png",
|
||||
},
|
||||
|
||||
suit: {
|
||||
displayName: "suit",
|
||||
gridSpot: getGridSpotKey([2, 2]),
|
||||
image: "inventory-suit.png",
|
||||
},
|
||||
|
||||
gloves: {
|
||||
displayName: "gloves",
|
||||
gridSpot: getGridSpotKey([2, 3]),
|
||||
image: "inventory-gloves.png",
|
||||
},
|
||||
|
||||
right_hand: {
|
||||
displayName: "right hand",
|
||||
gridSpot: getGridSpotKey([2, 4]),
|
||||
image: "inventory-hand_r.png",
|
||||
},
|
||||
|
||||
left_hand: {
|
||||
displayName: "left hand",
|
||||
gridSpot: getGridSpotKey([2, 5]),
|
||||
image: "inventory-hand_l.png",
|
||||
},
|
||||
|
||||
shoes: {
|
||||
displayName: "shoes",
|
||||
gridSpot: getGridSpotKey([3, 2]),
|
||||
image: "inventory-shoes.png",
|
||||
},
|
||||
|
||||
suit_storage: {
|
||||
displayName: "suit storage item",
|
||||
gridSpot: getGridSpotKey([4, 0]),
|
||||
image: "inventory-suit_storage.png",
|
||||
},
|
||||
|
||||
id: {
|
||||
displayName: "ID",
|
||||
gridSpot: getGridSpotKey([4, 1]),
|
||||
image: "inventory-id.png",
|
||||
},
|
||||
|
||||
belt: {
|
||||
displayName: "belt",
|
||||
gridSpot: getGridSpotKey([4, 2]),
|
||||
image: "inventory-belt.png",
|
||||
},
|
||||
|
||||
back: {
|
||||
displayName: "backpack",
|
||||
gridSpot: getGridSpotKey([4, 3]),
|
||||
image: "inventory-back.png",
|
||||
},
|
||||
|
||||
left_pocket: {
|
||||
displayName: "left pocket",
|
||||
gridSpot: getGridSpotKey([4, 4]),
|
||||
image: "inventory-pocket.png",
|
||||
},
|
||||
|
||||
right_pocket: {
|
||||
displayName: "right pocket",
|
||||
gridSpot: getGridSpotKey([4, 5]),
|
||||
image: "inventory-pocket.png",
|
||||
},
|
||||
};
|
||||
|
||||
enum ObscuringLevel {
|
||||
Completely = 1,
|
||||
Hidden = 2,
|
||||
}
|
||||
|
||||
type Interactable = {
|
||||
interacting: BooleanLike;
|
||||
};
|
||||
|
||||
/**
|
||||
* Some possible options:
|
||||
*
|
||||
* null - No interactions, no item, but is an available slot
|
||||
* { interacting: 1 } - No item, but we're interacting with it
|
||||
* { icon: icon, name: name } - An item with no alternate actions
|
||||
* that we're not interacting with.
|
||||
* { icon, name, interacting: 1 } - An item with no alternate actions
|
||||
* that we're interacting with.
|
||||
*/
|
||||
type StripMenuItem =
|
||||
| null
|
||||
| Interactable
|
||||
| ((
|
||||
| {
|
||||
icon: string;
|
||||
name: string;
|
||||
alternate?: string;
|
||||
}
|
||||
| {
|
||||
obscured: ObscuringLevel;
|
||||
}
|
||||
) &
|
||||
Partial<Interactable>);
|
||||
|
||||
type StripMenuData = {
|
||||
items: Record<keyof typeof SLOTS, StripMenuItem>;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export const StripMenu = (props, context) => {
|
||||
const { act, data } = useBackend<StripMenuData>(context);
|
||||
|
||||
const gridSpots = new Map<GridSpotKey, string>();
|
||||
for (const key of Object.keys(data.items)) {
|
||||
gridSpots.set(SLOTS[key].gridSpot, key);
|
||||
}
|
||||
|
||||
return (
|
||||
<Window
|
||||
title={`Stripping ${data.name}`}
|
||||
width={410}
|
||||
height={380}>
|
||||
<Window.Content
|
||||
style={{
|
||||
background: "#25252b",
|
||||
}} >
|
||||
<Stack fill vertical ml={'10px'}>
|
||||
{range(0, ROWS).map(row => (
|
||||
<Stack.Item grow key={row} ml={-2}>
|
||||
<Stack fill justify="space-around">
|
||||
{range(0, COLUMNS).map(column => {
|
||||
const key = getGridSpotKey([row, column]);
|
||||
const keyAtSpot = gridSpots.get(key);
|
||||
|
||||
if (!keyAtSpot) {
|
||||
return (
|
||||
<Stack.Item
|
||||
key={key}
|
||||
style={{
|
||||
width: BUTTON_DIMENSIONS,
|
||||
height: BUTTON_DIMENSIONS,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const item = data.items[keyAtSpot];
|
||||
const slot = SLOTS[keyAtSpot];
|
||||
|
||||
let alternateAction: AlternateAction | undefined;
|
||||
|
||||
let content;
|
||||
let tooltip;
|
||||
|
||||
if (item === null) {
|
||||
tooltip = slot.displayName;
|
||||
} else if ("name" in item) {
|
||||
if (item.alternate) {
|
||||
alternateAction = ALTERNATE_ACTIONS[item.alternate];
|
||||
}
|
||||
|
||||
content = (
|
||||
<Box
|
||||
as="img"
|
||||
src={`data:image/jpeg;base64,${item.icon}`}
|
||||
height="64px"
|
||||
width="64px"
|
||||
mt={0}
|
||||
ml={-1}
|
||||
style={{
|
||||
"-ms-interpolation-mode": "nearest-neighbor",
|
||||
"vertical-align": "middle",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
tooltip = item.name;
|
||||
} else if ("obscured" in item) {
|
||||
content = (
|
||||
<Icon
|
||||
name={
|
||||
item.obscured === ObscuringLevel.Completely
|
||||
? "ban"
|
||||
: "eye-slash"
|
||||
}
|
||||
size={3}
|
||||
ml={-1}
|
||||
mt={2.1}
|
||||
style={{
|
||||
"text-align": "center",
|
||||
height: "64px",
|
||||
width: "64px",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
tooltip = `obscured ${slot.displayName}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack.Item
|
||||
key={key}
|
||||
style={{
|
||||
width: BUTTON_DIMENSIONS,
|
||||
height: BUTTON_DIMENSIONS,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "64px",
|
||||
height: "64px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
act("use", {
|
||||
key: keyAtSpot,
|
||||
});
|
||||
}}
|
||||
fluid
|
||||
tooltip={tooltip}
|
||||
ml={-0.9}
|
||||
style={{
|
||||
background: item?.interacting
|
||||
? "hsl(39, 73%, 30%)"
|
||||
: "#25252b",
|
||||
position: "relative",
|
||||
width: "64px",
|
||||
height: "64px",
|
||||
}}
|
||||
>
|
||||
{slot.image && (
|
||||
<Box
|
||||
as="img"
|
||||
src={resolveAsset(slot.image)}
|
||||
opacity={0.9}
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: "64px",
|
||||
height: "64px",
|
||||
left: "50%",
|
||||
top: "50%",
|
||||
"-ms-interpolation-mode": "nearest-neighbor",
|
||||
transform:
|
||||
"translateX(-50%) translateY(-50%)",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Box style={{ position: "relative" }}>
|
||||
{content}
|
||||
</Box>
|
||||
|
||||
{slot.additionalComponent}
|
||||
</Button>
|
||||
|
||||
{alternateAction !== undefined && (
|
||||
<Button
|
||||
onClick={() => {
|
||||
act("alt", {
|
||||
key: keyAtSpot,
|
||||
});
|
||||
}}
|
||||
tooltip={alternateAction.text}
|
||||
mr={1}
|
||||
width={1.6}
|
||||
height={1.6}
|
||||
style={{
|
||||
background: "rgba(0, 0, 0, 0.6)",
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
"z-index": 2,
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
ml={-0.75}
|
||||
color={'white'}
|
||||
name={alternateAction.icon} />
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -147,6 +147,7 @@
|
||||
#include "code\__DEFINES\stat_tracking.dm"
|
||||
#include "code\__DEFINES\station.dm"
|
||||
#include "code\__DEFINES\status_effects.dm"
|
||||
#include "code\__DEFINES\strippable.dm"
|
||||
#include "code\__DEFINES\subsystems.dm"
|
||||
#include "code\__DEFINES\text.dm"
|
||||
#include "code\__DEFINES\tgs.config.dm"
|
||||
@@ -763,6 +764,7 @@
|
||||
#include "code\datums\elements\rust.dm"
|
||||
#include "code\datums\elements\speech_bubble_override.dm"
|
||||
#include "code\datums\elements\squish.dm"
|
||||
#include "code\datums\elements\strippable.dm"
|
||||
#include "code\datums\elements\turf_transparency.dm"
|
||||
#include "code\datums\elements\undertile.dm"
|
||||
#include "code\datums\elements\update_icon_blocker.dm"
|
||||
@@ -2875,6 +2877,7 @@
|
||||
#include "code\modules\mob\living\carbon\carbon_defense.dm"
|
||||
#include "code\modules\mob\living\carbon\carbon_defines.dm"
|
||||
#include "code\modules\mob\living\carbon\carbon_movement.dm"
|
||||
#include "code\modules\mob\living\carbon\carbon_stripping.dm"
|
||||
#include "code\modules\mob\living\carbon\damage_procs.dm"
|
||||
#include "code\modules\mob\living\carbon\death.dm"
|
||||
#include "code\modules\mob\living\carbon\emote.dm"
|
||||
@@ -2929,6 +2932,7 @@
|
||||
#include "code\modules\mob\living\carbon\human\human_defines.dm"
|
||||
#include "code\modules\mob\living\carbon\human\human_helpers.dm"
|
||||
#include "code\modules\mob\living\carbon\human\human_movement.dm"
|
||||
#include "code\modules\mob\living\carbon\human\human_stripping.dm"
|
||||
#include "code\modules\mob\living\carbon\human\inventory.dm"
|
||||
#include "code\modules\mob\living\carbon\human\life.dm"
|
||||
#include "code\modules\mob\living\carbon\human\physiology.dm"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/mob/living/carbon/alien/humanoid/Initialize(mapload, null)
|
||||
var/datum/action/cooldown/alien/regurgitate/regurgitate = new(src)
|
||||
regurgitate.Grant(src)
|
||||
AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW, 0.5, -11)
|
||||
AddElement(/datum/element/strippable, GLOB.strippable_alien_humanoid_items)
|
||||
. = ..()
|
||||
|
||||