diff --git a/code/citadel/custom_loadout/custom_items.dm b/code/citadel/custom_loadout/custom_items.dm
index 885e06d83b..108e50b07a 100644
--- a/code/citadel/custom_loadout/custom_items.dm
+++ b/code/citadel/custom_loadout/custom_items.dm
@@ -16,17 +16,20 @@
/obj/item/clothing/neck/cloak/inferno
name = "Kiara's Cloak"
desc = "The design on this seems a little too familiar."
- icon = 'icons/obj/clothing/cloaks.dmi'
- icon_state = "infcloak"
- item_state = "infcloak"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "infcloak-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "infcloak-w"
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS
/obj/item/clothing/neck/petcollar/inferno
name = "Kiara's Collar"
desc = "A soft black collar that seems to stretch to fit whoever wears it."
- icon_state = "infcollar"
- item_state = "infcollar"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "infcollar-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "infcollar-w"
item_color = null
tagname = null
@@ -43,7 +46,7 @@
/obj/item/lighter/gold
name = "\improper Engraved Zippo"
desc = "A shiny and relatively expensive zippo lighter. There's a small etched in verse on the bottom that reads, 'No Gods, No Masters, Only Man.'"
- icon = 'icons/obj/cigarettes.dmi'
+ icon = 'icons/obj/custom.dmi'
icon_state = "gold_zippo"
item_state = "gold_zippo"
w_class = WEIGHT_CLASS_TINY
@@ -58,16 +61,20 @@
/obj/item/clothing/neck/scarf/zomb //Default white color, same functionality as beanies.
name = "A special scarf"
- icon_state = "zombscarf"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "zombscarf-i"
desc = "A fashionable collar"
- item_color = "zombscarf"
+ icon_override = 'icons/obj/custom.dmi'
+ item_color = "zombscarf-w"
dog_fashion = /datum/dog_fashion/head
/obj/item/clothing/suit/toggle/labcoat/mad/red
name = "\improper The Mad's labcoat"
desc = "An oddly special looking coat."
- icon_state = "labred"
- item_state = "labred"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "labred-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "labred-w"
/*PLACEHOLDER*/
@@ -86,17 +93,17 @@
/obj/item/clothing/neck/cloak/carrot
name = "carrot cloak"
desc = "A cloak in the shape and color of a carrot!"
- icon = 'icons/obj/clothing/cloaks.dmi'
- icon_override = 'icons/mob/citadel/suit.dmi'
- icon_state = "carrotcloak"
- item_state = "carrotcloak"
+ icon = 'icons/obj/custom.dmi'
+ icon_override = 'icons/obj/custom.dmi'
+ icon_state = "carrotcloak-i"
+ item_state = "carrotcloak-w"
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS
/obj/item/toy/plush/tree
name = "christmass tree plushie"
desc = "A festive plush that squeeks when you squeeze it!"
- icon = 'icons/obj/plushes.dmi'
+ icon = 'icons/obj/custom.dmi'
icon_state = "pine_c"
item_state = "pine_c"
w_class = WEIGHT_CLASS_SMALL
@@ -107,10 +114,10 @@
/obj/item/clothing/neck/cloak/festive
name = "Celebratory Cloak of Morozko"
desc = " It probably will protect from snow, charcoal or elves."
- icon = 'icons/obj/clothing/cloaks.dmi'
- icon_override = 'icons/mob/citadel/suit.dmi'
- icon_state = "festivecloak"
- item_state = "festiveloak"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "festive-i"
+ item_state = "festive-w"
+ icon_override = 'icons/obj/custom.dmi'
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS
@@ -119,9 +126,10 @@
/obj/item/clothing/mask/luchador/zigfie
name = "Alboroto Rosa mask"
- icon = 'icons/mob/mask.dmi'
- icon_state = "lucharzigfie"
- item_state = "lucharzigfie"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "lucharzigfie-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "lucharzigfie-w"
/*PLACEHOLDER*/
@@ -159,8 +167,10 @@
/obj/item/clothing/suit/trenchcoat/green
name = "Reece's Great Coat"
desc = "You would swear this was in your nightmares after eating too many veggies."
- icon_state = "hos-g"
- item_state = "hos-g"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "hos-g-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "hos-g-w"
body_parts_covered = CHEST|GROIN|ARMS|LEGS
@@ -170,14 +180,15 @@
desc = "Every good russian spaceman knows it's a good idea to bring along a couple of pints of whiskey wherever they go."
icon = 'icons/obj/custom.dmi'
icon_state = "russianflask"
- item_state = "russianflask"
volume = 60
/obj/item/clothing/mask/gas/stalker
name = "S.T.A.L.K.E.R. mask"
desc = "Smells like reactor four."
- item_state = "stalker"
- icon_state = "stalker"
+ icon = 'icons/obj/custom.dmi'
+ item_state = "stalker-w"
+ icon_override = 'icons/obj/custom.dmi'
+ icon_state = "stalker-i"
/*Sylas*/
@@ -185,8 +196,9 @@
name = "collar"
desc = "It's a collar..."
icon = 'icons/obj/custom.dmi'
- icon_state = "petcollar-stripe"
- item_color = "petcollar-stripe"
+ icon_state = "petcollar-stripe-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "petcollar-stripe-w"
tagname = null
@@ -194,17 +206,21 @@
/obj/item/clothing/under/singery/custom
name = "bluish performer's outfit"
desc = "Just looking at this makes you want to sing."
- icon_state = "ssing"
- item_state = "ssing"
- item_color = "ssing"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "singer-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "singer-w"
+ item_color = "singer-i"
fitted = NO_FEMALE_UNIFORM
alternate_worn_layer = ABOVE_SHOES_LAYER
can_adjust = 0
/obj/item/clothing/shoes/sneakers/pink
- icon_state = "pink"
- item_state = "pink"
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "pink-i"
+ icon_override = 'icons/obj/custom.dmi'
+ item_state = "pink-w"
/*Fractious*/
@@ -212,10 +228,8 @@
/obj/item/clothing/suit/vermillion
name = "vermillion clothing"
desc = "Some clothing."
- icon_state = "vermillion-w"
- item_state = "vermillion-i"
+ icon_state = "vermillion-i"
+ item_state = "vermillion-w"
body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS
icon = 'icons/obj/custom.dmi'
-
-
-
+ icon_override = 'icons/obj/custom.dmi'
diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm
index f165717a31..e21db3e094 100644
--- a/code/datums/components/riding.dm
+++ b/code/datums/components/riding.dm
@@ -1,326 +1,326 @@
-/datum/component/riding
- var/next_vehicle_move = 0 //used for move delays
- var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
- var/keytype
-
- var/slowed = FALSE
- var/slowvalue = 1
-
- var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one.
- var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change.
- var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py)
- var/list/allowed_turf_typecache
- var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence.
- var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more.
- var/override_allow_spacemove = FALSE
- var/drive_verb = "drive"
- var/ride_check_rider_incapacitated = FALSE
- var/ride_check_rider_restrained = FALSE
- var/ride_check_ridden_incapacitated = FALSE
-
-/datum/component/riding/Initialize()
- if(!ismovableatom(parent))
- . = COMPONENT_INCOMPATIBLE
- CRASH("RIDING COMPONENT ASSIGNED TO NON ATOM MOVABLE!")
- RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle)
- RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle)
- RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
-
-/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE)
- restore_position(M)
- unequip_buckle_inhands(M)
-
-/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE)
- handle_vehicle_offsets()
-
-/datum/component/riding/proc/handle_vehicle_layer()
- var/atom/movable/AM = parent
- var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER)
- . = defaults["[AM.dir]"]
- if(directional_vehicle_layers["[AM.dir]"])
- . = directional_vehicle_layers["[AM.dir]"]
- if(isnull(.)) //you can set it to null to not change it.
- . = AM.layer
- AM.layer = .
-
-/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer)
- directional_vehicle_layers["[dir]"] = layer
-
-/datum/component/riding/proc/vehicle_moved()
- var/atom/movable/AM = parent
- for(var/i in AM.buckled_mobs)
- ride_check(i)
- handle_vehicle_offsets()
- handle_vehicle_layer()
-
-/datum/component/riding/proc/ride_check(mob/living/M)
- var/atom/movable/AM = parent
- var/mob/AMM = AM
- if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE)))
- AM.visible_message("[M] falls off of [AM]!")
- AM.unbuckle_mob(M)
- return TRUE
-
-/datum/component/riding/proc/force_dismount(mob/living/M)
- var/atom/movable/AM = parent
- AM.unbuckle_mob(M)
-
-/datum/component/riding/proc/handle_vehicle_offsets()
- var/atom/movable/AM = parent
- var/AM_dir = "[AM.dir]"
- var/passindex = 0
- if(AM.has_buckled_mobs())
- for(var/m in AM.buckled_mobs)
- passindex++
- var/mob/living/buckled_mob = m
- var/list/offsets = get_offsets(passindex)
- var/rider_dir = get_rider_dir(passindex)
- buckled_mob.setDir(rider_dir)
- dir_loop:
- for(var/offsetdir in offsets)
- if(offsetdir == AM_dir)
- var/list/diroffsets = offsets[offsetdir]
- buckled_mob.pixel_x = diroffsets[1]
- if(diroffsets.len >= 2)
- buckled_mob.pixel_y = diroffsets[2]
- if(diroffsets.len == 3)
- buckled_mob.layer = diroffsets[3]
- break dir_loop
- var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
- var/px = default_vehicle_pixel_offsets[AM_dir]
- var/py = default_vehicle_pixel_offsets[AM_dir]
- if(directional_vehicle_offsets[AM_dir])
- if(isnull(directional_vehicle_offsets[AM_dir]))
- px = AM.pixel_x
- py = AM.pixel_y
- else
- px = directional_vehicle_offsets[AM_dir][1]
- py = directional_vehicle_offsets[AM_dir][2]
- AM.pixel_x = px
- AM.pixel_y = py
-
-/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y)
- directional_vehicle_offsets["[dir]"] = list(x, y)
-
-//Override this to set your vehicle's various pixel offsets
-/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
- . = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
- if(riding_offsets["[pass_index]"])
- . = riding_offsets["[pass_index]"]
- else if(riding_offsets["[RIDING_OFFSET_ALL]"])
- . = riding_offsets["[RIDING_OFFSET_ALL]"]
-
-/datum/component/riding/proc/set_riding_offsets(index, list/offsets)
- if(!islist(offsets))
- return FALSE
- riding_offsets["[index]"] = offsets
-
-//Override this to set the passengers/riders dir based on which passenger they are.
-//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc.
-/datum/component/riding/proc/get_rider_dir(pass_index)
- var/atom/movable/AM = parent
- return AM.dir
-
-//KEYS
-/datum/component/riding/proc/keycheck(mob/user)
- return !keytype || user.is_holding_item_of_type(keytype)
-
-//BUCKLE HOOKS
-/datum/component/riding/proc/restore_position(mob/living/buckled_mob)
- if(buckled_mob)
- buckled_mob.pixel_x = 0
- buckled_mob.pixel_y = 0
- if(buckled_mob.client)
- buckled_mob.client.change_view(CONFIG_GET(string/default_view))
-
-//MOVEMENT
-/datum/component/riding/proc/turf_check(turf/next, turf/current)
- if(allowed_turf_typecache && !allowed_turf_typecache[next.type])
- return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type])
- else if(forbid_turf_typecache && forbid_turf_typecache[next.type])
- return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type])
- return TRUE
-
-/datum/component/riding/proc/handle_ride(mob/user, direction)
- var/atom/movable/AM = parent
- if(user.incapacitated())
- Unbuckle(user)
- return
-
- if(world.time < next_vehicle_move)
- return
- next_vehicle_move = world.time + vehicle_move_delay
-
- if(keycheck(user))
- var/turf/next = get_step(AM, direction)
- var/turf/current = get_turf(AM)
- if(!istype(next) || !istype(current))
- return //not happening.
- if(!turf_check(next, current))
- to_chat(user, "Your \the [AM] can not go onto [next]!")
- return
- if(!Process_Spacemove(direction) || !isturf(AM.loc))
- return
- step(AM, direction)
-
- handle_vehicle_layer()
- handle_vehicle_offsets()
- else
- to_chat(user, "You'll need the keys in one of your hands to [drive_verb] [AM].")
-
-/datum/component/riding/proc/Unbuckle(atom/movable/M)
- addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE)
-
-/datum/component/riding/proc/Process_Spacemove(direction)
- var/atom/movable/AM = parent
- return override_allow_spacemove || AM.has_gravity()
-
-/datum/component/riding/proc/account_limbs(mob/living/M)
- if(M.get_num_legs() < 2 && !slowed)
- vehicle_move_delay = vehicle_move_delay + slowvalue
- slowed = TRUE
- else if(slowed)
- vehicle_move_delay = vehicle_move_delay - slowvalue
- slowed = FALSE
-
-///////Yes, I said humans. No, this won't end well...//////////
-/datum/component/riding/human
-
-/datum/component/riding/human/Initialize()
- . = ..()
- RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
-
-/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
- var/mob/living/carbon/human/AM = parent
- if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
- force_dismount(target)
-
-/datum/component/riding/human/handle_vehicle_layer()
- var/atom/movable/AM = parent
- if(AM.buckled_mobs && AM.buckled_mobs.len)
- if(AM.dir == SOUTH)
- AM.layer = ABOVE_MOB_LAYER
- else
- AM.layer = OBJ_LAYER
- else
- AM.layer = MOB_LAYER
-
-/datum/component/riding/human/force_dismount(mob/living/user)
- var/atom/movable/AM = parent
- AM.unbuckle_mob(user)
- user.Knockdown(60)
- user.visible_message("[AM] pushes [user] off of them!")
-
-/datum/component/riding/cyborg
-
-/datum/component/riding/cyborg/ride_check(mob/user)
- var/atom/movable/AM = parent
- if(user.incapacitated())
- var/kick = TRUE
- if(iscyborg(AM))
- var/mob/living/silicon/robot/R = AM
- if(R.module && R.module.ride_allow_incapacitated)
- kick = FALSE
- if(kick)
- to_chat(user, "You fall off of [AM]!")
- Unbuckle(user)
- return
- if(iscarbon(user))
- var/mob/living/carbon/carbonuser = user
- if(!carbonuser.get_num_arms())
- Unbuckle(user)
- to_chat(user, "You can't grab onto [AM] with no hands!")
- return
-
-/datum/component/riding/cyborg/handle_vehicle_layer()
- var/atom/movable/AM = parent
- if(AM.buckled_mobs && AM.buckled_mobs.len)
- if(AM.dir == SOUTH)
- AM.layer = ABOVE_MOB_LAYER
- else
- AM.layer = OBJ_LAYER
- else
- AM.layer = MOB_LAYER
-
-/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
- return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3))
-
-/datum/component/riding/cyborg/handle_vehicle_offsets()
- var/atom/movable/AM = parent
- if(AM.has_buckled_mobs())
- for(var/mob/living/M in AM.buckled_mobs)
- M.setDir(AM.dir)
- if(iscyborg(AM))
- var/mob/living/silicon/robot/R = AM
- if(istype(R.module))
- M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)]
- M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)]
- else
- ..()
-
-/datum/component/riding/cyborg/force_dismount(mob/living/M)
- var/atom/movable/AM = parent
- AM.unbuckle_mob(M)
- var/turf/target = get_edge_target_turf(AM, AM.dir)
- var/turf/targetm = get_step(get_turf(AM), AM.dir)
- M.Move(targetm)
- M.visible_message("[M] is thrown clear of [AM]!")
- M.throw_at(target, 14, 5, AM)
- M.Knockdown(60)
-
-/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
- var/atom/movable/AM = parent
- var/amount_equipped = 0
- for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
- var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
- inhand.rider = user
- inhand.parent = AM
- if(user.put_in_hands(inhand, TRUE))
- amount_equipped++
- else
- break
- if(amount_equipped >= amount_required)
- return TRUE
- else
- unequip_buckle_inhands(user)
- return FALSE
-
-/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
- var/atom/movable/AM = parent
- for(var/obj/item/riding_offhand/O in user.contents)
- if(O.parent != AM)
- CRASH("RIDING OFFHAND ON WRONG MOB")
- continue
- if(O.selfdeleting)
- continue
- else
- qdel(O)
- return TRUE
-
-/obj/item/riding_offhand
- name = "offhand"
- icon = 'icons/obj/items_and_weapons.dmi'
- icon_state = "offhand"
- w_class = WEIGHT_CLASS_HUGE
- flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- var/mob/living/carbon/rider
- var/mob/living/parent
- var/selfdeleting = FALSE
-
-/obj/item/riding_offhand/dropped()
- selfdeleting = TRUE
- . = ..()
-
-/obj/item/riding_offhand/equipped()
- if(loc != rider)
- selfdeleting = TRUE
- qdel(src)
- . = ..()
-
-/obj/item/riding_offhand/Destroy()
- var/atom/movable/AM = parent
- if(selfdeleting)
- if(rider in AM.buckled_mobs)
- AM.unbuckle_mob(rider)
- . = ..()
+/datum/component/riding
+ var/next_vehicle_move = 0 //used for move delays
+ var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower
+ var/keytype
+
+ var/slowed = FALSE
+ var/slowvalue = 1
+
+ var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one.
+ var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change.
+ var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py)
+ var/list/allowed_turf_typecache
+ var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence.
+ var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more.
+ var/override_allow_spacemove = FALSE
+ var/drive_verb = "drive"
+ var/ride_check_rider_incapacitated = FALSE
+ var/ride_check_rider_restrained = FALSE
+ var/ride_check_ridden_incapacitated = FALSE
+
+/datum/component/riding/Initialize()
+ if(!ismovableatom(parent))
+ . = COMPONENT_INCOMPATIBLE
+ CRASH("RIDING COMPONENT ASSIGNED TO NON ATOM MOVABLE!")
+ RegisterSignal(COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle)
+ RegisterSignal(COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle)
+ RegisterSignal(COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
+
+/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE)
+ restore_position(M)
+ unequip_buckle_inhands(M)
+
+/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE)
+ handle_vehicle_offsets()
+
+/datum/component/riding/proc/handle_vehicle_layer()
+ var/atom/movable/AM = parent
+ var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER)
+ . = defaults["[AM.dir]"]
+ if(directional_vehicle_layers["[AM.dir]"])
+ . = directional_vehicle_layers["[AM.dir]"]
+ if(isnull(.)) //you can set it to null to not change it.
+ . = AM.layer
+ AM.layer = .
+
+/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer)
+ directional_vehicle_layers["[dir]"] = layer
+
+/datum/component/riding/proc/vehicle_moved()
+ var/atom/movable/AM = parent
+ for(var/i in AM.buckled_mobs)
+ ride_check(i)
+ handle_vehicle_offsets()
+ handle_vehicle_layer()
+
+/datum/component/riding/proc/ride_check(mob/living/M)
+ var/atom/movable/AM = parent
+ var/mob/AMM = AM
+ if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE)))
+ AM.visible_message("[M] falls off of [AM]!")
+ AM.unbuckle_mob(M)
+ return TRUE
+
+/datum/component/riding/proc/force_dismount(mob/living/M)
+ var/atom/movable/AM = parent
+ AM.unbuckle_mob(M)
+
+/datum/component/riding/proc/handle_vehicle_offsets()
+ var/atom/movable/AM = parent
+ var/AM_dir = "[AM.dir]"
+ var/passindex = 0
+ if(AM.has_buckled_mobs())
+ for(var/m in AM.buckled_mobs)
+ passindex++
+ var/mob/living/buckled_mob = m
+ var/list/offsets = get_offsets(passindex)
+ var/rider_dir = get_rider_dir(passindex)
+ buckled_mob.setDir(rider_dir)
+ dir_loop:
+ for(var/offsetdir in offsets)
+ if(offsetdir == AM_dir)
+ var/list/diroffsets = offsets[offsetdir]
+ buckled_mob.pixel_x = diroffsets[1]
+ if(diroffsets.len >= 2)
+ buckled_mob.pixel_y = diroffsets[2]
+ if(diroffsets.len == 3)
+ buckled_mob.layer = diroffsets[3]
+ break dir_loop
+ var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
+ var/px = default_vehicle_pixel_offsets[AM_dir]
+ var/py = default_vehicle_pixel_offsets[AM_dir]
+ if(directional_vehicle_offsets[AM_dir])
+ if(isnull(directional_vehicle_offsets[AM_dir]))
+ px = AM.pixel_x
+ py = AM.pixel_y
+ else
+ px = directional_vehicle_offsets[AM_dir][1]
+ py = directional_vehicle_offsets[AM_dir][2]
+ AM.pixel_x = px
+ AM.pixel_y = py
+
+/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y)
+ directional_vehicle_offsets["[dir]"] = list(x, y)
+
+//Override this to set your vehicle's various pixel offsets
+/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer)
+ . = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0))
+ if(riding_offsets["[pass_index]"])
+ . = riding_offsets["[pass_index]"]
+ else if(riding_offsets["[RIDING_OFFSET_ALL]"])
+ . = riding_offsets["[RIDING_OFFSET_ALL]"]
+
+/datum/component/riding/proc/set_riding_offsets(index, list/offsets)
+ if(!islist(offsets))
+ return FALSE
+ riding_offsets["[index]"] = offsets
+
+//Override this to set the passengers/riders dir based on which passenger they are.
+//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc.
+/datum/component/riding/proc/get_rider_dir(pass_index)
+ var/atom/movable/AM = parent
+ return AM.dir
+
+//KEYS
+/datum/component/riding/proc/keycheck(mob/user)
+ return !keytype || user.is_holding_item_of_type(keytype)
+
+//BUCKLE HOOKS
+/datum/component/riding/proc/restore_position(mob/living/buckled_mob)
+ if(buckled_mob)
+ buckled_mob.pixel_x = 0
+ buckled_mob.pixel_y = 0
+ if(buckled_mob.client)
+ buckled_mob.client.change_view(CONFIG_GET(string/default_view))
+
+//MOVEMENT
+/datum/component/riding/proc/turf_check(turf/next, turf/current)
+ if(allowed_turf_typecache && !allowed_turf_typecache[next.type])
+ return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type])
+ else if(forbid_turf_typecache && forbid_turf_typecache[next.type])
+ return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type])
+ return TRUE
+
+/datum/component/riding/proc/handle_ride(mob/user, direction)
+ var/atom/movable/AM = parent
+ if(user.incapacitated())
+ Unbuckle(user)
+ return
+
+ if(world.time < next_vehicle_move)
+ return
+ next_vehicle_move = world.time + vehicle_move_delay
+
+ if(keycheck(user))
+ var/turf/next = get_step(AM, direction)
+ var/turf/current = get_turf(AM)
+ if(!istype(next) || !istype(current))
+ return //not happening.
+ if(!turf_check(next, current))
+ to_chat(user, "Your \the [AM] can not go onto [next]!")
+ return
+ if(!Process_Spacemove(direction) || !isturf(AM.loc))
+ return
+ step(AM, direction)
+
+ handle_vehicle_layer()
+ handle_vehicle_offsets()
+ else
+ to_chat(user, "You'll need the keys in one of your hands to [drive_verb] [AM].")
+
+/datum/component/riding/proc/Unbuckle(atom/movable/M)
+ addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE)
+
+/datum/component/riding/proc/Process_Spacemove(direction)
+ var/atom/movable/AM = parent
+ return override_allow_spacemove || AM.has_gravity()
+
+/datum/component/riding/proc/account_limbs(mob/living/M)
+ if(M.get_num_legs() < 2 && !slowed)
+ vehicle_move_delay = vehicle_move_delay + slowvalue
+ slowed = TRUE
+ else if(slowed)
+ vehicle_move_delay = vehicle_move_delay - slowvalue
+ slowed = FALSE
+
+///////Yes, I said humans. No, this won't end well...//////////
+/datum/component/riding/human
+
+/datum/component/riding/human/Initialize()
+ . = ..()
+ RegisterSignal(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
+
+/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
+ var/mob/living/carbon/human/AM = parent
+ if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
+ force_dismount(target)
+
+/datum/component/riding/human/handle_vehicle_layer()
+ var/atom/movable/AM = parent
+ if(AM.buckled_mobs && AM.buckled_mobs.len)
+ if(AM.dir == SOUTH)
+ AM.layer = ABOVE_MOB_LAYER
+ else
+ AM.layer = OBJ_LAYER
+ else
+ AM.layer = MOB_LAYER
+
+/datum/component/riding/human/force_dismount(mob/living/user)
+ var/atom/movable/AM = parent
+ AM.unbuckle_mob(user)
+ user.Knockdown(60)
+ user.visible_message("[AM] pushes [user] off of them!")
+
+/datum/component/riding/cyborg
+
+/datum/component/riding/cyborg/ride_check(mob/user)
+ var/atom/movable/AM = parent
+ if(user.incapacitated())
+ var/kick = TRUE
+ if(iscyborg(AM))
+ var/mob/living/silicon/robot/R = AM
+ if(R.module && R.module.ride_allow_incapacitated)
+ kick = FALSE
+ if(kick)
+ to_chat(user, "You fall off of [AM]!")
+ Unbuckle(user)
+ return
+ if(iscarbon(user))
+ var/mob/living/carbon/carbonuser = user
+ if(!carbonuser.get_num_arms())
+ Unbuckle(user)
+ to_chat(user, "You can't grab onto [AM] with no hands!")
+ return
+
+/datum/component/riding/cyborg/handle_vehicle_layer()
+ var/atom/movable/AM = parent
+ if(AM.buckled_mobs && AM.buckled_mobs.len)
+ if(AM.dir == SOUTH)
+ AM.layer = ABOVE_MOB_LAYER
+ else
+ AM.layer = OBJ_LAYER
+ else
+ AM.layer = MOB_LAYER
+
+/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer)
+ return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3))
+
+/datum/component/riding/cyborg/handle_vehicle_offsets()
+ var/atom/movable/AM = parent
+ if(AM.has_buckled_mobs())
+ for(var/mob/living/M in AM.buckled_mobs)
+ M.setDir(AM.dir)
+ if(iscyborg(AM))
+ var/mob/living/silicon/robot/R = AM
+ if(istype(R.module))
+ M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)]
+ M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)]
+ else
+ ..()
+
+/datum/component/riding/cyborg/force_dismount(mob/living/M)
+ var/atom/movable/AM = parent
+ AM.unbuckle_mob(M)
+ var/turf/target = get_edge_target_turf(AM, AM.dir)
+ var/turf/targetm = get_step(get_turf(AM), AM.dir)
+ M.Move(targetm)
+ M.visible_message("[M] is thrown clear of [AM]!")
+ M.throw_at(target, 14, 5, AM)
+ M.Knockdown(60)
+
+/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
+ var/atom/movable/AM = parent
+ var/amount_equipped = 0
+ for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
+ var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
+ inhand.rider = user
+ inhand.parent = AM
+ if(user.put_in_hands(inhand, TRUE))
+ amount_equipped++
+ else
+ break
+ if(amount_equipped >= amount_required)
+ return TRUE
+ else
+ unequip_buckle_inhands(user)
+ return FALSE
+
+/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
+ var/atom/movable/AM = parent
+ for(var/obj/item/riding_offhand/O in user.contents)
+ if(O.parent != AM)
+ CRASH("RIDING OFFHAND ON WRONG MOB")
+ continue
+ if(O.selfdeleting)
+ continue
+ else
+ qdel(O)
+ return TRUE
+
+/obj/item/riding_offhand
+ name = "offhand"
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "offhand"
+ w_class = WEIGHT_CLASS_HUGE
+ flags_1 = ABSTRACT_1 | DROPDEL_1 | NOBLUDGEON_1
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ var/mob/living/carbon/rider
+ var/mob/living/parent
+ var/selfdeleting = FALSE
+
+/obj/item/riding_offhand/dropped()
+ selfdeleting = TRUE
+ . = ..()
+
+/obj/item/riding_offhand/equipped()
+ if(loc != rider)
+ selfdeleting = TRUE
+ qdel(src)
+ . = ..()
+
+/obj/item/riding_offhand/Destroy()
+ var/atom/movable/AM = parent
+ if(selfdeleting)
+ if(rider in AM.buckled_mobs)
+ AM.unbuckle_mob(rider)
+ . = ..()
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index 407965aeb9..175ac9469c 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -1,204 +1,204 @@
-GLOBAL_LIST_EMPTY(uplinks)
-
-/**
- * Uplinks
- *
- * All /obj/item(s) have a hidden_uplink var. By default it's null. Give the item one with 'new(src') (it must be in it's contents). Then add 'uses.'
- * Use whatever conditionals you want to check that the user has an uplink, and then call interact() on their uplink.
- * You might also want the uplink menu to open if active. Check if the uplink is 'active' and then interact() with it.
-**/
-/datum/component/uplink
- dupe_mode = COMPONENT_DUPE_UNIQUE
- var/name = "syndicate uplink"
- var/active = FALSE
- var/lockable = TRUE
- var/locked = TRUE
- var/telecrystals
- var/selected_cat
- var/owner = null
- var/datum/game_mode/gamemode
- var/spent_telecrystals = 0
- var/datum/uplink_purchase_log/purchase_log
- var/list/uplink_items
- var/hidden_crystals = 0
-
-/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
- if(!isitem(parent))
- return COMPONENT_INCOMPATIBLE
- GLOB.uplinks += src
- uplink_items = get_uplink_items(gamemode)
- RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
- RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/interact)
- owner = _owner
- if(owner)
- LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
- if(GLOB.uplink_purchase_logs_by_key[owner])
- purchase_log = GLOB.uplink_purchase_logs_by_key[owner]
- else
- purchase_log = new(owner, src)
- lockable = _lockable
- active = _enabled
- gamemode = _gamemode
- telecrystals = starting_tc
- if(!lockable)
- active = TRUE
- locked = FALSE
-
-/datum/component/uplink/InheritComponent(datum/component/uplink/U)
- lockable |= U.lockable
- active |= U.active
- if(!gamemode)
- gamemode = U.gamemode
- telecrystals += U.telecrystals
- if(purchase_log && U.purchase_log)
- purchase_log.MergeWithAndDel(U.purchase_log)
-
-/datum/component/uplink/Destroy()
- GLOB.uplinks -= src
- gamemode = null
- return ..()
-
-/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
- if(!silent)
- to_chat(user, "You slot [TC] into [parent] and charge its internal uplink.")
- var/amt = TC.amount
- telecrystals += amt
- TC.use(amt)
-
-/datum/component/uplink/proc/set_gamemode(_gamemode)
- gamemode = _gamemode
- uplink_items = get_uplink_items(gamemode)
-
-/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user)
- if(!active)
- return //no hitting everyone/everything just to try to slot tcs in!
- if(istype(I, /obj/item/stack/telecrystal))
- LoadTC(user, I)
- for(var/item in subtypesof(/datum/uplink_item))
- var/datum/uplink_item/UI = item
- var/path = null
- if(initial(UI.refund_path))
- path = initial(UI.refund_path)
- else
- path = initial(UI.item)
- var/cost = 0
- if(initial(UI.refund_amount))
- cost = initial(UI.refund_amount)
- else
- cost = initial(UI.cost)
- var/refundable = initial(UI.refundable)
- if(I.type == path && refundable && I.check_uplink_validity())
- telecrystals += cost
- spent_telecrystals -= cost
- to_chat(user, "[I] refunded.")
- qdel(I)
- return
-
-/datum/component/uplink/proc/interact(mob/user)
- if(locked)
- return
- active = TRUE
- if(user)
- ui_interact(user)
-
-/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
- datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
- active = TRUE
- ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state)
- ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
- ui.set_style("syndicate")
- ui.open()
-
-/datum/component/uplink/ui_data(mob/user)
- if(!user.mind)
- return
- var/list/data = list()
- data["telecrystals"] = telecrystals
- data["lockable"] = lockable
-
- data["categories"] = list()
- for(var/category in uplink_items)
- var/list/cat = list(
- "name" = category,
- "items" = (category == selected_cat ? list() : null))
- if(category == selected_cat)
- for(var/item in uplink_items[category])
- var/datum/uplink_item/I = uplink_items[category][item]
- if(I.limited_stock == 0)
- continue
- if(I.restricted_roles.len)
- var/is_inaccessible = 1
- for(var/R in I.restricted_roles)
- if(R == user.mind.assigned_role)
- is_inaccessible = 0
- if(is_inaccessible)
- continue
- cat["items"] += list(list(
- "name" = I.name,
- "cost" = I.cost,
- "desc" = I.desc,
- ))
- data["categories"] += list(cat)
- return data
-
-/datum/component/uplink/ui_act(action, params)
- if(!active)
- return
-
- switch(action)
- if("buy")
- var/item = params["item"]
-
- var/list/buyable_items = list()
- for(var/category in uplink_items)
- buyable_items += uplink_items[category]
-
- if(item in buyable_items)
- var/datum/uplink_item/I = buyable_items[item]
- MakePurchase(usr, I)
- . = TRUE
- if("lock")
- active = FALSE
- locked = TRUE
- telecrystals += hidden_crystals
- hidden_crystals = 0
- SStgui.close_uis(src)
- if("select")
- selected_cat = params["category"]
- return TRUE
-
-/datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U)
- if(!istype(U))
- return
- if (!user || user.incapacitated())
- return
-
- if(telecrystals < U.cost || U.limited_stock == 0)
- return
- telecrystals -= U.cost
-
- var/atom/A = U.spawn_item(get_turf(user), src, user)
- if(U.purchase_log_vis && purchase_log)
- var/obj/item/storage/box/B = A
- var/list/atom/logging = list()
- if(istype(B) && B.contents.len > 0)
- logging |= list(B)
- else
- logging |= A
- for(var/atom/_logging in logging)
- purchase_log.LogPurchase(_logging, U.cost)
-
- if(U.limited_stock > 0)
- U.limited_stock -= 1
-
- SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(U.name)]", "[U.cost]"))
- if(ishuman(user) && istype(A, /obj/item))
- var/mob/living/carbon/human/H = user
- if(H.put_in_hands(A))
- to_chat(H, "[A] materializes into your hands!")
- else
- to_chat(H, "\The [A] materializes onto the floor.")
- return TRUE
-
+GLOBAL_LIST_EMPTY(uplinks)
+
+/**
+ * Uplinks
+ *
+ * All /obj/item(s) have a hidden_uplink var. By default it's null. Give the item one with 'new(src') (it must be in it's contents). Then add 'uses.'
+ * Use whatever conditionals you want to check that the user has an uplink, and then call interact() on their uplink.
+ * You might also want the uplink menu to open if active. Check if the uplink is 'active' and then interact() with it.
+**/
+/datum/component/uplink
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+ var/name = "syndicate uplink"
+ var/active = FALSE
+ var/lockable = TRUE
+ var/locked = TRUE
+ var/telecrystals
+ var/selected_cat
+ var/owner = null
+ var/datum/game_mode/gamemode
+ var/spent_telecrystals = 0
+ var/datum/uplink_purchase_log/purchase_log
+ var/list/uplink_items
+ var/hidden_crystals = 0
+
+/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+ GLOB.uplinks += src
+ uplink_items = get_uplink_items(gamemode)
+ RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
+ RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/interact)
+ owner = _owner
+ if(owner)
+ LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
+ if(GLOB.uplink_purchase_logs_by_key[owner])
+ purchase_log = GLOB.uplink_purchase_logs_by_key[owner]
+ else
+ purchase_log = new(owner, src)
+ lockable = _lockable
+ active = _enabled
+ gamemode = _gamemode
+ telecrystals = starting_tc
+ if(!lockable)
+ active = TRUE
+ locked = FALSE
+
+/datum/component/uplink/InheritComponent(datum/component/uplink/U)
+ lockable |= U.lockable
+ active |= U.active
+ if(!gamemode)
+ gamemode = U.gamemode
+ telecrystals += U.telecrystals
+ if(purchase_log && U.purchase_log)
+ purchase_log.MergeWithAndDel(U.purchase_log)
+
+/datum/component/uplink/Destroy()
+ GLOB.uplinks -= src
+ gamemode = null
+ return ..()
+
+/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
+ if(!silent)
+ to_chat(user, "You slot [TC] into [parent] and charge its internal uplink.")
+ var/amt = TC.amount
+ telecrystals += amt
+ TC.use(amt)
+
+/datum/component/uplink/proc/set_gamemode(_gamemode)
+ gamemode = _gamemode
+ uplink_items = get_uplink_items(gamemode)
+
+/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user)
+ if(!active)
+ return //no hitting everyone/everything just to try to slot tcs in!
+ if(istype(I, /obj/item/stack/telecrystal))
+ LoadTC(user, I)
+ for(var/item in subtypesof(/datum/uplink_item))
+ var/datum/uplink_item/UI = item
+ var/path = null
+ if(initial(UI.refund_path))
+ path = initial(UI.refund_path)
+ else
+ path = initial(UI.item)
+ var/cost = 0
+ if(initial(UI.refund_amount))
+ cost = initial(UI.refund_amount)
+ else
+ cost = initial(UI.cost)
+ var/refundable = initial(UI.refundable)
+ if(I.type == path && refundable && I.check_uplink_validity())
+ telecrystals += cost
+ spent_telecrystals -= cost
+ to_chat(user, "[I] refunded.")
+ qdel(I)
+ return
+
+/datum/component/uplink/proc/interact(mob/user)
+ if(locked)
+ return
+ active = TRUE
+ if(user)
+ ui_interact(user)
+
+/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
+ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
+ active = TRUE
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "uplink", name, 450, 750, master_ui, state)
+ ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
+ ui.set_style("syndicate")
+ ui.open()
+
+/datum/component/uplink/ui_data(mob/user)
+ if(!user.mind)
+ return
+ var/list/data = list()
+ data["telecrystals"] = telecrystals
+ data["lockable"] = lockable
+
+ data["categories"] = list()
+ for(var/category in uplink_items)
+ var/list/cat = list(
+ "name" = category,
+ "items" = (category == selected_cat ? list() : null))
+ if(category == selected_cat)
+ for(var/item in uplink_items[category])
+ var/datum/uplink_item/I = uplink_items[category][item]
+ if(I.limited_stock == 0)
+ continue
+ if(I.restricted_roles.len)
+ var/is_inaccessible = 1
+ for(var/R in I.restricted_roles)
+ if(R == user.mind.assigned_role)
+ is_inaccessible = 0
+ if(is_inaccessible)
+ continue
+ cat["items"] += list(list(
+ "name" = I.name,
+ "cost" = I.cost,
+ "desc" = I.desc,
+ ))
+ data["categories"] += list(cat)
+ return data
+
+/datum/component/uplink/ui_act(action, params)
+ if(!active)
+ return
+
+ switch(action)
+ if("buy")
+ var/item = params["item"]
+
+ var/list/buyable_items = list()
+ for(var/category in uplink_items)
+ buyable_items += uplink_items[category]
+
+ if(item in buyable_items)
+ var/datum/uplink_item/I = buyable_items[item]
+ MakePurchase(usr, I)
+ . = TRUE
+ if("lock")
+ active = FALSE
+ locked = TRUE
+ telecrystals += hidden_crystals
+ hidden_crystals = 0
+ SStgui.close_uis(src)
+ if("select")
+ selected_cat = params["category"]
+ return TRUE
+
+/datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U)
+ if(!istype(U))
+ return
+ if (!user || user.incapacitated())
+ return
+
+ if(telecrystals < U.cost || U.limited_stock == 0)
+ return
+ telecrystals -= U.cost
+
+ var/atom/A = U.spawn_item(get_turf(user), src, user)
+ if(U.purchase_log_vis && purchase_log)
+ var/obj/item/storage/box/B = A
+ var/list/atom/logging = list()
+ if(istype(B) && B.contents.len > 0)
+ logging |= list(B)
+ else
+ logging |= A
+ for(var/atom/_logging in logging)
+ purchase_log.LogPurchase(_logging, U.cost)
+
+ if(U.limited_stock > 0)
+ U.limited_stock -= 1
+
+ SSblackbox.record_feedback("nested tally", "traitor_uplink_items_bought", 1, list("[initial(U.name)]", "[U.cost]"))
+ if(ishuman(user) && istype(A, /obj/item))
+ var/mob/living/carbon/human/H = user
+ if(H.put_in_hands(A))
+ to_chat(H, "[A] materializes into your hands!")
+ else
+ to_chat(H, "\The [A] materializes onto the floor.")
+ return TRUE
+
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 1cf172d3a6..b086854ab6 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -897,6 +897,9 @@
to_chat(user,"[src] suddenly vanishes!")
qdel(src)
+/obj/item/spellbook/oneuse/random
+ icon_state = "random_book"
+
/obj/item/spellbook/oneuse/random/Initialize()
..()
var/static/banned_spells = list(/obj/item/spellbook/oneuse/mimery_blockade, /obj/item/spellbook/oneuse/mimery_guns)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index e889a5d96f..eb51703642 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -678,6 +678,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/machinery/vending/snack/random
name = "\improper Random Snackies"
+ icon_state = "random_snack"
desc = "Uh oh!"
/obj/machinery/vending/snack/random/Initialize()
@@ -730,6 +731,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/machinery/vending/cola/random
name = "\improper Random Drinkies"
+ icon_state = "random_cola"
desc = "Uh oh!"
/obj/machinery/vending/cola/random/Initialize()
diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm
index 8ec32f088e..a3ad685406 100644
--- a/code/game/objects/items/cosmetics.dm
+++ b/code/game/objects/items/cosmetics.dm
@@ -25,9 +25,11 @@
/obj/item/lipstick/random
name = "lipstick"
+ icon_state = "random_lipstick"
/obj/item/lipstick/random/New()
..()
+ icon_state = "lipstick"
colour = pick("red","purple","lime","black","green","blue","white")
name = "[colour] lipstick"
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index fd56c6283f..a7b0eaaf25 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -488,16 +488,14 @@
/obj/item/device/flashlight/glowstick/random
name = "random colored glowstick"
+ icon_state = "random_glowstick"
+ color = null
/obj/item/device/flashlight/glowstick/random/Initialize()
- var/list/glowtypes = typesof(/obj/item/device/flashlight/glowstick)
- glowtypes -= /obj/item/device/flashlight/glowstick/random
-
- var/obj/item/device/flashlight/glowstick/glowtype = pick(glowtypes)
-
- name = initial(glowtype.name)
- color = initial(glowtype.color)
. = ..()
+ var/T = pick(typesof(/obj/item/device/flashlight/glowstick) - /obj/item/device/flashlight/glowstick/random)
+ new T(loc)
+ return INITIALIZE_HINT_QDEL
/obj/item/device/flashlight/spotlight //invisible lighting source
name = "disco light"
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index 912a083171..69b6e54841 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -289,6 +289,9 @@
fix()
//Random colour tapes
+/obj/item/device/tape/random
+ icon_state = "random_tape"
+
/obj/item/device/tape/random/New()
icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]"
..()
diff --git a/code/game/objects/items/devices/uplink_devices.dm b/code/game/objects/items/devices/uplink_devices.dm
index 3f3970fe51..2541b33e27 100644
--- a/code/game/objects/items/devices/uplink_devices.dm
+++ b/code/game/objects/items/devices/uplink_devices.dm
@@ -1,31 +1,31 @@
-
-// A collection of pre-set uplinks, for admin spawns.
-/obj/item/device/radio/uplink/Initialize(mapload, _owner, _tc_amount = 20)
- . = ..()
- icon_state = "radio"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount)
-
-/obj/item/device/radio/uplink/nuclear/Initialize()
- . = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
- hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
-
-/obj/item/device/multitool/uplink/Initialize(mapload, _owner, _tc_amount = 20)
- . = ..()
- LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount)
-
-/obj/item/pen/uplink/Initialize(mapload, _owner, _tc_amount = 20)
- . = ..()
- LoadComponent(/datum/component/uplink)
- traitor_unlock_degrees = 360
-
-/obj/item/device/radio/uplink/old
- name = "dusty radio"
- desc = "A dusty looking radio."
-
-/obj/item/device/radio/uplink/old/Initialize(mapload, _owner, _tc_amount = 10)
- . = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
- hidden_uplink.name = "dusty radio"
+
+// A collection of pre-set uplinks, for admin spawns.
+/obj/item/device/radio/uplink/Initialize(mapload, _owner, _tc_amount = 20)
+ . = ..()
+ icon_state = "radio"
+ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+ LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount)
+
+/obj/item/device/radio/uplink/nuclear/Initialize()
+ . = ..()
+ GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
+
+/obj/item/device/multitool/uplink/Initialize(mapload, _owner, _tc_amount = 20)
+ . = ..()
+ LoadComponent(/datum/component/uplink, _owner, FALSE, TRUE, null, _tc_amount)
+
+/obj/item/pen/uplink/Initialize(mapload, _owner, _tc_amount = 20)
+ . = ..()
+ LoadComponent(/datum/component/uplink)
+ traitor_unlock_degrees = 360
+
+/obj/item/device/radio/uplink/old
+ name = "dusty radio"
+ desc = "A dusty looking radio."
+
+/obj/item/device/radio/uplink/old/Initialize(mapload, _owner, _tc_amount = 10)
+ . = ..()
+ GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ hidden_uplink.name = "dusty radio"
diff --git a/code/game/objects/items/grenades/clusterbuster.dm b/code/game/objects/items/grenades/clusterbuster.dm
index 9f2cb1ab88..167c3114ec 100644
--- a/code/game/objects/items/grenades/clusterbuster.dm
+++ b/code/game/objects/items/grenades/clusterbuster.dm
@@ -129,6 +129,9 @@
//random clusterbuster spawner
+/obj/item/grenade/clusterbuster/random
+ icon_state = "random_clusterbang"
+
/obj/item/grenade/clusterbuster/random/New()
var/real_type = pick(subtypesof(/obj/item/grenade/clusterbuster))
new real_type(loc)
diff --git a/code/game/objects/items/implants/implantuplink.dm b/code/game/objects/items/implants/implantuplink.dm
index 5365f71ca7..d1d5adf4b5 100644
--- a/code/game/objects/items/implants/implantuplink.dm
+++ b/code/game/objects/items/implants/implantuplink.dm
@@ -1,49 +1,49 @@
-/obj/item/implant/uplink
- name = "uplink implant"
- desc = "Sneeki breeki."
- icon = 'icons/obj/radio.dmi'
- icon_state = "radio"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- var/starting_tc = 0
-
-/obj/item/implant/uplink/Initialize(mapload, _owner)
- . = ..()
- LoadComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
-
-/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0)
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
- if(hidden_uplink)
- for(var/X in target.implants)
- if(istype(X, type))
- var/obj/item/implant/imp_e = X
- GET_COMPONENT_FROM(their_hidden_uplink, /datum/component/uplink, imp_e)
- if(their_hidden_uplink)
- their_hidden_uplink.telecrystals += hidden_uplink.telecrystals
- qdel(src)
- return TRUE
- else
- qdel(imp_e) //INFERIOR AND EMPTY!
-
- if(..())
- if(hidden_uplink)
- hidden_uplink.owner = "[user.key]"
- return TRUE
- return FALSE
-
-/obj/item/implant/uplink/activate()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
- if(hidden_uplink)
- hidden_uplink.locked = FALSE
- hidden_uplink.interact(usr)
-
-/obj/item/implanter/uplink
- name = "implanter (uplink)"
- imp_type = /obj/item/implant/uplink
-
-/obj/item/implanter/uplink/precharged
- name = "implanter (precharged uplink)"
- imp_type = /obj/item/implant/uplink/precharged
-
-/obj/item/implant/uplink/precharged
- starting_tc = 10
+/obj/item/implant/uplink
+ name = "uplink implant"
+ desc = "Sneeki breeki."
+ icon = 'icons/obj/radio.dmi'
+ icon_state = "radio"
+ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+ var/starting_tc = 0
+
+/obj/item/implant/uplink/Initialize(mapload, _owner)
+ . = ..()
+ LoadComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc)
+
+/obj/item/implant/uplink/implant(mob/living/target, mob/user, silent = 0)
+ GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ if(hidden_uplink)
+ for(var/X in target.implants)
+ if(istype(X, type))
+ var/obj/item/implant/imp_e = X
+ GET_COMPONENT_FROM(their_hidden_uplink, /datum/component/uplink, imp_e)
+ if(their_hidden_uplink)
+ their_hidden_uplink.telecrystals += hidden_uplink.telecrystals
+ qdel(src)
+ return TRUE
+ else
+ qdel(imp_e) //INFERIOR AND EMPTY!
+
+ if(..())
+ if(hidden_uplink)
+ hidden_uplink.owner = "[user.key]"
+ return TRUE
+ return FALSE
+
+/obj/item/implant/uplink/activate()
+ GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ if(hidden_uplink)
+ hidden_uplink.locked = FALSE
+ hidden_uplink.interact(usr)
+
+/obj/item/implanter/uplink
+ name = "implanter (uplink)"
+ imp_type = /obj/item/implant/uplink
+
+/obj/item/implanter/uplink/precharged
+ name = "implanter (precharged uplink)"
+ imp_type = /obj/item/implant/uplink/precharged
+
+/obj/item/implant/uplink/precharged
+ starting_tc = 10
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index 7747c3843d..885dbc3830 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -72,6 +72,9 @@
else
return ..()
+/obj/item/storage/wallet/random
+ icon_state = "random_wallet"
+
/obj/item/storage/wallet/random/PopulateContents()
var/item1_type = pick( /obj/item/stack/spacecash/c10, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, /obj/item/stack/spacecash/c20, /obj/item/stack/spacecash/c200, /obj/item/stack/spacecash/c50, /obj/item/stack/spacecash/c500)
var/item2_type
@@ -86,3 +89,4 @@
new item2_type(src)
if(item3_type)
new item3_type(src)
+ update_icon()
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index 238c83725b..aa9acae22c 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -225,7 +225,7 @@ LINEN BINS
/obj/item/bedsheet/random
- icon_state = "sheetrainbow"
+ icon_state = "random_bedsheet"
item_color = "rainbow"
name = "random bedsheet"
desc = "If you're reading this description ingame, something has gone wrong! Honk!"
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 260285aff9..f7071cd0a5 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -285,10 +285,13 @@
user.remove_alt_appearance("sneaking_mission")
/obj/item/twohanded/required/kirbyplants/random
+ icon = 'icons/obj/flora/_flora.dmi'
+ icon_state = "random_plant"
var/list/static/states
/obj/item/twohanded/required/kirbyplants/random/Initialize()
. = ..()
+ icon = 'icons/obj/flora/plants.dmi'
if(!states)
generate_states()
icon_state = pick(states)
diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm
index e3a99fdb9a..b2b869edae 100644
--- a/code/modules/clothing/glasses/engine_goggles.dm
+++ b/code/modules/clothing/glasses/engine_goggles.dm
@@ -8,7 +8,8 @@
/obj/item/clothing/glasses/meson/engine
name = "engineering scanner goggles"
desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, the T-ray Scanner mode lets you see underfloor objects such as cables and pipes, and the Radiation Scanner mode let's you see objects contaminated by radiation."
- icon_state = "trayson"
+ icon_state = "trayson-meson"
+ item_state = "trayson-meson"
actions_types = list(/datum/action/item_action/toggle_mode)
origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3"
@@ -117,14 +118,22 @@
flick_overlay(pic, list(user.client), 8)
/obj/item/clothing/glasses/meson/engine/update_icon()
- icon_state = "[initial(icon_state)]-[mode]"
- if(istype(loc, /mob/living/carbon/human/))
- var/mob/living/carbon/human/user = loc
- if(user.glasses == src)
+ icon_state = "trayson-[mode]"
+ update_mob()
+
+/obj/item/clothing/glasses/meson/engine/proc/update_mob()
+ item_state = icon_state
+ if(isliving(loc))
+ var/mob/living/user = loc
+ if(user.get_item_by_slot(slot_glasses) == src)
user.update_inv_glasses()
+ else
+ user.update_inv_hands()
/obj/item/clothing/glasses/meson/engine/tray //atmos techs have lived far too long without tray goggles while those damned engineers get their dual-purpose gogles all to themselves
name = "optical t-ray scanner"
+ icon_state = "trayson-t-ray"
+ item_state = "trayson-t-ray"
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
origin_tech = "materials=3;magnets=2;engineering=2"
diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm
index 8b714f25dd..257318ce80 100644
--- a/code/modules/clothing/gloves/color.dm
+++ b/code/modules/clothing/gloves/color.dm
@@ -188,7 +188,7 @@
/obj/item/clothing/gloves/color/random
name = "random gloves"
desc = "These gloves are supposed to be a random color..."
- icon_state = "white"
+ icon_state = "random_gloves"
item_state = "wgloves"
item_color = "mime"
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
index 141336cf5d..4bf76a1a46 100644
--- a/code/modules/hydroponics/beekeeping/beebox.dm
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -58,6 +58,7 @@
/obj/structure/beebox/premade/New()
..()
+ icon_state = "beebox"
var/datum/reagent/R = null
if(random_reagent)
R = pick(subtypesof(/datum/reagent))
@@ -80,6 +81,7 @@
/obj/structure/beebox/premade/random
+ icon_state = "random_beebox"
random_reagent = TRUE
diff --git a/code/modules/library/random_books.dm b/code/modules/library/random_books.dm
index 769c9ac66b..e101a7143a 100644
--- a/code/modules/library/random_books.dm
+++ b/code/modules/library/random_books.dm
@@ -1,3 +1,6 @@
+/obj/item/book/manual/random
+ icon_state = "random_book"
+
/obj/item/book/manual/random/Initialize()
..()
var/static/banned_books = list(/obj/item/book/manual/random, /obj/item/book/manual/nuclear, /obj/item/book/manual/wiki)
@@ -6,6 +9,7 @@
return INITIALIZE_HINT_QDEL
/obj/item/book/random
+ icon_state = "random_book"
var/amount = 1
var/category = null
@@ -20,6 +24,7 @@
/obj/structure/bookcase/random
var/category = null
var/book_count = 2
+ icon_state = "random_bookcase"
anchored = TRUE
state = 2
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index a1f0dbf4be..5c24b15267 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -1,21 +1,21 @@
-/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0)
- if(ionpulse())
- return 1
- return ..()
-
-/mob/living/silicon/robot/movement_delay()
- . = ..()
- var/static/config_robot_delay
- if(isnull(config_robot_delay))
- config_robot_delay = CONFIG_GET(number/robot_delay)
- . += speed + config_robot_delay
-
-/mob/living/silicon/robot/mob_negates_gravity()
- return magpulse
-
-/mob/living/silicon/robot/mob_has_gravity()
- return ..() || mob_negates_gravity()
-
-/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
- if(!magpulse)
- return ..()
+/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0)
+ if(ionpulse())
+ return 1
+ return ..()
+
+/mob/living/silicon/robot/movement_delay()
+ . = ..()
+ var/static/config_robot_delay
+ if(isnull(config_robot_delay))
+ config_robot_delay = CONFIG_GET(number/robot_delay)
+ . += speed + config_robot_delay
+
+/mob/living/silicon/robot/mob_negates_gravity()
+ return magpulse
+
+/mob/living/silicon/robot/mob_has_gravity()
+ return ..() || mob_negates_gravity()
+
+/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
+ if(!magpulse)
+ return ..()
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index a4d766539f..bc92521b93 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -40,6 +40,9 @@
if(51 to INFINITY)
icon_state = "full"
+/obj/item/reagent_containers/blood/random
+ icon_state = "random_bloodpack"
+
/obj/item/reagent_containers/blood/random/Initialize()
blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L")
. = ..()
diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm
index ea3a05470a..32975e1e0f 100644
--- a/code/modules/vehicles/ridden.dm
+++ b/code/modules/vehicles/ridden.dm
@@ -1,76 +1,76 @@
-/obj/vehicle/ridden
- name = "ridden vehicle"
- can_buckle = TRUE
- max_buckled_mobs = 1
- buckle_lying = FALSE
- default_driver_move = FALSE
- var/legs_required = 2
- var/arms_requires = 0 //why not?
-
-/obj/vehicle/ridden/Initialize()
- . = ..()
- LoadComponent(/datum/component/riding)
-
-/obj/vehicle/ridden/examine(mob/user)
- . = ..()
- to_chat(user, "Put a key inside it by clicking it with the key. If there's a key inside, you can remove it via Alt-Click!")
-
-/obj/vehicle/ridden/generate_action_type(actiontype)
- var/datum/action/vehicle/ridden/A = ..()
- . = A
- if(istype(A))
- A.vehicle_ridden_target = src
-
-/obj/vehicle/ridden/post_unbuckle_mob(mob/living/M)
- remove_occupant(M)
- return ..()
-
-/obj/vehicle/ridden/post_buckle_mob(mob/living/M)
- add_occupant(M)
- return ..()
-
-/obj/vehicle/ridden/attackby(obj/item/I, mob/user, params)
- if(key_type && !is_key(inserted_key) && is_key(I))
- if(user.transferItemToLoc(I, src))
- to_chat(user, "You insert \the [I] into \the [src].")
- if(inserted_key) //just in case there's an invalid key
- inserted_key.forceMove(drop_location())
- inserted_key = I
- else
- to_chat(user, "[I] seems to be stuck to your hand!")
- return
- return ..()
-
-/obj/vehicle/ridden/AltClick(mob/user)
- if(user.Adjacent(src) && inserted_key)
- if(!is_occupant(user))
- to_chat(user, "You must be riding the [src] to remove [src]'s key!")
- return
- to_chat(user, "You remove \the [inserted_key] from \the [src].")
- inserted_key.forceMove(drop_location())
- user.put_in_hands(inserted_key)
- inserted_key = null
- return ..()
-
-/obj/vehicle/ridden/driver_move(mob/user, direction)
- if(key_type && !is_key(inserted_key))
- to_chat(user, "[src] has no key inserted!")
- return FALSE
- var/datum/component/riding/R = GetComponent(/datum/component/riding)
- R.handle_ride(user, direction)
- return ..()
-
-/obj/vehicle/ridden/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
- if(user.incapacitated())
- return
- for(var/atom/movable/A in get_turf(src))
- if(A.density)
- if(A != src && A != M)
- return
- M.forceMove(get_turf(src))
- . = ..()
-
-/obj/vehicle/ridden/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
- if(!force && occupant_amount() >= max_occupants)
- return FALSE
- return ..()
+/obj/vehicle/ridden
+ name = "ridden vehicle"
+ can_buckle = TRUE
+ max_buckled_mobs = 1
+ buckle_lying = FALSE
+ default_driver_move = FALSE
+ var/legs_required = 2
+ var/arms_requires = 0 //why not?
+
+/obj/vehicle/ridden/Initialize()
+ . = ..()
+ LoadComponent(/datum/component/riding)
+
+/obj/vehicle/ridden/examine(mob/user)
+ . = ..()
+ to_chat(user, "Put a key inside it by clicking it with the key. If there's a key inside, you can remove it via Alt-Click!")
+
+/obj/vehicle/ridden/generate_action_type(actiontype)
+ var/datum/action/vehicle/ridden/A = ..()
+ . = A
+ if(istype(A))
+ A.vehicle_ridden_target = src
+
+/obj/vehicle/ridden/post_unbuckle_mob(mob/living/M)
+ remove_occupant(M)
+ return ..()
+
+/obj/vehicle/ridden/post_buckle_mob(mob/living/M)
+ add_occupant(M)
+ return ..()
+
+/obj/vehicle/ridden/attackby(obj/item/I, mob/user, params)
+ if(key_type && !is_key(inserted_key) && is_key(I))
+ if(user.transferItemToLoc(I, src))
+ to_chat(user, "You insert \the [I] into \the [src].")
+ if(inserted_key) //just in case there's an invalid key
+ inserted_key.forceMove(drop_location())
+ inserted_key = I
+ else
+ to_chat(user, "[I] seems to be stuck to your hand!")
+ return
+ return ..()
+
+/obj/vehicle/ridden/AltClick(mob/user)
+ if(user.Adjacent(src) && inserted_key)
+ if(!is_occupant(user))
+ to_chat(user, "You must be riding the [src] to remove [src]'s key!")
+ return
+ to_chat(user, "You remove \the [inserted_key] from \the [src].")
+ inserted_key.forceMove(drop_location())
+ user.put_in_hands(inserted_key)
+ inserted_key = null
+ return ..()
+
+/obj/vehicle/ridden/driver_move(mob/user, direction)
+ if(key_type && !is_key(inserted_key))
+ to_chat(user, "[src] has no key inserted!")
+ return FALSE
+ var/datum/component/riding/R = GetComponent(/datum/component/riding)
+ R.handle_ride(user, direction)
+ return ..()
+
+/obj/vehicle/ridden/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
+ if(user.incapacitated())
+ return
+ for(var/atom/movable/A in get_turf(src))
+ if(A.density)
+ if(A != src && A != M)
+ return
+ M.forceMove(get_turf(src))
+ . = ..()
+
+/obj/vehicle/ridden/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
+ if(!force && occupant_amount() >= max_occupants)
+ return FALSE
+ return ..()
diff --git a/code/modules/vehicles/vehicle_actions.dm b/code/modules/vehicles/vehicle_actions.dm
index 79a24c8b11..865834495f 100644
--- a/code/modules/vehicles/vehicle_actions.dm
+++ b/code/modules/vehicles/vehicle_actions.dm
@@ -1,112 +1,112 @@
-//VEHICLE DEFAULT HANDLING
-/obj/vehicle/proc/generate_actions()
- return
-
-/obj/vehicle/proc/generate_action_type(actiontype)
- var/datum/action/vehicle/A = new actiontype
- if(!istype(A))
- return
- A.vehicle_target = src
- return A
-
-/obj/vehicle/proc/initialize_passenger_action_type(actiontype)
- autogrant_actions_passenger += actiontype
- for(var/i in occupants)
- grant_passenger_actions(i) //refresh
-
-/obj/vehicle/proc/initialize_controller_action_type(actiontype, control_flag)
- LAZYINITLIST(autogrant_actions_controller["[control_flag]"])
- autogrant_actions_controller["[control_flag]"] += actiontype
- for(var/i in occupants)
- grant_controller_actions(i) //refresh
-
-/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/m)
- if(!occupants[m] || !actiontype)
- return FALSE
- LAZYINITLIST(occupant_actions[m])
- if(occupant_actions[m][actiontype])
- return TRUE
- var/datum/action/action = generate_action_type(actiontype)
- action.Grant(m)
- occupant_actions[m][action.type] = action
- return TRUE
-
-/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/m)
- if(!occupants[m] || !actiontype)
- return FALSE
- LAZYINITLIST(occupant_actions[m])
- if(occupant_actions[m][actiontype])
- var/datum/action/action = occupant_actions[m][actiontype]
- action.Remove(m)
- occupant_actions[m] -= actiontype
- return TRUE
-
-/obj/vehicle/proc/grant_passenger_actions(mob/M)
- for(var/v in autogrant_actions_passenger)
- grant_action_type_to_mob(v, M)
-
-/obj/vehicle/proc/remove_passenger_actions(mob/M)
- for(var/v in autogrant_actions_passenger)
- remove_action_type_from_mob(v, M)
-
-/obj/vehicle/proc/grant_controller_actions(mob/M)
- if(!istype(M) || !occupants[M])
- return FALSE
- for(var/i in GLOB.bitflags)
- if(occupants[M] & i)
- grant_controller_actions_by_flag(M, i)
- return TRUE
-
-/obj/vehicle/proc/remove_controller_actions(mob/M)
- if(!istype(M) || !occupants[M])
- return FALSE
- for(var/i in GLOB.bitflags)
- remove_controller_actions_by_flag(M, i)
- return TRUE
-
-/obj/vehicle/proc/grant_controller_actions_by_flag(mob/M, flag)
- if(!istype(M) || !autogrant_actions_controller["[flag]"])
- return FALSE
- for(var/v in autogrant_actions_controller["[flag]"])
- grant_action_type_to_mob(v, M)
- return TRUE
-
-/obj/vehicle/proc/remove_controller_actions_by_flag(mob/M, flag)
- if(!istype(M) || autogrant_actions_controller["[flag]"])
- return FALSE
- for(var/v in autogrant_actions_controller["[flag]"])
- remove_action_type_from_mob(v, M)
- return TRUE
-
-/obj/vehicle/proc/cleanup_actions_for_mob(mob/M)
- if(!istype(M))
- return FALSE
- LAZYINITLIST(occupant_actions[M])
- for(var/path in occupant_actions[M])
- stack_trace("Leftover action type [path] in vehicle type [type] for mob type [M.type] - THIS SHOULD NOT BE HAPPENING!")
- var/datum/action/action = occupant_actions[M]
- action.Remove(M)
- occupant_actions -= M
- return TRUE
-
-//ACTION DATUMS
-
-/datum/action/vehicle
- check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS
- icon_icon = 'icons/mob/actions/actions_vehicle.dmi'
- button_icon_state = "vehicle_eject"
- var/obj/vehicle/vehicle_target
-
-/datum/action/vehicle/sealed
- var/obj/vehicle/sealed/vehicle_entered_target
-
-/datum/action/vehicle/sealed/climb_out
- name = "Climb Out"
- desc = "Climb out of your vehicle!"
-
-/datum/action/vehicle/sealed/climb_out/Trigger()
- if(..() && istype(vehicle_entered_target))
- vehicle_entered_target.mob_try_exit(owner, owner)
-
-/datum/action/vehicle/ridden
- var/obj/vehicle/ridden/vehicle_ridden_target
+//VEHICLE DEFAULT HANDLING
+/obj/vehicle/proc/generate_actions()
+ return
+
+/obj/vehicle/proc/generate_action_type(actiontype)
+ var/datum/action/vehicle/A = new actiontype
+ if(!istype(A))
+ return
+ A.vehicle_target = src
+ return A
+
+/obj/vehicle/proc/initialize_passenger_action_type(actiontype)
+ autogrant_actions_passenger += actiontype
+ for(var/i in occupants)
+ grant_passenger_actions(i) //refresh
+
+/obj/vehicle/proc/initialize_controller_action_type(actiontype, control_flag)
+ LAZYINITLIST(autogrant_actions_controller["[control_flag]"])
+ autogrant_actions_controller["[control_flag]"] += actiontype
+ for(var/i in occupants)
+ grant_controller_actions(i) //refresh
+
+/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/m)
+ if(!occupants[m] || !actiontype)
+ return FALSE
+ LAZYINITLIST(occupant_actions[m])
+ if(occupant_actions[m][actiontype])
+ return TRUE
+ var/datum/action/action = generate_action_type(actiontype)
+ action.Grant(m)
+ occupant_actions[m][action.type] = action
+ return TRUE
+
+/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/m)
+ if(!occupants[m] || !actiontype)
+ return FALSE
+ LAZYINITLIST(occupant_actions[m])
+ if(occupant_actions[m][actiontype])
+ var/datum/action/action = occupant_actions[m][actiontype]
+ action.Remove(m)
+ occupant_actions[m] -= actiontype
+ return TRUE
+
+/obj/vehicle/proc/grant_passenger_actions(mob/M)
+ for(var/v in autogrant_actions_passenger)
+ grant_action_type_to_mob(v, M)
+
+/obj/vehicle/proc/remove_passenger_actions(mob/M)
+ for(var/v in autogrant_actions_passenger)
+ remove_action_type_from_mob(v, M)
+
+/obj/vehicle/proc/grant_controller_actions(mob/M)
+ if(!istype(M) || !occupants[M])
+ return FALSE
+ for(var/i in GLOB.bitflags)
+ if(occupants[M] & i)
+ grant_controller_actions_by_flag(M, i)
+ return TRUE
+
+/obj/vehicle/proc/remove_controller_actions(mob/M)
+ if(!istype(M) || !occupants[M])
+ return FALSE
+ for(var/i in GLOB.bitflags)
+ remove_controller_actions_by_flag(M, i)
+ return TRUE
+
+/obj/vehicle/proc/grant_controller_actions_by_flag(mob/M, flag)
+ if(!istype(M) || !autogrant_actions_controller["[flag]"])
+ return FALSE
+ for(var/v in autogrant_actions_controller["[flag]"])
+ grant_action_type_to_mob(v, M)
+ return TRUE
+
+/obj/vehicle/proc/remove_controller_actions_by_flag(mob/M, flag)
+ if(!istype(M) || autogrant_actions_controller["[flag]"])
+ return FALSE
+ for(var/v in autogrant_actions_controller["[flag]"])
+ remove_action_type_from_mob(v, M)
+ return TRUE
+
+/obj/vehicle/proc/cleanup_actions_for_mob(mob/M)
+ if(!istype(M))
+ return FALSE
+ LAZYINITLIST(occupant_actions[M])
+ for(var/path in occupant_actions[M])
+ stack_trace("Leftover action type [path] in vehicle type [type] for mob type [M.type] - THIS SHOULD NOT BE HAPPENING!")
+ var/datum/action/action = occupant_actions[M]
+ action.Remove(M)
+ occupant_actions -= M
+ return TRUE
+
+//ACTION DATUMS
+
+/datum/action/vehicle
+ check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS
+ icon_icon = 'icons/mob/actions/actions_vehicle.dmi'
+ button_icon_state = "vehicle_eject"
+ var/obj/vehicle/vehicle_target
+
+/datum/action/vehicle/sealed
+ var/obj/vehicle/sealed/vehicle_entered_target
+
+/datum/action/vehicle/sealed/climb_out
+ name = "Climb Out"
+ desc = "Climb out of your vehicle!"
+
+/datum/action/vehicle/sealed/climb_out/Trigger()
+ if(..() && istype(vehicle_entered_target))
+ vehicle_entered_target.mob_try_exit(owner, owner)
+
+/datum/action/vehicle/ridden
+ var/obj/vehicle/ridden/vehicle_ridden_target
diff --git a/code/modules/vehicles/vehicle_key.dm b/code/modules/vehicles/vehicle_key.dm
index 204a10bd17..e34ad9253d 100644
--- a/code/modules/vehicles/vehicle_key.dm
+++ b/code/modules/vehicles/vehicle_key.dm
@@ -1,15 +1,15 @@
-/obj/item/key
- name = "key"
- desc = "A small grey key."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "key"
- w_class = WEIGHT_CLASS_TINY
-
-/obj/item/key/security
- desc = "A keyring with a small steel key, and a rubber stun baton accessory."
- icon_state = "keysec"
-
-/obj/item/key/janitor
- desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"."
- icon_state = "keyjanitor"
-
+/obj/item/key
+ name = "key"
+ desc = "A small grey key."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "key"
+ w_class = WEIGHT_CLASS_TINY
+
+/obj/item/key/security
+ desc = "A keyring with a small steel key, and a rubber stun baton accessory."
+ icon_state = "keysec"
+
+/obj/item/key/janitor
+ desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"."
+ icon_state = "keyjanitor"
+
diff --git a/icons/effects/vanguard_target.dmi b/icons/effects/vanguard_target.dmi
index 73ba014e2d..5220c325e5 100644
Binary files a/icons/effects/vanguard_target.dmi and b/icons/effects/vanguard_target.dmi differ
diff --git a/icons/emoji.dmi b/icons/emoji.dmi
index 9d3e0630a7..b0434f431f 100644
Binary files a/icons/emoji.dmi and b/icons/emoji.dmi differ
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
index 0255204f60..3a7b0648fd 100644
Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ
diff --git a/icons/mob/actions/actions_clockcult.dmi b/icons/mob/actions/actions_clockcult.dmi
index 19fd68f836..4aad4ba569 100644
Binary files a/icons/mob/actions/actions_clockcult.dmi and b/icons/mob/actions/actions_clockcult.dmi differ
diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi
index de8587dba5..2eab8fa78e 100644
Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 89eb9dbcbc..3aa655b574 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index 0cdee31ae1..70988dbef5 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi
index 38c89769d2..76adebdc11 100644
Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ
diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi
index c14fbb3fb2..a12053ae1d 100644
Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ
diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi
index 3854f252eb..e83588d5ed 100644
Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ
diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi
index b5b851a8d5..59635b8c7d 100644
Binary files a/icons/mob/neck.dmi and b/icons/mob/neck.dmi differ
diff --git a/icons/mob/screen_cyborg.dmi b/icons/mob/screen_cyborg.dmi
index e9fd4ed401..fc236ac7e2 100644
Binary files a/icons/mob/screen_cyborg.dmi and b/icons/mob/screen_cyborg.dmi differ
diff --git a/icons/mob/screen_full.dmi b/icons/mob/screen_full.dmi
index 988bf59592..502e9ad3f9 100644
Binary files a/icons/mob/screen_full.dmi and b/icons/mob/screen_full.dmi differ
diff --git a/icons/mob/simple_human.dmi b/icons/mob/simple_human.dmi
index f3345c0825..597ee94d72 100644
Binary files a/icons/mob/simple_human.dmi and b/icons/mob/simple_human.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index c251b93f2e..241db46d08 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/Cryogenic2.dmi b/icons/obj/Cryogenic2.dmi
new file mode 100644
index 0000000000..9d7b7510c5
Binary files /dev/null and b/icons/obj/Cryogenic2.dmi differ
diff --git a/icons/obj/bedsheets.dmi b/icons/obj/bedsheets.dmi
index 17dc5b8fb2..d492ae52f6 100644
Binary files a/icons/obj/bedsheets.dmi and b/icons/obj/bedsheets.dmi differ
diff --git a/icons/obj/biogenerator.dmi b/icons/obj/biogenerator.dmi
new file mode 100644
index 0000000000..7989d6f355
Binary files /dev/null and b/icons/obj/biogenerator.dmi differ
diff --git a/icons/obj/bloodpack.dmi b/icons/obj/bloodpack.dmi
index 423b5bb641..ac879aa33c 100644
Binary files a/icons/obj/bloodpack.dmi and b/icons/obj/bloodpack.dmi differ
diff --git a/icons/obj/cigarettes.dmi b/icons/obj/cigarettes.dmi
index ed8f37c4da..76ac7bd0a8 100644
Binary files a/icons/obj/cigarettes.dmi and b/icons/obj/cigarettes.dmi differ
diff --git a/icons/obj/clockwork_objects.dmi b/icons/obj/clockwork_objects.dmi
index 561359959b..784c0f55eb 100644
Binary files a/icons/obj/clockwork_objects.dmi and b/icons/obj/clockwork_objects.dmi differ
diff --git a/icons/obj/cloning.dmi b/icons/obj/cloning.dmi
new file mode 100644
index 0000000000..5aa439df6b
Binary files /dev/null and b/icons/obj/cloning.dmi differ
diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi
index 4c3c0fe5ce..63c036ce14 100644
Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ
diff --git a/icons/obj/clothing/cloaks.dmi b/icons/obj/clothing/cloaks.dmi
index 31aab0ae26..dd1ae7d727 100644
Binary files a/icons/obj/clothing/cloaks.dmi and b/icons/obj/clothing/cloaks.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index 48f37887cf..6c193f1044 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 6ec16c836f..2a6d2004b3 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index 786a8c7fd0..b1d7a7106d 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi
index c41db68326..0f3668ce10 100644
Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ
diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi
index 2cf675c571..77b62691d2 100644
Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index d0326b1141..f44fc29f7c 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi
index 8fe4c9619b..6c1dabef23 100644
Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ
diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi
index 0669549b02..31e700d23d 100644
Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 876f747fc1..88aa6f7985 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/flora/_flora.dmi b/icons/obj/flora/_flora.dmi
new file mode 100644
index 0000000000..d3e800576e
Binary files /dev/null and b/icons/obj/flora/_flora.dmi differ
diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi
index 7d413895ca..7f4d65e081 100644
Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ
diff --git a/icons/obj/guns/bayonets.dmi b/icons/obj/guns/bayonets.dmi
index 176005b7d7..32b5448b8e 100644
Binary files a/icons/obj/guns/bayonets.dmi and b/icons/obj/guns/bayonets.dmi differ
diff --git a/icons/obj/hydroponics/equipment.dmi b/icons/obj/hydroponics/equipment.dmi
index ad5f8bc863..3d125d68c7 100644
Binary files a/icons/obj/hydroponics/equipment.dmi and b/icons/obj/hydroponics/equipment.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 636d895450..446b093167 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index 2048725e56..776bf7a9ec 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/icons/obj/machines/research.dmi b/icons/obj/machines/research.dmi
index cd74eed322..a150880d39 100644
Binary files a/icons/obj/machines/research.dmi and b/icons/obj/machines/research.dmi differ
diff --git a/icons/obj/pda.dmi b/icons/obj/pda.dmi
index 5404b908c6..241bb46b98 100644
Binary files a/icons/obj/pda.dmi and b/icons/obj/pda.dmi differ
diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi
index 7eec51e46e..f0eb817549 100644
Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index f563af642f..dadf843041 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/icons/obj/suitstorage.dmi b/icons/obj/suitstorage.dmi
new file mode 100644
index 0000000000..e61f9567c6
Binary files /dev/null and b/icons/obj/suitstorage.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 18bbcb3610..d18a1bf262 100755
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi
index c7b9bbcdc8..a1471e6418 100644
Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ
diff --git a/icons/obj/vending_restock.dmi b/icons/obj/vending_restock.dmi
index 7f8289a087..a59fdd0f52 100644
Binary files a/icons/obj/vending_restock.dmi and b/icons/obj/vending_restock.dmi differ