code:
//VEHICLE DEFAULT HANDLING

/**
 * ## generate_actions
 *
 * You override this with initialize_passenger_action_type and initialize_controller_action_type calls
 * To give passengers actions when they enter the vehicle.
 * Read the documentation on the aforementioned procs to learn the difference
 */
/obj/vehicle/proc/generate_actions()
	return

/**
 * ## generate_action_type
 *
 * A small proc to properly set up each action path.
 * args:
 * * actiontype: typepath of the action the proc sets up.
 * returns created and set up action instance
 */
/obj/vehicle/proc/generate_action_type(actiontype)
	var/datum/action/vehicle/A = new actiontype
	if(!istype(A))
		return
	A.vehicle_target = src
	return A

/**
 * ## initialize_passenger_action_type
 *
 * Gives any passenger that enters the mech this action.
 * They will lose it when they disembark.
 * args:
 * * actiontype: typepath of the action you want to give occupants.
 */
/obj/vehicle/proc/initialize_passenger_action_type(actiontype)
	autogrant_actions_passenger += actiontype
	for(var/i in occupants)
		grant_passenger_actions(i) //refresh

/**
 * ## initialize_controller_action_type
 *
 * Gives any passenger that enters the mech this action... IF they have the correct vehicle control flag.
 * This is used so passengers cannot press buttons only drivers should have, for example.
 * args:
 * * actiontype: typepath of the action you want to give occupants.
 */
/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

/**
 * ## grant_action_type_to_mob
 *
 * As on the tin, it does all the annoying small stuff and sanity needed
 * to GRANT an action to a mob.
 * args:
 * * actiontype: typepath of the action you want to give to grant_to.
 * * grant_to: the mob we're giving actiontype to
 * returns TRUE if successfully granted
 */
/obj/vehicle/proc/grant_action_type_to_mob(actiontype, mob/grant_to)
	if(isnull(LAZYACCESS(occupants, grant_to)) || !actiontype)
		return FALSE
	LAZYINITLIST(occupant_actions[grant_to])
	if(occupant_actions[grant_to][actiontype])
		return TRUE
	var/datum/action/action = generate_action_type(actiontype)
	action.Grant(grant_to)
	occupant_actions[grant_to][action.type] = action
	return TRUE

/**
 * ## remove_action_type_from_mob
 *
 * As on the tin, it does all the annoying small stuff and sanity needed
 * to REMOVE an action to a mob.
 * args:
 * * actiontype: typepath of the action you want to give to grant_to.
 * * take_from: the mob we're taking actiontype to
 * returns TRUE if successfully removed
 */
/obj/vehicle/proc/remove_action_type_from_mob(actiontype, mob/take_from)
	if(isnull(LAZYACCESS(occupants, take_from)) || !actiontype)
		return FALSE
	LAZYINITLIST(occupant_actions[take_from])
	if(occupant_actions[take_from][actiontype])
		var/datum/action/action = occupant_actions[take_from][actiontype]
		action.Remove(take_from)
		occupant_actions[take_from] -= actiontype
	return TRUE

/**
 * ## grant_passenger_actions
 *
 * Called on every passenger that enters the vehicle, goes through the list of actions it needs to give...
 * and does that.
 * args:
 * * grant_to: mob that needs to get every action the vehicle grants
 */
/obj/vehicle/proc/grant_passenger_actions(mob/grant_to)
	for(var/v in autogrant_actions_passenger)
		grant_action_type_to_mob(v, grant_to)

/**
 * ## remove_passenger_actions
 *
 * Called on every passenger that exits the vehicle, goes through the list of actions it needs to remove...
 * and does that.
 * args:
 * * take_from: mob that needs to get every action the vehicle grants
 */
/obj/vehicle/proc/remove_passenger_actions(mob/take_from)
	for(var/v in autogrant_actions_passenger)
		remove_action_type_from_mob(v, take_from)

/obj/vehicle/proc/grant_controller_actions(mob/M)
	if(!istype(M) || isnull(LAZYACCESS(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) || isnull(LAZYACCESS(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))
		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))
		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
	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][path]
		action.Remove(M)
		occupant_actions[M] -= path
	occupant_actions -= M
	return TRUE

/***************** ACTION DATUMS *****************/

/datum/action/vehicle
	check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | 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
	check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS
	var/obj/vehicle/sealed/vehicle_entered_target

/datum/action/vehicle/sealed/climb_out
	name = "Climb Out"
	desc = "Climb out of your vehicle!"
	button_icon_state = "car_eject"

/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

/datum/action/vehicle/sealed/remove_key
	name = "Remove key"
	desc = "Take your key out of the vehicle's ignition."
	button_icon_state = "car_removekey"

/datum/action/vehicle/sealed/remove_key/Trigger()
	vehicle_entered_target.remove_key(owner)

//CLOWN CAR ACTION DATUMS
/datum/action/vehicle/sealed/horn
	name = "Honk Horn"
	desc = "Honk your classy horn."
	button_icon_state = "car_horn"
	var/hornsound = 'sound/items/carhorn.ogg'

/datum/action/vehicle/sealed/horn/Trigger()
	if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_CAR_HONK))
		return
	TIMER_COOLDOWN_START(src, COOLDOWN_CAR_HONK, 2 SECONDS)
	vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] loudly honks!"))
	to_chat(owner, span_notice("You press [vehicle_entered_target]'s horn."))
	if(istype(vehicle_target.inserted_key, /obj/item/bikehorn))
		vehicle_target.inserted_key.attack_self(owner) //The bikehorn plays a sound instead
		return
	playsound(vehicle_entered_target, hornsound, 75)

/datum/action/vehicle/sealed/headlights
	name = "Toggle Headlights"
	desc = "Turn on your brights!"
	button_icon_state = "car_headlights"

/datum/action/vehicle/sealed/headlights/Trigger()
	to_chat(owner, span_notice("You flip the switch for the vehicle's headlights."))
	vehicle_entered_target.headlights_toggle = !vehicle_entered_target.headlights_toggle
	vehicle_entered_target.set_light_on(vehicle_entered_target.headlights_toggle)
	vehicle_entered_target.update_appearance()
	playsound(owner, vehicle_entered_target.headlights_toggle ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE)

/datum/action/vehicle/sealed/dump_kidnapped_mobs
	name = "Dump Kidnapped Mobs"
	desc = "Dump all objects and people in your car on the floor."
	button_icon_state = "car_dump"

/datum/action/vehicle/sealed/dump_kidnapped_mobs/Trigger()
	vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] starts dumping the people inside of it."))
	vehicle_entered_target.dump_specific_mobs(VEHICLE_CONTROL_KIDNAPPED)

/datum/action/vehicle/sealed/roll_the_dice
	name = "Press Colorful Button"
	desc = "Press one of those colorful buttons on your display panel!"
	button_icon_state = "car_rtd"

/datum/action/vehicle/sealed/roll_the_dice/Trigger()
	if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
		return
	var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target
	C.roll_the_dice(owner)

/datum/action/vehicle/sealed/cannon
	name = "Toggle Siege Mode"
	desc = "Destroy them with their own fodder!"
	button_icon_state = "car_cannon"

/datum/action/vehicle/sealed/cannon/Trigger()
	if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
		return
	var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target
	C.toggle_cannon(owner)

/datum/action/vehicle/sealed/thank
	name = "Thank the Clown Car Driver"
	desc = "They're just doing their job."
	button_icon_state = "car_thanktheclown"
	COOLDOWN_DECLARE(thank_time_cooldown)

/datum/action/vehicle/sealed/thank/Trigger()
	if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar))
		return
	if(!COOLDOWN_FINISHED(src, thank_time_cooldown))
		return
	COOLDOWN_START(src, thank_time_cooldown, 6 SECONDS)
	var/obj/vehicle/sealed/car/clowncar/clown_car = vehicle_entered_target
	var/mob/living/carbon/human/clown = pick(clown_car.return_drivers())
	if(!clown)
		return
	owner.say("Thank you for the fun ride, [clown.name]!")
	clown_car.increment_thanks_counter()

/datum/action/vehicle/ridden/scooter/skateboard/ollie
	name = "Ollie"
	desc = "Get some air! Land on a table to do a gnarly grind."
	button_icon_state = "skateboard_ollie"
	///Cooldown to next jump
	var/next_ollie

/datum/action/vehicle/ridden/scooter/skateboard/ollie/Trigger()
	if(world.time > next_ollie)
		var/obj/vehicle/ridden/scooter/skateboard/vehicle = vehicle_target
		vehicle.obj_flags |= BLOCK_Z_OUT_DOWN
		if (vehicle.grinding)
			return
		var/mob/living/rider = owner
		var/turf/landing_turf = get_step(vehicle.loc, vehicle.dir)
		rider.adjustStaminaLoss(vehicle.instability*2)
		if (rider.getStaminaLoss() >= 100)
			vehicle.obj_flags &= ~CAN_BE_HIT
			playsound(src, 'sound/effects/bang.ogg', 20, TRUE)
			vehicle.unbuckle_mob(rider)
			rider.throw_at(landing_turf, 2, 2)
			rider.Paralyze(40)
			vehicle.visible_message(span_danger("[rider] misses the landing and falls on [rider.p_their()] face!"))
		else
			rider.spin(4, 1)
			animate(rider, pixel_y = -6, time = 4)
			animate(vehicle, pixel_y = -6, time = 3)
			playsound(vehicle, 'sound/vehicles/skateboard_ollie.ogg', 50, TRUE)
			passtable_on(rider, VEHICLE_TRAIT)
			vehicle.pass_flags |= PASSTABLE
			rider.Move(landing_turf, vehicle_target.dir)
			passtable_off(rider, VEHICLE_TRAIT)
			vehicle.pass_flags &= ~PASSTABLE
		if((locate(/obj/structure/table) in vehicle.loc.contents) || (locate(/obj/structure/fluff/tram_rail) in vehicle.loc.contents))
			if(locate(/obj/structure/fluff/tram_rail) in vehicle.loc.contents)
				rider.client.give_award(/datum/award/achievement/misc/tram_surfer, rider)
			vehicle.grinding = TRUE
			vehicle.icon_state = "[initial(vehicle.icon_state)]-grind"
			addtimer(CALLBACK(vehicle, /obj/vehicle/ridden/scooter/skateboard/.proc/grind), 2)

//VIM ACTION DATUMS

/datum/action/vehicle/sealed/climb_out/vim
	name = "Eject From Mech"
	icon_icon = 'icons/mob/actions/actions_mecha.dmi'
	button_icon_state = "mech_eject"

/datum/action/vehicle/sealed/noise
	var/sound_path = 'sound/items/carhorn.ogg'
	var/sound_message = "makes a sound."

/datum/action/vehicle/sealed/noise/Trigger()
	var/obj/vehicle/sealed/car/vim/vim_mecha = vehicle_entered_target
	if(!COOLDOWN_FINISHED(vim_mecha, sound_cooldown))
		vim_mecha.balloon_alert(owner, "on cooldown!")
		return
	COOLDOWN_START(vim_mecha, sound_cooldown, VIM_SOUND_COOLDOWN)
	vehicle_entered_target.visible_message(span_notice("[vehicle_entered_target] [sound_message]"))
	playsound(vim_mecha, sound_path, 75)

/datum/action/vehicle/sealed/noise/chime
	name = "Chime!"
	desc = "Affirmative!"
	button_icon_state = "vim_chime"
	sound_path = 'sound/machines/chime.ogg'
	sound_message = "chimes!"

/datum/action/vehicle/sealed/noise/buzz
	name = "Buzz."
	desc = "Negative!"
	button_icon_state = "vim_buzz"
	sound_path = 'sound/machines/buzz-sigh.ogg'
	sound_message = "buzzes."

/datum/action/vehicle/sealed/headlights/vim
	button_icon_state = "vim_headlights"


code:
/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/atv
	name = "ATV key"
	desc = "A small grey key for starting and operating ATVs."

/obj/item/key/security
	desc = "A keyring with a small steel key, and a rubber stun baton accessory."
	icon_state = "keysec"

/obj/item/key/security/suicide_act(mob/living/carbon/user)
	if(!user.emote("spin")) //In the off chance that someone attempts this suicide while under the effects of mime's bane they deserve the silliness.
		user.visible_message(span_suicide("[user] is putting \the [src] in [user.p_their()] ear and starts [user.p_their()] motor! It looks like [user.p_theyre()] trying to commit suicide... But [user.p_they()] sputters and stalls out! "))
		playsound(src, 'sound/misc/sadtrombone.ogg', 50, TRUE, -1)
		return SHAME
	user.visible_message(span_suicide("[user] is putting \the [src] in [user.p_their()] ear and starts [user.p_their()] motor! It looks like [user.p_theyre()] trying to commit suicide!"))
	user.say("Vroom vroom!!", forced="secway key suicide") //Not doing a shamestate here, because even if they fail to speak they're spinning.
	addtimer(CALLBACK(user, /mob/living/.proc/gib), 20)
	return MANUAL_SUICIDE

/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/janitor/suicide_act(mob/living/carbon/user)
	switch(user.mind?.get_skill_level(/datum/skill/cleaning))
		if(SKILL_LEVEL_NONE to SKILL_LEVEL_NOVICE) //Their mind is too weak to ascend as a janny
			user.visible_message(span_suicide("[user] is putting \the [src] in [user.p_their()] mouth and is trying to become one with the janicart, but has no idea where to start! It looks like [user.p_theyre()] trying to commit suicide!"))
			user.gib()
			return MANUAL_SUICIDE
		if(SKILL_LEVEL_APPRENTICE to SKILL_LEVEL_JOURNEYMAN) //At least they tried
			user.visible_message(span_suicide("[user] is putting \the [src] in [user.p_their()] mouth and has inefficiently become one with the janicart! It looks like [user.p_theyre()] trying to commit suicide!"))
			user.AddElement(/datum/element/cleaning)
			addtimer(CALLBACK(src, .proc/manual_suicide, user), 51)
			return MANUAL_SUICIDE
		if(SKILL_LEVEL_EXPERT to SKILL_LEVEL_MASTER) //They are worthy enough, but can it go even further beyond?
			user.visible_message(span_suicide("[user] is putting \the [src] in [user.p_their()] mouth and has skillfully become one with the janicart! It looks like [user.p_theyre()] trying to commit suicide!"))
			user.AddElement(/datum/element/cleaning)
			for(var/i in 1 to 100)
				addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#a245bb" : "#7a7d82", ADMIN_COLOUR_PRIORITY), i)
			addtimer(CALLBACK(src, .proc/manual_suicide, user), 101)
			return MANUAL_SUICIDE
		if(SKILL_LEVEL_LEGENDARY to INFINITY) //Holy shit, look at that janny go!
			user.visible_message(span_suicide("[user] is putting \the [src] in [user.p_their()] mouth and has epically become one with the janicart, and they're even in overdrive mode! It looks like [user.p_theyre()] trying to commit suicide!"))
			user.AddElement(/datum/element/cleaning)
			playsound(src, 'sound//magic/lightning_chargeup.ogg', 50, TRUE, -1)
			user.reagents.add_reagent(/datum/reagent/drug/methamphetamine, 10) //Gotta go fast!
			for(var/i in 1 to 150)
				addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#a245bb" : "#7a7d82", ADMIN_COLOUR_PRIORITY), i)
			addtimer(CALLBACK(src, .proc/manual_suicide, user), 151)
			return MANUAL_SUICIDE

/obj/item/key/proc/manual_suicide(mob/living/user)
	if(user)
		user.remove_atom_colour(ADMIN_COLOUR_PRIORITY)
		user.visible_message(span_suicide("[user] forgot [user.p_they()] isn't actually a janicart! That's a paddlin'!"))
		if(user.mind?.get_skill_level(/datum/skill/cleaning) >= SKILL_LEVEL_LEGENDARY) //Janny janny janny janny janny
			playsound(src, 'sound/effects/adminhelp.ogg', 50, TRUE, -1)
		user.adjustOxyLoss(200)
		user.death(0)

/obj/item/key/lasso
	name = "bone lasso"
	desc = "Perfect for taming all kinds of supernatural beasts! (Warning: only perfect for taming one kind of supernatural beast.)"
	force = 12
	icon_state = "lasso"
	inhand_icon_state = "chain"
	worn_icon_state = "whip"
	lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
	righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
	attack_verb_continuous = list("flogs", "whips", "lashes", "disciplines")
	attack_verb_simple = list("flog", "whip", "lash", "discipline")
	hitsound = 'sound/weapons/whip.ogg'
	slot_flags = ITEM_SLOT_BELT

repo_name: AnalWerewolf/sundown

license: mit


code:
/obj/vehicle/ridden/wheelchair //ported from Hippiestation (by Jujumatic)
	name = "wheelchair"
	desc = "A chair with big wheels. It looks like you can move in this on your own."
	icon = 'icons/obj/vehicles.dmi'
	icon_state = "wheelchair"
	layer = OBJ_LAYER
	max_integrity = 100
	armor = list(MELEE = 10, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 10, BIO = 0, RAD = 0, FIRE = 20, ACID = 30) //Wheelchairs aren't super tough yo
	density = FALSE //Thought I couldn't fix this one easily, phew
	/// Run speed delay is multiplied with this for vehicle move delay.
	var/delay_multiplier = 6.7
	/// This variable is used to specify which overlay icon is used for the wheelchair, ensures wheelchair can cover your legs
	var/overlay_icon = "wheelchair_overlay"
	var/image/wheels_overlay
	///Determines the typepath of what the object folds into
	var/foldabletype = /obj/item/wheelchair

/obj/vehicle/ridden/wheelchair/Initialize(mapload)
	. = ..()
	make_ridable()
	wheels_overlay = image(icon, overlay_icon, FLY_LAYER)
	ADD_TRAIT(src, TRAIT_NO_IMMOBILIZE, INNATE_TRAIT)

/obj/vehicle/ridden/wheelchair/ComponentInitialize() //Since it's technically a chair I want it to have chair properties
	. = ..()
	AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE, CALLBACK(src, .proc/can_user_rotate),CALLBACK(src, .proc/can_be_rotated),null)

/obj/vehicle/ridden/wheelchair/atom_destruction(damage_flag)
	new /obj/item/stack/rods(drop_location(), 1)
	new /obj/item/stack/sheet/iron(drop_location(), 1)
	return ..()

/obj/vehicle/ridden/wheelchair/Moved()
	. = ..()
	playsound(src, 'sound/effects/roll.ogg', 75, TRUE)

/obj/vehicle/ridden/wheelchair/post_buckle_mob(mob/living/user)
	. = ..()
	update_appearance()

/obj/vehicle/ridden/wheelchair/post_unbuckle_mob()
	. = ..()
	update_appearance()

/obj/vehicle/ridden/wheelchair/wrench_act(mob/living/user, obj/item/I) //Attackby should stop it attacking the wheelchair after moving away during decon
	..()
	to_chat(user, span_notice("You begin to detach the wheels..."))
	if(I.use_tool(src, user, 40, volume=50))
		to_chat(user, span_notice("You detach the wheels and deconstruct the chair."))
		new /obj/item/stack/rods(drop_location(), 6)
		new /obj/item/stack/sheet/iron(drop_location(), 4)
		qdel(src)
	return TRUE

/obj/vehicle/ridden/wheelchair/update_overlays()
	. = ..()
	if(has_buckled_mobs())
		. += wheels_overlay

///used for simple rotation component checks
/obj/vehicle/ridden/wheelchair/proc/can_be_rotated(mob/living/user)
	return TRUE

///used in simple rotation component checks as to whether a user can rotate this chair
/obj/vehicle/ridden/wheelchair/proc/can_user_rotate(mob/living/user)
	var/mob/living/L = user
	if(istype(L))
		if(!user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE, !iscyborg(user)))
			return FALSE
	if(isobserver(user) && CONFIG_GET(flag/ghost_interaction))
		return TRUE
	return FALSE

/// I assign the ridable element in this so i don't have to fuss with hand wheelchairs and motor wheelchairs having different subtypes
/obj/vehicle/ridden/wheelchair/proc/make_ridable()
	AddElement(/datum/element/ridable, /datum/component/riding/vehicle/wheelchair/hand)

/obj/vehicle/ridden/wheelchair/gold
	material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_AFFECT_STATISTICS
	desc = "Damn, he's been through a lot."
	icon_state = "gold_wheelchair"
	overlay_icon = "gold_wheelchair_overlay"
	max_integrity = 200
	armor = list(MELEE = 20, BULLET = 20, LASER = 20, ENERGY = 0, BOMB = 20, BIO = 0, RAD = 0, FIRE = 30, ACID = 40)
	custom_materials = list(/datum/material/gold = 10000)
	foldabletype = /obj/item/wheelchair/gold

/obj/item/wheelchair
	name = "wheelchair"
	desc = "A collapsed wheelchair that can be carried around."
	icon = 'icons/obj/vehicles.dmi'
	icon_state = "wheelchair_folded"
	inhand_icon_state = "wheelchair_folded"
	lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
	righthand_file = 'icons/mob/inhands/items_righthand.dmi'
	w_class = WEIGHT_CLASS_NORMAL
	force = 8 //Force is same as a chair
	custom_materials = list(/datum/material/iron = 10000)
	///The wheelchair vehicle type we create when we unfold this chair
	var/unfolded_type = /obj/vehicle/ridden/wheelchair

/obj/item/wheelchair/gold
	name = "gold wheelchair"
	desc = "A collapsed, shiny wheelchair that can be carried around."
	icon = 'icons/obj/vehicles.dmi'
	icon_state = "wheelchair_folded_gold"
	inhand_icon_state = "wheelchair_folded_gold"
	lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
	righthand_file = 'icons/mob/inhands/items_righthand.dmi'
	force = 10
	custom_materials = list(/datum/material/gold = 10000)
	unfolded_type = /obj/vehicle/ridden/wheelchair/gold

/obj/vehicle/ridden/wheelchair/MouseDrop(over_object, src_location, over_location)  //Lets you collapse wheelchair
	. = ..()
	if(over_object != usr || !Adjacent(usr) || !foldabletype)
		return FALSE
	if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
		return FALSE
	if(has_buckled_mobs())
		return FALSE
	usr.visible_message(span_notice("[usr] collapses [src]."), span_notice("You collapse [src]."))
	var/obj/vehicle/ridden/wheelchair/wheelchair_folded = new foldabletype(get_turf(src))
	usr.put_in_hands(wheelchair_folded)
	qdel(src)

/obj/item/wheelchair/attack_self(mob/user)  //Deploys wheelchair on in-hand use
	deploy_wheelchair(user, user.loc)

/obj/item/wheelchair/proc/deploy_wheelchair(mob/user, atom/location)
	var/obj/vehicle/ridden/wheelchair/wheelchair_unfolded = new unfolded_type(location)
	wheelchair_unfolded.add_fingerprint(user)
	qdel(src)


code:
/*
 * Vending machine types - Can be found under /code/modules/vending/
 */

/*

/obj/machinery/vending/[vendors name here]   // --vending machine template   :)
	name = ""
	desc = ""
	icon = ''
	icon_state = ""
	products = list()
	contraband = list()
	premium = list()
*/

#define MAX_VENDING_INPUT_AMOUNT 30
/**
 * # vending record datum
 *
 * A datum that represents a product that is vendable
 */
/datum/data/vending_product
	name = "generic"
	///Typepath of the product that is created when this record "sells"
	var/product_path = null
	///How many of this product we currently have
	var/amount = 0
	///How many we can store at maximum
	var/max_amount = 0
	///Does the item have a custom price override
	var/custom_price
	///Does the item have a custom premium price override
	var/custom_premium_price
	///Whether spessmen with an ID with an age below AGE_MINOR (20 by default) can buy this item
	var/age_restricted = FALSE
	///Whether the product can be recolored by the GAGS system
	var/colorable

/**
 * # vending machines
 *
 * Captalism in the year 2525, everything in a vending machine, even love
 */
/obj/machinery/vending
	name = "\improper Vendomat"
	desc = "A generic vending machine."
	icon = 'icons/obj/vending.dmi'
	icon_state = "generic"
	layer = BELOW_OBJ_LAYER
	density = TRUE
	verb_say = "beeps"
	verb_ask = "beeps"
	verb_exclaim = "beeps"
	max_integrity = 300
	integrity_failure = 0.33
	armor = list(MELEE = 20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 70)
	circuit = /obj/item/circuitboard/machine/vendor
	payment_department = ACCOUNT_SRV
	light_power = 0.5
	light_range = MINIMUM_USEFUL_LIGHT_RANGE
	/// Is the machine active (No sales pitches if off)!
	var/active = 1
	///Are we ready to vend?? Is it time??
	var/vend_ready = TRUE
	///Next world time to send a purchase message
	var/purchase_message_cooldown
	///The ref of the last mob to shop with us
	var/last_shopper
	var/tilted = FALSE
	var/tiltable = TRUE
	var/squish_damage = 75
	var/forcecrit = 0
	var/num_shards = 7
	var/list/pinned_mobs = list()

	/**
	  * List of products this machine sells
	  *
	  * form should be list(/type/path = amount, /type/path2 = amount2)
	  */
	var/list/products = list()

	/**
	  * List of products this machine sells when you hack it
	  *
	  * form should be list(/type/path = amount, /type/path2 = amount2)
	  */
	var/list/contraband = list()

	/**
	  * List of premium products this machine sells
	  *
	  * form should be list(/type/path, /type/path2) as there is only ever one in stock
	  */
	var/list/premium = list()

	///String of slogans separated by semicolons, optional
	var/product_slogans = ""
	///String of small ad messages in the vending screen - random chance
	var/product_ads = ""

	var/list/product_records = list()
	var/list/hidden_records = list()
	var/list/coin_records = list()
	var/list/slogan_list = list()
	///Small ad messages in the vending screen - random chance of popping up whenever you open it
	var/list/small_ads = list()
	///Message sent post vend (Thank you for shopping!)
	var/vend_reply
	///Last world tick we sent a vent reply
	var/last_reply = 0
	///Last world tick we sent a slogan message out
	var/last_slogan = 0
	///How many ticks until we can send another
	var/slogan_delay = 6000
	///Icon when vending an item to the user
	var/icon_vend
	///Icon to flash when user is denied a vend
	var/icon_deny
	///World ticks the machine is electified for
	var/seconds_electrified = MACHINE_NOT_ELECTRIFIED
	///When this is TRUE, we fire items at customers! We're broken!
	var/shoot_inventory = 0
	///How likely this is to happen (prob 100) per second
	var/shoot_inventory_chance = 1
	//Stop spouting those godawful pitches!
	var/shut_up = 0
	///can we access the hidden inventory?
	var/extended_inventory = 0
	///Are we checking the users ID
	var/scan_id = 1
	///Coins that we accept?
	var/obj/item/coin/coin
	///Bills we accept?
	var/obj/item/stack/spacecash/bill
	///Default price of items if not overridden
	var/default_price = 25
	///Default price of premium items if not overridden
	var/extra_price = 50
	///Whether our age check is currently functional
	var/age_restrictions = TRUE
	/**
	  * Is this item on station or not
	  *
	  * if it doesn't originate from off-station during mapload, everything is free
	  */
	var/onstation = TRUE //if it doesn't originate from off-station during mapload, everything is free
	///A variable to change on a per instance basis on the map that allows the instance to force cost and ID requirements
	var/onstation_override = FALSE //change this on the object on the map to override the onstation check. DO NOT APPLY THIS GLOBALLY.

	///ID's that can load this vending machine wtih refills
	var/list/canload_access_list

	var/list/vending_machine_input = list()
	///Display header on the input view
	var/input_display_header = "Custom Vendor"

	//The type of refill canisters used by this machine.
	var/obj/item/vending_refill/refill_canister = null

	/// how many items have been inserted in a vendor
	var/loaded_items = 0

	///Name of lighting mask for the vending machine
	var/light_mask

	/// used for narcing on underages
	var/obj/item/radio/Radio

/**
 * Initialize the vending machine
 *
 * Builds the vending machine inventory, sets up slogans and other such misc work
 *
 * This also sets the onstation var to:
 * * FALSE - if the machine was maploaded on a zlevel that doesn't pass the is_station_level check
 * * TRUE - all other cases
 */
/obj/machinery/vending/Initialize(mapload)
	var/build_inv = FALSE
	if(!refill_canister)
		circuit = null
		build_inv = TRUE
	. = ..()
	wires = new /datum/wires/vending(src)
	if(build_inv) //non-constructable vending machine
		build_inventory(products, product_records)
		build_inventory(contraband, hidden_records)
		build_inventory(premium, coin_records)

	slogan_list = splittext(product_slogans, ";")
	// So not all machines speak at the exact same time.
	// The first time this machine says something will be at slogantime + this random value,
	// so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated.
	last_slogan = world.time + rand(0, slogan_delay)
	power_change()

	if(onstation_override) //overrides the checks if true.
		onstation = TRUE
		return
	if(mapload) //check if it was initially created off station during mapload.
		if(!is_station_level(z))
			onstation = FALSE
			if(circuit)
				circuit.onstation = onstation //sync up the circuit so the pricing schema is carried over if it's reconstructed.
	else if(circuit && (circuit.onstation != onstation)) //check if they're not the same to minimize the amount of edited values.
		onstation = circuit.onstation //if it was constructed outside mapload, sync the vendor up with the circuit's var so you can't bypass price requirements by moving / reconstructing it off station.
	Radio = new /obj/item/radio(src)
	Radio.listening = 0

/obj/machinery/vending/Destroy()
	QDEL_NULL(wires)
	QDEL_NULL(coin)
	QDEL_NULL(bill)
	QDEL_NULL(Radio)
	return ..()

/obj/machinery/vending/can_speak()
	return !shut_up

/obj/machinery/vending/RefreshParts()         //Better would be to make constructable child
	if(!component_parts)
		return

	product_records = list()
	hidden_records = list()
	coin_records = list()
	build_inventory(products, product_records, start_empty = TRUE)
	build_inventory(contraband, hidden_records, start_empty = TRUE)
	build_inventory(premium, coin_records, start_empty = TRUE)
	for(var/obj/item/vending_refill/VR in component_parts)
		restock(VR)

/obj/machinery/vending/deconstruct(disassembled = TRUE)
	if(!refill_canister) //the non constructable vendors drop metal instead of a machine frame.
		if(!(flags_1 & NODECONSTRUCT_1))
			new /obj/item/stack/sheet/iron(loc, 3)
		qdel(src)
	else
		..()

/obj/machinery/vending/update_appearance(updates=ALL)
	. = ..()
	if(machine_stat & BROKEN)
		set_light(0)
		return
	set_light(powered() ? MINIMUM_USEFUL_LIGHT_RANGE : 0)

/obj/machinery/vending/update_icon_state()
	if(machine_stat & BROKEN)
		icon_state = "[initial(icon_state)]-broken"
		return ..()
	icon_state = "[initial(icon_state)][powered() ? null : "-off"]"
	return ..()

/obj/machinery/vending/update_overlays()
	. = ..()
	if(!light_mask)
		return
	if(!(machine_stat & BROKEN) && powered())
		. += emissive_appearance(icon, light_mask)

/obj/machinery/vending/atom_break(damage_flag)
	. = ..()
	if(!.)
		return

	var/dump_amount = 0
	var/found_anything = TRUE
	while (found_anything)
		found_anything = FALSE
		for(var/record in shuffle(product_records))
			var/datum/data/vending_product/R = record
			if(R.amount <= 0) //Try to use a record that actually has something to dump.
				continue
			var/dump_path = R.product_path
			if(!dump_path)
				continue
			R.amount--
			// busting open a vendor will destroy some of the contents
			if(found_anything && prob(80))
				continue

			var/obj/O = new dump_path(loc)
			step(O, pick(GLOB.alldirs))
			found_anything = TRUE
			dump_amount++
			if (dump_amount >= 16)
				return

GLOBAL_LIST_EMPTY(vending_products)
/**
 * Build the inventory of the vending machine from it's product and record lists
 *
 * This builds up a full set of /datum/data/vending_products from the product list of the vending machine type
 * Arguments:
 * * productlist - the list of products that need to be converted
 * * recordlist - the list containing /datum/data/vending_product datums
 * * startempty - should we set vending_product record amount from the product list (so it's prefilled at roundstart)
 */
/obj/machinery/vending/proc/build_inventory(list/productlist, list/recordlist, start_empty = FALSE)
	default_price = round(initial(default_price) * SSeconomy.inflation_value())
	extra_price = round(initial(extra_price) * SSeconomy.inflation_value())
	for(var/typepath in productlist)
		var/amount = productlist[typepath]
		if(isnull(amount))
			amount = 0

		var/obj/item/temp = typepath
		var/datum/data/vending_product/R = new /datum/data/vending_product()
		GLOB.vending_products[typepath] = 1
		R.name = initial(temp.name)
		R.product_path = typepath
		if(!start_empty)
			R.amount = amount
		R.max_amount = amount
		///Prices of vending machines are all increased uniformly.
		R.custom_price = round(initial(temp.custom_price) * SSeconomy.inflation_value())
		R.custom_premium_price = round(initial(temp.custom_premium_price) * SSeconomy.inflation_value())
		R.age_restricted = initial(temp.age_restricted)
		R.colorable = !!(initial(temp.greyscale_config) && initial(temp.greyscale_colors) && (initial(temp.flags_1) & IS_PLAYER_COLORABLE_1))
		recordlist += R

/**
 * Reassign the prices of the vending machine as a result of the inflation value, as provided by SSeconomy
 *
 * This rebuilds both /datum/data/vending_products lists for premium and standard products based on their most relevant pricing values.
 * Arguments:
 * * recordlist - the list of standard product datums in the vendor to refresh their prices.
 * * premiumlist - the list of premium product datums in the vendor to refresh their prices.
 */
/obj/machinery/vending/proc/reset_prices(list/recordlist, list/premiumlist)
	default_price = round(initial(default_price) * SSeconomy.inflation_value())
	extra_price = round(initial(extra_price) * SSeconomy.inflation_value())
	for(var/R in recordlist)
		var/datum/data/vending_product/record = R
		var/obj/item/potential_product = record.product_path
		record.custom_price = round(initial(potential_product.custom_price) * SSeconomy.inflation_value())
	for(var/R in premiumlist)
		var/datum/data/vending_product/record = R
		var/obj/item/potential_product = record.product_path
		var/premium_sanity = round(initial(potential_product.custom_premium_price))
		if(premium_sanity)
			record.custom_premium_price = round(premium_sanity * SSeconomy.inflation_value())
			continue
		//For some ungodly reason, some premium only items only have a custom_price
		record.custom_premium_price = round(extra_price + (initial(potential_product.custom_price) * (SSeconomy.inflation_value() - 1)))

/**
 * Refill a vending machine from a refill canister
 *
 * This takes the products from the refill canister and then fills the products,contraband and premium product categories
 *
 * Arguments:
 * * canister - the vending canister we are refilling from
 */
/obj/machinery/vending/proc/restock(obj/item/vending_refill/canister)
	if (!canister.products)
		canister.products = products.Copy()
	if (!canister.contraband)
		canister.contraband = contraband.Copy()
	if (!canister.premium)
		canister.premium = premium.Copy()
	. = 0
	. += refill_inventory(canister.products, product_records)
	. += refill_inventory(canister.contraband, hidden_records)
	. += refill_inventory(canister.premium, coin_records)
/**
 * Refill our inventory from the passed in product list into the record list
 *
 * Arguments:
 * * productlist - list of types -> amount
 * * recordlist - existing record datums
 */
/obj/machinery/vending/proc/refill_inventory(list/productlist, list/recordlist)
	. = 0
	for(var/R in recordlist)
		var/datum/data/vending_product/record = R
		var/diff = min(record.max_amount - record.amount, productlist[record.product_path])
		if (diff)
			productlist[record.product_path] -= diff
			record.amount += diff
			. += diff
/**
 * Set up a refill canister that matches this machines products
 *
 * This is used when the machine is deconstructed, so the items aren't "lost"
 */
/obj/machinery/vending/proc/update_canister()
	if (!component_parts)
		return

	var/obj/item/vending_refill/R = locate() in component_parts
	if (!R)
		CRASH("Constructible vending machine did not have a refill canister")

	R.products = unbuild_inventory(product_records)
	R.contraband = unbuild_inventory(hidden_records)
	R.premium = unbuild_inventory(coin_records)

/**
 * Given a record list, go through and and return a list of type -> amount
 */
/obj/machinery/vending/proc/unbuild_inventory(list/recordlist)
	. = list()
	for(var/R in recordlist)
		var/datum/data/vending_product/record = R
		.[record.product_path] += record.amount

/obj/machinery/vending/crowbar_act(mob/living/user, obj/item/I)
	if(!component_parts)
		return FALSE
	default_deconstruction_crowbar(I)
	return TRUE

/obj/machinery/vending/wrench_act(mob/living/user, obj/item/I)
	..()
	if(panel_open)
		default_unfasten_wrench(user, I, time = 60)
		unbuckle_all_mobs(TRUE)
	return TRUE

/obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/I)
	if(..())
		return TRUE
	if(anchored)
		default_deconstruction_screwdriver(user, icon_state, icon_state, I)
		cut_overlays()
		if(panel_open)
			add_overlay("[initial(icon_state)]-panel")
		updateUsrDialog()
	else
		to_chat(user, span_warning("You must first secure [src]."))
	return TRUE

/obj/machinery/vending/attackby(obj/item/I, mob/living/user, params)
	if(panel_open && is_wire_tool(I))
		wires.interact(user)
		return

	if(refill_canister && istype(I, refill_canister))
		if (!panel_open)
			to_chat(user, span_warning("You should probably unscrew the service panel first!"))
		else if (machine_stat & (BROKEN|NOPOWER))
			to_chat(user, span_notice("[src] does not respond."))
		else
			//if the panel is open we attempt to refill the machine
			var/obj/item/vending_refill/canister = I
			if(canister.get_part_rating() == 0)
				to_chat(user, span_warning("[canister] is empty!"))
			else
				// instantiate canister if needed
				var/transferred = restock(canister)
				if(transferred)
					to_chat(user, span_notice("You loaded [transferred] items in [src]."))
				else
					to_chat(user, span_warning("There's nothing to restock!"))
			return
	//if(compartmentLoadAccessCheck(user) && !user.combat_mode) //SEPTIC EDIT REMOVAL
	//SEPTIC EDIT BEGIN
	if(compartmentLoadAccessCheck(user) && IS_HELP_INTENT(user, params2list(params)))
	//SEPTIC EDIT END
		if(canLoadItem(I))
			loadingAttempt(I,user)
			updateUsrDialog() //can't put this on the proc above because we spam it below

		if(istype(I, /obj/item/storage/bag)) //trays USUALLY
			var/obj/item/storage/T = I
			var/loaded = 0
			var/denied_items = 0
			for(var/obj/item/the_item in T.contents)
				if(contents.len >= MAX_VENDING_INPUT_AMOUNT) // no more than 30 item can fit inside, legacy from snack vending although not sure why it exists
					to_chat(user, span_warning("[src]'s compartment is full."))
					break
				if(canLoadItem(the_item) && loadingAttempt(the_item,user))
					SEND_SIGNAL(T, COMSIG_TRY_STORAGE_TAKE, the_item, src, TRUE)
					loaded++
				else
					denied_items++
			if(denied_items)
				to_chat(user, span_warning("[src] refuses some items!"))
			if(loaded)
				to_chat(user, span_notice("You insert [loaded] dishes into [src]'s compartment."))
				updateUsrDialog()
	else
		. = ..()
		if(tiltable && !tilted && I.force)
			switch(rand(1, 100))
				if(1 to 5)
					freebie(user, 3)
				if(6 to 15)
					freebie(user, 2)
				if(16 to 25)
					freebie(user, 1)
				if(76 to 90)
					tilt(user)
				if(91 to 100)
					tilt(user, crit=TRUE)

/obj/machinery/vending/proc/freebie(mob/fatty, freebies)
	visible_message(span_notice("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"]!"))

	for(var/i in 1 to freebies)
		playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
		for(var/datum/data/vending_product/R in shuffle(product_records))

			if(R.amount <= 0) //Try to use a record that actually has something to dump.
				continue
			var/dump_path = R.product_path
			if(!dump_path)
				continue

			R.amount--
			new dump_path(get_turf(src))
			break

///Tilts ontop of the atom supplied, if crit is true some extra shit can happen. Returns TRUE if it dealt damage to something.
/obj/machinery/vending/proc/tilt(atom/fatty, crit=FALSE)
	visible_message(span_danger("[src] tips over!"))
	tilted = TRUE
	layer = ABOVE_MOB_LAYER

	var/crit_case
	if(crit)
		crit_case = rand(1,6)

	if(forcecrit)
		crit_case = forcecrit

	. = FALSE

	if(in_range(fatty, src))
		for(var/mob/living/L in get_turf(fatty))
			var/was_alive = (L.stat != DEAD)
			var/mob/living/carbon/C = L

			SEND_SIGNAL(L, COMSIG_ON_VENDOR_CRUSH)

			if(istype(C))
				var/crit_rebate = 0 // lessen the normal damage we deal for some of the crits

				if(crit_case < 5) // the body/head asplode case has its own description
					C.visible_message(span_danger("[C] is crushed by [src]!"), \
						span_userdanger("You are crushed by [src]!"))

				switch(crit_case) // only carbons can have the fun crits
					if(1) // shatter their legs and bleed 'em
						crit_rebate = 60
						C.bleed(150)
						var/obj/item/bodypart/l_leg/l = C.get_bodypart(BODY_ZONE_L_LEG)
						if(l)
							l.receive_damage(brute=200)
						var/obj/item/bodypart/r_leg/r = C.get_bodypart(BODY_ZONE_R_LEG)
						if(r)
							r.receive_damage(brute=200)
						if(l || r)
							C.visible_message(span_danger("[C]'s legs shatter with a sickening crunch!"), \
								span_userdanger("Your legs shatter with a sickening crunch!"))
					if(2) // pin them beneath the machine until someone untilts it
						forceMove(get_turf(C))
						buckle_mob(C, force=TRUE)
						C.visible_message(span_danger("[C] is pinned underneath [src]!"), \
							span_userdanger("You are pinned down by [src]!"))
					if(3) // glass candy
						crit_rebate = 50
						for(var/i = 0, i < num_shards, i++)
							var/obj/item/shard/shard = new /obj/item/shard(get_turf(C))
							shard.embedding = list(embed_chance = 100, ignore_throwspeed_threshold = TRUE, impact_pain_mult=1, pain_chance=5)
							shard.updateEmbedding()
							C.hitby(shard, skipcatch = TRUE, hitpush = FALSE)
							shard.embedding = list()
							shard.updateEmbedding()
					if(4) // paralyze this binch
						// the new paraplegic gets like 4 lines of losing their legs so skip them
						visible_message(span_danger("[C]'s spinal cord is obliterated with a sickening crunch!"), ignored_mobs = list(C))
						C.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic)
					if(5) // limb squish!
						for(var/i in C.bodyparts)
							var/obj/item/bodypart/squish_part = i
							if(squish_part.is_organic_limb())
								var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate))
								squish_part.force_wound_upwards(type_wound)
							else
								squish_part.receive_damage(brute=30)
						C.visible_message(span_danger("[C]'s body is maimed underneath the mass of [src]!"), \
							span_userdanger("Your body is maimed underneath the mass of [src]!"))
					if(6) // skull squish!
						var/obj/item/bodypart/head/O = C.get_bodypart(BODY_ZONE_HEAD)
						if(O)
							C.visible_message(span_danger("[O] explodes in a shower of gore beneath [src]!"), \
								span_userdanger("Oh f-"))
							O.dismember()
							O.drop_organs()
							qdel(O)
							new /obj/effect/gibspawner/human/bodypartless(get_turf(C))

				if(prob(30))
					C.apply_damage(max(0, squish_damage - crit_rebate), forced=TRUE, spread_damage=TRUE) // the 30% chance to spread the damage means you escape breaking any bones
				else
					C.take_bodypart_damage((squish_damage - crit_rebate)*0.5, wound_bonus = 5) // otherwise, deal it to 2 random limbs (or the same one) which will likely shatter something
					C.take_bodypart_damage((squish_damage - crit_rebate)*0.5, wound_bonus = 5)
				C.AddElement(/datum/element/squish, 80 SECONDS)
			else
				L.visible_message(span_danger("[L] is crushed by [src]!"), \
				span_userdanger("You are crushed by [src]!"))
				L.apply_damage(squish_damage, forced=TRUE)
				if(crit_case)
					L.apply_damage(squish_damage, forced=TRUE)
			if(was_alive && L.stat == DEAD && L.client)
				L.client.give_award(/datum/award/achievement/misc/vendor_squish, L) // good job losing a fight with an inanimate object idiot

			L.Paralyze(60)
			L.emote("scream")
			. = TRUE
			playsound(L, 'sound/effects/blobattack.ogg', 40, TRUE)
			playsound(L, 'sound/effects/splat.ogg', 50, TRUE)
			add_memory_in_range(L, 7, MEMORY_VENDING_CRUSHED, list(DETAIL_PROTAGONIST = L, DETAIL_WHAT_BY = src), story_value = STORY_VALUE_AMAZING, memory_flags = MEMORY_CHECK_BLINDNESS, protagonist_memory_flags = MEMORY_SKIP_UNCONSCIOUS)

	var/matrix/M = matrix()
	M.Turn(pick(90, 270))
	transform = M

	if(get_turf(fatty) != get_turf(src))
		throw_at(get_turf(fatty), 1, 1, spin=FALSE, quickstart=FALSE)

/obj/machinery/vending/proc/untilt(mob/user)
	if(user)
		user.visible_message(span_notice("[user] rights [src]."), \
			span_notice("You right [src]."))

	unbuckle_all_mobs(TRUE)

	tilted = FALSE
	layer = initial(layer)

	var/matrix/M = matrix()
	M.Turn(0)
	transform = M

/obj/machinery/vending/proc/loadingAttempt(obj/item/I, mob/user)
	. = TRUE
	if(!user.transferItemToLoc(I, src))
		return FALSE
	if(vending_machine_input[format_text(I.name)])
		vending_machine_input[format_text(I.name)]++
	else
		vending_machine_input[format_text(I.name)] = 1
	to_chat(user, span_notice("You insert [I] into [src]'s input compartment."))
	loaded_items++

/obj/machinery/vending/unbuckle_mob(mob/living/buckled_mob, force=FALSE)
	if(!force)
		return
	. = ..()

/**
 * Is the passed in user allowed to load this vending machines compartments
 *
 * Arguments:
 * * user - mob that is doing the loading of the vending machine
 */
/obj/machinery/vending/proc/compartmentLoadAccessCheck(mob/user)
	if(!canload_access_list)
		return TRUE
	else
		var/do_you_have_access = FALSE
		var/req_access_txt_holder = req_access_txt
		for(var/i in canload_access_list)
			req_access_txt = i
			if(!allowed(user) && !(obj_flags & EMAGGED) && scan_id)
				continue
			else
				do_you_have_access = TRUE
				break //you passed don't bother looping anymore
		req_access_txt = req_access_txt_holder // revert to normal (before the proc ran)
		if(do_you_have_access)
			return TRUE
		else
			to_chat(user, span_warning("[src]'s input compartment blinks red: Access denied."))
			return FALSE

/obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/W)
	if(!istype(W))
		return FALSE
	if((flags_1 & NODECONSTRUCT_1) && !W.works_from_distance)
		return FALSE
	if(!component_parts || !refill_canister)
		return FALSE

	var/moved = 0
	if(panel_open || W.works_from_distance)
		if(W.works_from_distance)
			display_parts(user)
		for(var/I in W)
			if(istype(I, refill_canister))
				moved += restock(I)
	else
		display_parts(user)
	if(moved)
		to_chat(user, span_notice("[moved] items restocked."))
		W.play_rped_sound()
	return TRUE

/obj/machinery/vending/on_deconstruction()
	update_canister()
	. = ..()

/obj/machinery/vending/emag_act(mob/user)
	if(obj_flags & EMAGGED)
		return
	obj_flags |= EMAGGED
	to_chat(user, span_notice("You short out the product lock on [src]."))

/obj/machinery/vending/_try_interact(mob/user)
	if(seconds_electrified && !(machine_stat & NOPOWER))
		if(shock(user, 100))
			return

	if(tilted && !user.buckled && !isAI(user))
		to_chat(user, span_notice("You begin righting [src]."))
		if(do_after(user, 50, target=src))
			untilt(user)
		return

	return ..()

/obj/machinery/vending/ui_assets(mob/user)
	return list(
		get_asset_datum(/datum/asset/spritesheet/vending),
	)

/obj/machinery/vending/ui_interact(mob/user, datum/tgui/ui)
	ui = SStgui.try_update_ui(user, src, ui)
	if(!ui)
		ui = new(user, src, "Vending", name)
		ui.open()

/obj/machinery/vending/ui_static_data(mob/user)
	. = list()
	.["onstation"] = onstation
	.["department"] = payment_department
	.["jobDiscount"] = VENDING_DISCOUNT
	.["product_records"] = list()
	for (var/datum/data/vending_product/R in product_records)
		var/list/data = list(
			path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"),
			name = R.name,
			price = R.custom_price || default_price,
			max_amount = R.max_amount,
			ref = REF(R)
		)
		.["product_records"] += list(data)
	.["coin_records"] = list()
	for (var/datum/data/vending_product/R in coin_records)
		var/list/data = list(
			path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"),
			name = R.name,
			price = R.custom_premium_price || extra_price,
			max_amount = R.max_amount,
			ref = REF(R),
			premium = TRUE
		)
		.["coin_records"] += list(data)
	.["hidden_records"] = list()
	for (var/datum/data/vending_product/R in hidden_records)
		var/list/data = list(
			path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"),
			name = R.name,
			price = R.custom_premium_price || extra_price,
			max_amount = R.max_amount,
			ref = REF(R),
			premium = TRUE
		)
		.["hidden_records"] += list(data)

/obj/machinery/vending/ui_data(mob/user)
	. = list()
	var/obj/item/card/id/C
	if(isliving(user))
		var/mob/living/L = user
		C = L.get_idcard(TRUE)
	if(C?.registered_account)
		.["user"] = list()
		.["user"]["name"] = C.registered_account.account_holder
		.["user"]["cash"] = C.registered_account.account_balance
		if(C.registered_account.account_job)
			.["user"]["job"] = C.registered_account.account_job.title
			.["user"]["department"] = C.registered_account.account_job.paycheck_department
		else
			.["user"]["job"] = "No Job"
			.["user"]["department"] = "No Department"
	.["stock"] = list()
	for (var/datum/data/vending_product/R in product_records + coin_records + hidden_records)
		var/list/product_data = list(
			name = R.name,
			amount = R.amount,
			colorable = R.colorable,
		)
		.["stock"][R.name] = product_data
	.["extended_inventory"] = extended_inventory

/obj/machinery/vending/ui_act(action, params)
	. = ..()
	if(.)
		return
	switch(action)
		if("vend")
			. = vend(params)
		if("select_colors")
			. = select_colors(params)

/obj/machinery/vending/proc/can_vend(user, silent=FALSE)
	. = FALSE
	if(!vend_ready)
		return
	if(panel_open)
		to_chat(user, span_warning("The vending machine cannot dispense products while its service panel is open!"))
		return
	return TRUE

/obj/machinery/vending/proc/select_colors(list/params)
	. = TRUE
	if(!can_vend(usr))
		return
	var/datum/data/vending_product/product = locate(params["ref"])
	var/atom/fake_atom = product.product_path

	var/list/allowed_configs = list()
	var/config = initial(fake_atom.greyscale_config)
	if(!config)
		return
	allowed_configs += "[config]"
	if(ispath(fake_atom, /obj/item))
		var/obj/item/item = fake_atom
		if(initial(item.greyscale_config_worn))
			allowed_configs += "[initial(item.greyscale_config_worn)]"
		if(initial(item.greyscale_config_inhand_left))
			allowed_configs += "[initial(item.greyscale_config_inhand_left)]"
		if(initial(item.greyscale_config_inhand_right))
			allowed_configs += "[initial(item.greyscale_config_inhand_right)]"

	var/datum/greyscale_modify_menu/menu = new(
		src, usr, allowed_configs, CALLBACK(src, .proc/vend_greyscale, params),
		starting_icon_state=initial(fake_atom.icon_state),
		starting_config=initial(fake_atom.greyscale_config),
		starting_colors=initial(fake_atom.greyscale_colors)
	)
	menu.ui_interact(usr)

/obj/machinery/vending/proc/vend_greyscale(list/params, datum/greyscale_modify_menu/menu)
	if(usr != menu.user)
		return
	if(!menu.target.can_interact(usr))
		return
	vend(params, menu.split_colors)

/obj/machinery/vending/proc/vend(list/params, list/greyscale_colors)
	. = TRUE
	if(!can_vend(usr))
		return
	vend_ready = FALSE //One thing at a time!!
	var/datum/data/vending_product/R = locate(params["ref"])
	var/list/record_to_check = product_records + coin_records
	if(extended_inventory)
		record_to_check = product_records + coin_records + hidden_records
	if(!R || !istype(R) || !R.product_path)
		vend_ready = TRUE
		return
	var/price_to_use = default_price
	if(R.custom_price)
		price_to_use = R.custom_price
	if(R in hidden_records)
		if(!extended_inventory)
			vend_ready = TRUE
			return
	else if (!(R in record_to_check))
		vend_ready = TRUE
		message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!")
		return
	if (R.amount <= 0)
		say("Sold out of [R.name].")
		flick(icon_deny,src)
		vend_ready = TRUE
		return
	if(onstation)
		var/obj/item/card/id/C
		if(isliving(usr))
			var/mob/living/L = usr
			C = L.get_idcard(TRUE)
		if(!C)
			say("No card found.")
			flick(icon_deny,src)
			vend_ready = TRUE
			return
		else if (!C.registered_account)
			say("No account found.")
			flick(icon_deny,src)
			vend_ready = TRUE
			return
		else if(!C.registered_account.account_job)
			say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
			flick(icon_deny, src)
			vend_ready = TRUE
			return
		else if(age_restrictions && R.age_restricted && (!C.registered_age || C.registered_age < AGE_MINOR))
			say("You are not of legal age to purchase [R.name].")
			if(!(usr in GLOB.narcd_underages))
				Radio.set_frequency(FREQ_SECURITY)
				Radio.talk_into(src, "SECURITY ALERT: Underaged crewmember [usr] recorded attempting to purchase [R.name] in [get_area(src)]. Please watch for substance abuse.", FREQ_SECURITY)
				GLOB.narcd_underages += usr
			flick(icon_deny,src)
			vend_ready = TRUE
			return
		var/datum/bank_account/account = C.registered_account
		if(account.account_job && account.account_job.paycheck_department == payment_department)
			price_to_use = max(round(price_to_use * VENDING_DISCOUNT), 1) //No longer free, but signifigantly cheaper.
		if(coin_records.Find(R) || hidden_records.Find(R))
			price_to_use = R.custom_premium_price ? R.custom_premium_price : extra_price
		if(price_to_use && !account.adjust_money(-price_to_use))
			say("You do not possess the funds to purchase [R.name].")
			flick(icon_deny,src)
			vend_ready = TRUE
			return
		var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
		if(D)
			D.adjust_money(price_to_use)
			SSblackbox.record_feedback("amount", "vending_spent", price_to_use)
			log_econ("[price_to_use] credits were inserted into [src] by [D.account_holder] to buy [R].")
	if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
		say("Thank you for shopping with [src]!")
		purchase_message_cooldown = world.time + 5 SECONDS
		//This is not the best practice, but it's safe enough here since the chances of two people using a machine with the same ref in 5 seconds is fuck low
		last_shopper = REF(usr)
	use_power(5)
	if(icon_vend) //Show the vending animation if needed
		flick(icon_vend,src)
	playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
	var/obj/item/vended_item = new R.product_path(get_turf(src))
	if(greyscale_colors)
		vended_item.set_greyscale(colors=greyscale_colors)
	R.amount--
	if(usr.CanReach(src) && usr.put_in_hands(vended_item))
		to_chat(usr, span_notice("You take [R.name] out of the slot."))
	else
		to_chat(usr, span_warning("[capitalize(R.name)] falls onto the floor!"))
	SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[R.product_path]"))
	vend_ready = TRUE

/obj/machinery/vending/process(delta_time)
	if(machine_stat & (BROKEN|NOPOWER))
		return PROCESS_KILL
	if(!active)
		return

	if(seconds_electrified > MACHINE_NOT_ELECTRIFIED)
		seconds_electrified--

	//Pitch to the people!  Really sell it!
	if(last_slogan + slogan_delay <= world.time && slogan_list.len > 0 && !shut_up && DT_PROB(2.5, delta_time))
		var/slogan = pick(slogan_list)
		speak(slogan)
		last_slogan = world.time

	if(shoot_inventory && DT_PROB(shoot_inventory_chance, delta_time))
		throw_item()
/**
 * Speak the given message verbally
 *
 * Checks if the machine is powered and the message exists
 *
 * Arguments:
 * * message - the message to speak
 */
/obj/machinery/vending/proc/speak(message)
	if(machine_stat & (BROKEN|NOPOWER))
		return
	if(!message)
		return

	say(message)

/obj/machinery/vending/power_change()
	. = ..()
	if(powered())
		START_PROCESSING(SSmachines, src)

//Somebody cut an important wire and now we're following a new definition of "pitch."
/**
 * Throw an item from our internal inventory out in front of us
 *
 * This is called when we are hacked, it selects a random product from the records that has an amount > 0
 * This item is then created and tossed out in front of us with a visible message
 */
/obj/machinery/vending/proc/throw_item()
	var/obj/throw_item = null
	var/mob/living/target = locate() in view(7,src)
	if(!target)
		return FALSE

	for(var/datum/data/vending_product/R in shuffle(product_records))
		if(R.amount <= 0) //Try to use a record that actually has something to dump.
			continue
		var/dump_path = R.product_path
		if(!dump_path)
			continue

		R.amount--
		throw_item = new dump_path(loc)
		break
	if(!throw_item)
		return FALSE

	pre_throw(throw_item)

	throw_item.throw_at(target, 16, 3)
	visible_message(span_danger("[src] launches [throw_item] at [target]!"))
	return TRUE
/**
 * A callback called before an item is tossed out
 *
 * Override this if you need to do any special case handling
 *
 * Arguments:
 * * I - obj/item being thrown
 */
/obj/machinery/vending/proc/pre_throw(obj/item/I)
	return
/**
 * Shock the passed in user
 *
 * This checks we have power and that the passed in prob is passed, then generates some sparks
 * and calls electrocute_mob on the user
 *
 * Arguments:
 * * user - the user to shock
 * * prb - probability the shock happens
 */
/obj/machinery/vending/proc/shock(mob/living/user, prb)
	if(!istype(user) || machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock
		return FALSE
	if(!prob(prb))
		return FALSE
	do_sparks(5, TRUE, src)
	var/check_range = TRUE
	if(electrocute_mob(user, get_area(src), src, 0.7, check_range))
		return TRUE
	else
		return FALSE
/**
 * Are we able to load the item passed in
 *
 * Arguments:
 * * I - the item being loaded
 * * user - the user doing the loading
 */
/obj/machinery/vending/proc/canLoadItem(obj/item/I, mob/user)
	return FALSE

/obj/machinery/vending/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
	. = ..()
	var/mob/living/L = AM
	if(tilted || !istype(L) || !prob(20 * (throwingdatum.speed - L.throw_speed))) // hulk throw = +20%, neckgrab throw = +20%
		return

	tilt(L)

/obj/machinery/vending/attack_tk_grab(mob/user)
	to_chat(user, span_warning("[src] seems to resist your mental grasp!"))

///Crush the mob that the vending machine got thrown at
/obj/machinery/vending/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
	if(isliving(hit_atom))
		tilt(fatty=hit_atom)
	return ..()

/obj/machinery/vending/custom
	name = "Custom Vendor"
	icon_state = "custom"
	icon_deny = "custom-deny"
	max_integrity = 400
	payment_department = NO_FREEBIES
	light_mask = "custom-light-mask"
	refill_canister = /obj/item/vending_refill/custom
	/// where the money is sent
	var/datum/bank_account/private_a
	/// max number of items that the custom vendor can hold
	var/max_loaded_items = 20
	/// Base64 cache of custom icons.
	var/list/base64_cache = list()

/obj/machinery/vending/custom/compartmentLoadAccessCheck(mob/user)
	. = FALSE
	if(!isliving(user))
		return FALSE
	var/mob/living/L = user
	var/obj/item/card/id/C = L.get_idcard(FALSE)
	if(C?.registered_account && C.registered_account == private_a)
		return TRUE

/obj/machinery/vending/custom/canLoadItem(obj/item/I, mob/user)
	. = FALSE
	if(I.flags_1 & HOLOGRAM_1)
		say("This vendor cannot accept nonexistent items.")
		return
	if(loaded_items >= max_loaded_items)
		say("There are too many items in stock.")
		return
	if(istype(I, /obj/item/stack))
		say("Loose items may cause problems, try to use it inside wrapping paper.")
		return
	if(I.custom_price)
		return TRUE

/obj/machinery/vending/custom/ui_data(mob/user)
	. = ..()
	.["access"] = compartmentLoadAccessCheck(user)
	.["vending_machine_input"] = list()
	for (var/O in vending_machine_input)
		if(vending_machine_input[O] > 0)
			var/base64
			var/price = 0
			for(var/obj/item/T in contents)
				if(format_text(T.name) == O)
					price = T.custom_price
					if(!base64)
						if(base64_cache[T.type])
							base64 = base64_cache[T.type]
						else
							base64 = icon2base64(getFlatIcon(T, no_anim=TRUE))
							base64_cache[T.type] = base64
					break
			var/list/data = list(
				name = O,
				price = price,
				img = base64,
				amount = vending_machine_input[O],
				colorable = FALSE
			)
			.["vending_machine_input"] += list(data)

/obj/machinery/vending/custom/ui_act(action, params)
	. = ..()
	if(.)
		return
	switch(action)
		if("dispense")
			. = TRUE
			if(!vend_ready)
				return
			var/N = params["item"]
			var/obj/item/S
			vend_ready = FALSE
			var/obj/item/card/id/C
			if(isliving(usr))
				var/mob/living/L = usr
				C = L.get_idcard(TRUE)
			if(!C)
				say("No card found.")
				flick(icon_deny,src)
				vend_ready = TRUE
				return
			else if (!C.registered_account)
				say("No account found.")
				flick(icon_deny,src)
				vend_ready = TRUE
				return
			var/datum/bank_account/account = C.registered_account
			for(var/obj/O in contents)
				if(format_text(O.name) == N)
					S = O
					break
			if(S)
				if(compartmentLoadAccessCheck(usr))
					vending_machine_input[N] = max(vending_machine_input[N] - 1, 0)
					S.forceMove(drop_location())
					loaded_items--
					use_power(5)
					vend_ready = TRUE
					updateUsrDialog()
					return
				if(account.has_money(S.custom_price))
					account.adjust_money(-S.custom_price)
					var/datum/bank_account/owner = private_a
					if(owner)
						owner.adjust_money(S.custom_price)
						SSblackbox.record_feedback("amount", "vending_spent", S.custom_price)
						log_econ("[S.custom_price] credits were spent on [src] buying a [S] by [owner.account_holder], owned by [private_a.account_holder].")
					vending_machine_input[N] = max(vending_machine_input[N] - 1, 0)
					S.forceMove(drop_location())
					loaded_items--
					use_power(5)
					if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
						say("Thank you for buying local and purchasing [S]!")
						purchase_message_cooldown = world.time + 5 SECONDS
						last_shopper = REF(usr)
					vend_ready = TRUE
					updateUsrDialog()
					return
				else
					say("You do not possess the funds to purchase this.")
			vend_ready = TRUE

/obj/machinery/vending/custom/attackby(obj/item/I, mob/user, params)
	if(!private_a && isliving(user))
		var/mob/living/L = user
		var/obj/item/card/id/C = L.get_idcard(TRUE)
		if(C?.registered_account)
			private_a = C.registered_account
			say("\The [src] has been linked to [C].")

	if(compartmentLoadAccessCheck(user))
		if(istype(I, /obj/item/pen))
			name = stripped_input(user,"Set name","Name", name, 20)
			desc = stripped_input(user,"Set description","Description", desc, 60)
			slogan_list += stripped_input(user,"Set slogan","Slogan","Epic", 60)
			last_slogan = world.time + rand(0, slogan_delay)
			return

	return ..()

/obj/machinery/vending/custom/crowbar_act(mob/living/user, obj/item/I)
	return FALSE

/obj/machinery/vending/custom/Destroy()
	unbuckle_all_mobs(TRUE)
	var/turf/T = get_turf(src)
	if(T)
		for(var/obj/item/I in contents)
			I.forceMove(T)
		explosion(src, devastation_range = -1, light_impact_range = 3)
	return ..()

/obj/machinery/vending/custom/unbreakable
	name = "Indestructible Vendor"
	resistance_flags = INDESTRUCTIBLE

/obj/item/vending_refill/custom
	machine_name = "Custom Vendor"
	icon_state = "refill_custom"
	custom_premium_price = PAYCHECK_ASSISTANT

/obj/item/price_tagger
	name = "price tagger"
	desc = "This tool is used to set a price for items used in custom vendors."
	icon = 'icons/obj/device.dmi'
	icon_state = "pricetagger"
	custom_premium_price = PAYCHECK_ASSISTANT * 0.5
	///the price of the item
	var/price = 1

/obj/item/price_tagger/attack_self(mob/user)
	price = max(1, round(input(user,"set price","price") as num|null, 1))
	to_chat(user, span_notice(" The [src] will now give things a [price] cr tag."))

/obj/item/price_tagger/afterattack(atom/target, mob/user, proximity)
	. = ..()
	if(!proximity)
		return
	if(isitem(target))
		var/obj/item/I = target
		I.custom_price = price
		to_chat(user, span_notice("You set the price of [I] to [price] cr."))

/obj/machinery/vending/custom/greed //name and like decided by the spawn
	icon_state = "greed"
	icon_deny = "greed-deny"
	light_mask = "greed-light-mask"
	custom_materials = list(/datum/material/gold = MINERAL_MATERIAL_AMOUNT * 5)

/obj/machinery/vending/custom/greed/Initialize(mapload)
	. = ..()
	//starts in a state where you can move it
	panel_open = TRUE
	set_anchored(FALSE)
	add_overlay("[initial(icon_state)]-panel")
	//and references the deity
	name = "[GLOB.deity]'s Consecrated Vendor"
	desc = "A vending machine created by [GLOB.deity]."
	slogan_list = list("[GLOB.deity] says: It's your divine right to buy!")
	add_filter("vending_outline", 9, list("type" = "outline", "color" = COLOR_VERY_SOFT_YELLOW))
	add_filter("vending_rays", 10, list("type" = "rays", "size" = 35, "color" = COLOR_VIVID_YELLOW))


code:
/obj/machinery/vending/assist
	name = "\improper Part-Mart"
	desc = "All the finest of miscellaneous electronics one could ever need! Not responsible for any injuries caused by reckless misuse of parts."
	icon_state = "parts"
	icon_deny = "parts-deny"
	products = list(
		/obj/item/assembly/prox_sensor = 5,
		/obj/item/assembly/igniter = 3,
		/obj/item/assembly/signaler = 4,
		/obj/item/wirecutters = 1,
		/obj/item/cartridge/signal = 4,
		/obj/item/stock_parts/matter_bin = 3,
		/obj/item/stock_parts/manipulator = 3,
		/obj/item/stock_parts/micro_laser = 3,
		/obj/item/stock_parts/scanning_module = 3,
		/obj/item/stock_parts/capacitor = 3
	)
	contraband = list(
		/obj/item/assembly/timer = 2,
		/obj/item/assembly/voice = 2,
		/obj/item/assembly/health = 2,
		/obj/item/stock_parts/cell/high = 1
	)
	premium = list(
		/obj/item/price_tagger = 3,
		/obj/item/vending_refill/custom = 3,
		/obj/item/circuitboard/machine/vendor = 3,
		/obj/item/assembly/igniter/condenser = 2
	)

	refill_canister = /obj/item/vending_refill/assist
	product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!"
	default_price = PAYCHECK_ASSISTANT * 0.7 //Default of 35.
	extra_price = PAYCHECK_EASY
	payment_department = NO_FREEBIES
	light_mask = "parts-light-mask"

/obj/item/vending_refill/assist
	machine_name = "Part-Mart"
	icon_state = "refill_parts"


code:
/obj/machinery/vending/autodrobe
	name = "\improper AutoDrobe"
	desc = "A vending machine for costumes."
	icon_state = "theater"
	icon_deny = "theater-deny"
	req_access = list(ACCESS_THEATRE)
	product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!"
	vend_reply = "Thank you for using AutoDrobe!"
	products = list(
		/obj/item/clothing/suit/chickensuit = 1,
		/obj/item/clothing/head/chicken = 1,
		/obj/item/clothing/under/rank/civilian/clown/blue = 1,
		/obj/item/clothing/under/rank/civilian/clown/green = 1,
		/obj/item/clothing/under/rank/civilian/clown/yellow = 1,
		/obj/item/clothing/under/rank/civilian/clown/orange = 1,
		/obj/item/clothing/under/rank/civilian/clown/purple = 1,
		/obj/item/clothing/under/costume/gladiator = 1,
		/obj/item/clothing/head/helmet/gladiator = 1,
		/obj/item/clothing/under/rank/captain/suit = 1,
		/obj/item/clothing/under/rank/captain/suit/skirt = 1,
		/obj/item/clothing/head/flatcap = 1,
		/obj/item/clothing/suit/toggle/labcoat/mad = 1,
		/obj/item/clothing/shoes/jackboots = 1,
		/obj/item/clothing/under/costume/schoolgirl = 1,
		/obj/item/clothing/under/costume/schoolgirl/red = 1,
		/obj/item/clothing/under/costume/schoolgirl/green = 1,
		/obj/item/clothing/under/costume/schoolgirl/orange = 1,
		/obj/item/clothing/head/kitty = 1,
		/obj/item/clothing/under/dress/skirt = 1,
		/obj/item/clothing/head/beret = 1,
		/obj/item/clothing/accessory/waistcoat = 1,
		/obj/item/clothing/under/suit/black = 1,
		/obj/item/clothing/head/that = 1,
		/obj/item/clothing/under/costume/kilt = 1,
		/obj/item/clothing/head/beret = 3,
		/obj/item/clothing/accessory/waistcoat = 1,
		/obj/item/clothing/glasses/monocle =1,
		/obj/item/clothing/head/bowler = 1,
		/obj/item/cane = 1,
		/obj/item/clothing/under/suit/sl = 1,
		/obj/item/clothing/mask/fakemoustache = 1,
		/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,
		/obj/item/clothing/head/plaguedoctorhat = 1,
		/obj/item/clothing/mask/gas/plaguedoctor = 1,
		/obj/item/clothing/suit/toggle/owlwings = 1,
		/obj/item/clothing/under/costume/owl = 1,
		/obj/item/clothing/mask/gas/owl_mask = 1,
		/obj/item/clothing/suit/toggle/owlwings/griffinwings = 1,
		/obj/item/clothing/under/costume/griffin = 1,
		/obj/item/clothing/shoes/griffin = 1,
		/obj/item/clothing/head/griffin = 1,
		/obj/item/clothing/suit/apron = 1,
		/obj/item/clothing/under/suit/waiter = 1,
		/obj/item/clothing/suit/jacket/miljacket = 1,
		/obj/item/clothing/under/costume/pirate = 1,
		/obj/item/clothing/suit/pirate = 1,
		/obj/item/clothing/head/pirate = 1,
		/obj/item/clothing/head/bandana = 1,
		/obj/item/clothing/head/bandana = 1,
		/obj/item/clothing/under/costume/soviet = 1,
		/obj/item/clothing/head/ushanka = 1,
		/obj/item/clothing/suit/imperium_monk = 1,
		/obj/item/clothing/mask/gas/cyborg = 1,
		/obj/item/clothing/suit/chaplainsuit/holidaypriest = 1,
		/obj/item/clothing/suit/chaplainsuit/whiterobe = 1,
		/obj/item/clothing/head/wizard/marisa/fake = 1,
		/obj/item/clothing/suit/wizrobe/marisa/fake = 1,
		/obj/item/clothing/under/dress/sundress = 1,
		/obj/item/clothing/head/witchwig = 1,
		/obj/item/staff/broom = 1,
		/obj/item/clothing/suit/wizrobe/fake = 1,
		/obj/item/clothing/head/wizard/fake = 1,
		/obj/item/staff = 3,
		/obj/item/clothing/mask/gas/sexyclown = 1,
		/obj/item/clothing/under/rank/civilian/clown/sexy = 1,
		/obj/item/clothing/mask/gas/sexymime = 1,
		/obj/item/clothing/under/rank/civilian/mime/sexy = 1,
		/obj/item/clothing/under/rank/civilian/mime/skirt = 1,
		/obj/item/clothing/mask/animal/rat/bat = 1,
		/obj/item/clothing/mask/animal/rat/bee = 1,
		/obj/item/clothing/mask/animal/rat/bear = 1,
		/obj/item/clothing/mask/animal/rat/raven = 1,
		/obj/item/clothing/mask/animal/rat/jackal = 1,
		/obj/item/clothing/mask/animal/rat/fox = 1,
		/obj/item/clothing/mask/animal/frog = 1,
		/obj/item/clothing/mask/animal/rat/tribal = 1,
		/obj/item/clothing/mask/animal/rat = 1,
		/obj/item/clothing/suit/apron/overalls = 1,
		/obj/item/clothing/head/rabbitears =1,
		/obj/item/clothing/head/sombrero = 1,
		/obj/item/clothing/head/sombrero/green = 1,
		/obj/item/clothing/suit/poncho = 1,
		/obj/item/clothing/suit/poncho/green = 1,
		/obj/item/clothing/suit/poncho/red = 1,
		/obj/item/clothing/under/costume/maid = 1,
		/obj/item/clothing/under/rank/civilian/janitor/maid = 1,
		/obj/item/clothing/glasses/cold=1,
		/obj/item/clothing/glasses/heat=1,
		/obj/item/clothing/suit/whitedress = 1,
		/obj/item/clothing/under/rank/civilian/clown/jester = 1,
		/obj/item/clothing/head/jester = 1,
		/obj/item/clothing/under/costume/villain = 1,
		/obj/item/clothing/shoes/singery = 1,
		/obj/item/clothing/under/costume/singer/yellow = 1,
		/obj/item/clothing/shoes/singerb = 1,
		/obj/item/clothing/under/costume/singer/blue = 1,
		/obj/item/clothing/suit/hooded/carp_costume = 1,
		/obj/item/clothing/suit/hooded/ian_costume = 1,
		/obj/item/clothing/suit/hooded/bee_costume = 1,
		/obj/item/clothing/suit/snowman = 1,
		/obj/item/clothing/head/snowman = 1,
		/obj/item/clothing/mask/joy = 1,
		/obj/item/clothing/head/cueball = 1,
		/obj/item/clothing/under/suit/white_on_white = 1,
		/obj/item/clothing/under/costume/sailor = 1,
		/obj/item/clothing/under/costume/referee = 1,
		/obj/item/clothing/mask/whistle = 1,
		/obj/item/clothing/head/delinquent = 1,
		/obj/item/clothing/head/wig/random = 3,
		/obj/item/clothing/head/shrine_wig = 1,
		/obj/item/clothing/suit/shrine_maiden = 1,
		/obj/item/clothing/suit/changshan_red = 1,
		/obj/item/clothing/suit/changshan_blue = 1,
		/obj/item/clothing/suit/cheongsam_red = 1,
		/obj/item/clothing/suit/cheongsam_blue = 1,
		/obj/item/gohei = 1
	)
	contraband = list(
		/obj/item/clothing/suit/judgerobe = 1,
		/obj/item/clothing/head/powdered_wig = 1,
		/obj/item/gun/magic/wand/nothing = 2,
		/obj/item/clothing/glasses/sunglasses/garb = 2,
		/obj/item/clothing/glasses/blindfold = 1,
		/obj/item/clothing/mask/muzzle = 2
	)
	premium = list(
		/obj/item/clothing/suit/pirate/captain = 2,
		/obj/item/clothing/head/pirate/captain = 2,
		/obj/item/clothing/under/rank/civilian/clown/rainbow = 1,
		/obj/item/clothing/head/helmet/roman/fake = 1,
		/obj/item/clothing/head/helmet/roman/legionnaire/fake = 1,
		/obj/item/clothing/under/costume/roman = 1,
		/obj/item/clothing/shoes/roman = 1,
		/obj/item/shield/riot/roman/fake = 1,
		/obj/item/clothing/suit/chaplainsuit/clownpriest = 1,
		/obj/item/clothing/head/clownmitre = 1,
		/obj/item/skub = 1,
		/obj/item/clothing/suit/hooded/mysticrobe = 1,
		/obj/item/clothing/under/dress/wedding_dress = 1,
		/obj/item/clothing/under/suit/tuxedo = 1,
		/obj/item/clothing/head/weddingveil = 1,
		/obj/item/storage/belt/cummerbund = 1
	)
	refill_canister = /obj/item/vending_refill/autodrobe
	default_price = PAYCHECK_ASSISTANT * 0.8 //Default of 40.
	extra_price = PAYCHECK_HARD
	payment_department = ACCOUNT_SRV
	light_mask="theater-light-mask"

/obj/machinery/vending/autodrobe/canLoadItem(obj/item/I,mob/user)
	return (I.type in products)

/obj/machinery/vending/autodrobe/all_access
	desc = "A vending machine for costumes. This model appears to have no access restrictions."
	req_access = null

/obj/item/vending_refill/autodrobe
	machine_name = "AutoDrobe"
	icon_state = "refill_costume"


code:
/obj/machinery/vending/boozeomat
	name = "\improper Booze-O-Mat"
	desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one."
	icon_state = "boozeomat"
	icon_deny = "boozeomat-deny"
	products = list(
		/obj/item/reagent_containers/food/drinks/drinkingglass = 30,
		/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12,
		/obj/item/reagent_containers/food/drinks/flask = 3,
		/obj/item/reagent_containers/food/drinks/ice = 10,
		/obj/item/reagent_containers/food/drinks/bottle/orangejuice = 4,
		/obj/item/reagent_containers/food/drinks/bottle/tomatojuice = 4,
		/obj/item/reagent_containers/food/drinks/bottle/limejuice = 4,
		/obj/item/reagent_containers/food/drinks/bottle/cream = 4,
		/obj/item/reagent_containers/food/drinks/soda_cans/cola = 8,
		/obj/item/reagent_containers/food/drinks/soda_cans/tonic = 8,
		/obj/item/reagent_containers/food/drinks/soda_cans/sodawater = 15,
		/obj/item/reagent_containers/food/drinks/soda_cans/sol_dry = 8,
		/obj/item/reagent_containers/food/drinks/bottle/grenadine = 4,
		/obj/item/reagent_containers/food/drinks/bottle/menthol = 4,
		/obj/item/reagent_containers/food/drinks/bottle/ale = 6,
		/obj/item/reagent_containers/food/drinks/bottle/beer = 6,
		/obj/item/reagent_containers/food/drinks/bottle/maltliquor = 6,
		/obj/item/reagent_containers/food/drinks/bottle/gin = 5,
		/obj/item/reagent_containers/food/drinks/bottle/whiskey = 5,
		/obj/item/reagent_containers/food/drinks/bottle/tequila = 5,
		/obj/item/reagent_containers/food/drinks/bottle/vodka = 5,
		/obj/item/reagent_containers/food/drinks/bottle/vermouth = 5,
		/obj/item/reagent_containers/food/drinks/bottle/rum = 5,
		/obj/item/reagent_containers/food/drinks/bottle/wine = 5,
		/obj/item/reagent_containers/food/drinks/bottle/cognac = 5,
		/obj/item/reagent_containers/food/drinks/bottle/kahlua = 5,
		/obj/item/reagent_containers/food/drinks/bottle/hcider = 5,
		/obj/item/reagent_containers/food/drinks/bottle/absinthe = 5,
		/obj/item/reagent_containers/food/drinks/bottle/grappa = 5,
		/obj/item/reagent_containers/food/drinks/bottle/amaretto = 5,
		/obj/item/reagent_containers/food/drinks/bottle/sake = 5,
		/obj/item/reagent_containers/food/drinks/bottle/applejack = 5,
		/obj/item/reagent_containers/food/drinks/bottle = 15,
		/obj/item/reagent_containers/food/drinks/bottle/small = 15
	)
	contraband = list(
		/obj/item/reagent_containers/food/drinks/mug/tea = 12,
		/obj/item/reagent_containers/food/drinks/bottle/fernet = 5,
	)
	premium = list(
		/obj/item/reagent_containers/glass/bottle/ethanol = 4,
		/obj/item/reagent_containers/food/drinks/bottle/champagne = 5,
		/obj/item/reagent_containers/food/drinks/bottle/trappist = 5,
	)

	product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?"
	product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!"
	req_access = list(ACCESS_BAR)
	refill_canister = /obj/item/vending_refill/boozeomat
	default_price = PAYCHECK_ASSISTANT * 0.9
	extra_price = PAYCHECK_COMMAND
	payment_department = ACCOUNT_SRV
	light_mask = "boozeomat-light-mask"

/obj/machinery/vending/boozeomat/all_access
	desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one. This model appears to have no access restrictions."
	req_access = null

/obj/machinery/vending/boozeomat/syndicate_access
	req_access = list(ACCESS_SYNDICATE)
	age_restrictions = FALSE

/obj/item/vending_refill/boozeomat
	machine_name = "Booze-O-Mat"
	icon_state = "refill_booze"


code:
//This one's from bay12
/obj/machinery/vending/cart
	name = "\improper PTech"
	desc = "Cartridges for PDAs."
	product_slogans = "Carts to go!"
	icon_state = "cart"
	icon_deny = "cart-deny"
	products = list(
		/obj/item/cartridge/medical = 10,
		/obj/item/cartridge/engineering = 10,
		/obj/item/cartridge/security = 10,
		/obj/item/cartridge/janitor = 10,
		/obj/item/cartridge/signal/ordnance = 10,
		/obj/item/pda/heads = 10,
		/obj/item/cartridge/captain = 3,
		/obj/item/cartridge/quartermaster = 10
	)
	refill_canister = /obj/item/vending_refill/cart
	default_price = PAYCHECK_COMMAND
	extra_price = PAYCHECK_COMMAND * 2.5
	payment_department = ACCOUNT_SRV
	light_mask="cart-light-mask"

/obj/item/vending_refill/cart
	machine_name = "PTech"
	icon_state = "refill_smoke"


code:
/obj/machinery/vending/cigarette
	name = "\improper ShadyCigs Deluxe"
	desc = "If you want to get cancer, might as well do it in style."
	product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!"
	product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs."
	icon_state = "cigs"
	products = list(
		/obj/item/storage/fancy/cigarettes = 5,
		/obj/item/storage/fancy/cigarettes/cigpack_candy = 4,
		/obj/item/storage/fancy/cigarettes/cigpack_uplift = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_robust = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_carp = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_midori = 3,
		/obj/item/storage/box/matches = 10,
		/obj/item/lighter/greyscale = 4,
		/obj/item/storage/fancy/rollingpapers = 5
	)
	contraband = list(
		/obj/item/clothing/mask/vape = 5
	)
	premium = list(
		/obj/item/storage/fancy/cigarettes/cigpack_robustgold = 3,
		/obj/item/storage/box/gum/nicotine = 2,
		/obj/item/lighter = 3,
		/obj/item/storage/fancy/cigarettes/cigars = 1,
		/obj/item/storage/fancy/cigarettes/cigars/havana = 1,
		/obj/item/storage/fancy/cigarettes/cigars/cohiba = 1
	)

	refill_canister = /obj/item/vending_refill/cigarette
	default_price = PAYCHECK_ASSISTANT
	extra_price = PAYCHECK_HARD
	payment_department = ACCOUNT_SRV
	light_mask = "cigs-light-mask"

/obj/machinery/vending/cigarette/syndicate
	products = list(
		/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 7,
		/obj/item/storage/fancy/cigarettes/cigpack_uplift = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_candy = 2,
		/obj/item/storage/fancy/cigarettes/cigpack_robust = 2,
		/obj/item/storage/fancy/cigarettes/cigpack_carp = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_midori = 1,
		/obj/item/storage/box/matches = 10,
		/obj/item/lighter/greyscale = 4,
		/obj/item/storage/fancy/rollingpapers = 5
	)

/obj/machinery/vending/cigarette/beach //Used in the lavaland_biodome_beach.dmm ruin
	name = "\improper ShadyCigs Ultra"
	desc = "Now with extra premium products!"
	product_ads = "Probably not bad for you!;Dope will get you through times of no money better than money will get you through times of no dope!;It's good for you!"
	product_slogans = "Turn on, tune in, drop out!;Better living through chemistry!;Toke!;Don't forget to keep a smile on your lips and a song in your heart!"
	products = list(
		/obj/item/storage/fancy/cigarettes = 5,
		/obj/item/storage/fancy/cigarettes/cigpack_uplift = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_robust = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_carp = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_midori = 3,
		/obj/item/storage/fancy/cigarettes/cigpack_cannabis = 5,
		/obj/item/storage/box/matches = 10,
		/obj/item/lighter/greyscale = 4,
		/obj/item/storage/fancy/rollingpapers = 5
	)
	premium = list(
		/obj/item/storage/fancy/cigarettes/cigpack_mindbreaker = 5,
		/obj/item/clothing/mask/vape = 5,
		/obj/item/lighter = 3
	)

/obj/item/vending_refill/cigarette
	machine_name = "ShadyCigs Deluxe"
	icon_state = "refill_smoke"

/obj/machinery/vending/cigarette/pre_throw(obj/item/I)
	if(istype(I, /obj/item/lighter))
		var/obj/item/lighter/L = I
		L.set_lit(TRUE)


code:
/obj/machinery/vending/clothing
	name = "ClothesMate" //renamed to make the slogan rhyme
	desc = "A vending machine for clothing."
	icon_state = "clothes"
	icon_deny = "clothes-deny"
	product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this swag!;Why leave style up to fate? Use the ClothesMate!"
	vend_reply = "Thank you for using the ClothesMate!"
	products = list(
		/obj/item/clothing/head/beanie = 3,
		/obj/item/clothing/head/beanie/black = 3,
		/obj/item/clothing/head/beanie/red = 3,
		/obj/item/clothing/head/beanie/green = 3,
		/obj/item/clothing/head/beanie/darkblue = 3,
		/obj/item/clothing/head/beanie/purple = 3,
		/obj/item/clothing/head/beanie/yellow = 3,
		/obj/item/clothing/head/beanie/orange = 3,
		/obj/item/clothing/head/beanie/cyan = 3,
		/obj/item/clothing/head/beanie/christmas = 3,
		/obj/item/clothing/head/beanie/striped = 3,
		/obj/item/clothing/head/beanie/stripedred = 3,
		/obj/item/clothing/head/beanie/stripedblue = 3,
		/obj/item/clothing/head/beanie/stripedgreen = 3,
		/obj/item/clothing/head/beanie/rasta = 3,
		/obj/item/clothing/head/beret/black = 3,
		/obj/item/clothing/head/kippah = 3,
		/obj/item/clothing/head/taqiyahred = 3,
		/obj/item/clothing/gloves/fingerless = 2,
		/obj/item/clothing/neck/scarf/pink = 3,
		/obj/item/clothing/neck/scarf/red = 3,
		/obj/item/clothing/neck/scarf/green = 3,
		/obj/item/clothing/neck/scarf/darkblue = 3,
		/obj/item/clothing/neck/scarf/purple = 3,
		/obj/item/clothing/neck/scarf/yellow = 3,
		/obj/item/clothing/neck/scarf/orange = 3,
		/obj/item/clothing/neck/scarf/cyan = 3,
		/obj/item/clothing/neck/scarf = 3,
		/obj/item/clothing/neck/scarf/black = 3,
		/obj/item/clothing/neck/scarf/zebra = 3,
		/obj/item/clothing/neck/scarf/christmas = 3,
		/obj/item/clothing/neck/stripedredscarf = 3,
		/obj/item/clothing/neck/stripedbluescarf = 3,
		/obj/item/clothing/neck/stripedgreenscarf = 3,
		/obj/item/clothing/neck/tie/blue = 3,
		/obj/item/clothing/neck/tie/red = 3,
		/obj/item/clothing/neck/tie/black = 3,
		/obj/item/clothing/neck/tie/horrible = 3,
		/obj/item/storage/belt/fannypack = 3,
		/obj/item/storage/belt/fannypack/blue = 3,
		/obj/item/storage/belt/fannypack/red = 3,
		/obj/item/clothing/under/misc/overalls = 2,
		/obj/item/clothing/under/pants/jeans = 2,
		/obj/item/clothing/under/pants/classicjeans = 2,
		/obj/item/clothing/under/pants/camo = 2,
		/obj/item/clothing/under/pants/blackjeans = 2,
		/obj/item/clothing/under/pants/khaki = 2,
		/obj/item/clothing/under/pants/white = 2,
		/obj/item/clothing/under/pants/red = 2,
		/obj/item/clothing/under/pants/black = 2,
		/obj/item/clothing/under/pants/tan = 2,
		/obj/item/clothing/under/pants/track = 2,
		/obj/item/clothing/shoes/sneakers/black = 4,
		/obj/item/clothing/head/wig/natural  = 4,
		/obj/item/clothing/under/dress/skirt/plaid = 2,
		/obj/item/clothing/under/dress/skirt/plaid/blue = 2,
		/obj/item/clothing/under/dress/skirt/plaid/green = 2,
		/obj/item/clothing/under/dress/skirt/plaid/purple = 2,
		/obj/item/clothing/under/dress/skirt = 2,
		/obj/item/clothing/under/dress/skirt/blue = 2,
		/obj/item/clothing/under/dress/skirt/red = 2,
		/obj/item/clothing/under/dress/skirt/purple = 2,
		/obj/item/clothing/under/suit/white/skirt = 2,
		/obj/item/clothing/under/rank/captain/suit/skirt = 2,
		/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt = 2,
		/obj/item/clothing/suit/jacket = 2,
		/obj/item/clothing/suit/hooded/wintercoat/custom = 2,
		/obj/item/clothing/suit/jacket/puffer/vest = 2,
		/obj/item/clothing/suit/jacket/puffer = 2,
		/obj/item/clothing/suit/jacket/letterman = 2,
		/obj/item/clothing/suit/jacket/letterman_red = 2,
		/obj/item/clothing/glasses/regular = 2,
		/obj/item/clothing/glasses/regular/jamjar = 1,
		/obj/item/clothing/glasses/orange = 1,
		/obj/item/clothing/glasses/red = 1,
		/obj/item/clothing/under/suit/navy = 1,
		/obj/item/clothing/under/suit/black_really = 1,
		/obj/item/clothing/under/suit/burgundy = 1,
		/obj/item/clothing/under/suit/charcoal = 1,
		/obj/item/clothing/under/suit/white = 1,
		/obj/item/clothing/under/suit/sl = 1,
		/obj/item/clothing/accessory/waistcoat = 1,
		/obj/item/clothing/head/that = 1,
		/obj/item/clothing/head/fedora = 1,
		/obj/item/clothing/glasses/monocle = 1,
		/obj/item/clothing/head/sombrero = 1,
		/obj/item/clothing/suit/poncho = 1,
		/obj/item/clothing/under/costume/kilt = 1,
		/obj/item/clothing/under/dress/sundress = 1,
		/obj/item/clothing/under/dress/striped = 1,
		/obj/item/clothing/under/dress/sailor = 1,
		/obj/item/clothing/under/dress/redeveninggown = 1,
		/obj/item/clothing/under/dress/blacktango = 1,
		/obj/item/clothing/suit/ianshirt = 1,
		/obj/item/clothing/shoes/laceup = 2,
		/obj/item/clothing/shoes/sandal = 2,
		/obj/item/clothing/shoes/winterboots = 2,
		/obj/item/clothing/shoes/cowboy = 2,
		/obj/item/clothing/shoes/cowboy/white = 2,
		/obj/item/clothing/shoes/cowboy/black = 2,
		/obj/item/clothing/suit/jacket/miljacket = 1,
		/obj/item/clothing/suit/apron/purple_bartender = 2,
		/obj/item/clothing/under/rank/civilian/bartender/purple = 2,
		/obj/item/clothing/suit/toggle/suspenders/blue = 2,
		/obj/item/clothing/suit/toggle/suspenders/gray = 2,
		/obj/item/storage/backpack/henchmen = 20,
		/obj/item/clothing/under/suit/henchmen = 20,
		/obj/item/clothing/under/costume/yakuza = 20,
		/obj/item/clothing/shoes/yakuza = 20,
		/obj/item/clothing/suit/yakuza = 20,
		/obj/item/clothing/under/costume/jackbros = 20,
		/obj/item/clothing/shoes/jackbros = 20,
		/obj/item/clothing/head/jackbros = 20,
		/obj/item/clothing/under/costume/dutch = 20,
		/obj/item/clothing/head/bowler = 20,
		/obj/item/clothing/suit/dutch = 20,
		/obj/item/clothing/shoes/cowboy = 20,
		/obj/item/clothing/suit/irs = 20,
		/obj/item/clothing/under/costume/irs = 20,
		/obj/item/clothing/head/irs = 20,
		/obj/item/clothing/suit/osi = 20,
		/obj/item/clothing/under/costume/osi = 20,
		/obj/item/clothing/glasses/osi = 20,
		/obj/item/clothing/suit/tmc = 20,
		/obj/item/clothing/under/costume/tmc = 20,
		/obj/item/clothing/head/tmc = 20,
		/obj/item/clothing/suit/pg = 20,
		/obj/item/clothing/under/costume/pg = 20,
		/obj/item/clothing/head/pg = 20,
		/obj/item/clothing/suit/driscoll = 20,
		/obj/item/clothing/under/costume/driscoll = 20,
		/obj/item/clothing/mask/gas/driscoll = 20,
		/obj/item/clothing/suit/deckers = 20,
		/obj/item/clothing/under/costume/deckers = 20,
		/obj/item/clothing/head/deckers = 20,
		/obj/item/clothing/shoes/deckers = 20,
		/obj/item/clothing/suit/morningstar = 20,
		/obj/item/clothing/under/costume/morningstar = 20,
		/obj/item/clothing/head/morningstar = 20,
		/obj/item/clothing/shoes/morningstar = 20,
		/obj/item/clothing/suit/saints = 20,
		/obj/item/clothing/under/costume/saints = 20,
		/obj/item/clothing/head/saints = 20,
		/obj/item/clothing/shoes/saints = 20,
		/obj/item/clothing/suit/phantom = 20,
		/obj/item/clothing/under/costume/phantom = 20,
		/obj/item/clothing/glasses/phantom = 20,
		/obj/item/clothing/shoes/phantom = 20,
		/obj/item/clothing/suit/allies = 20,
		/obj/item/clothing/under/costume/allies = 20,
		/obj/item/clothing/head/allies = 20,
		/obj/item/clothing/suit/soviet = 20,
		/obj/item/clothing/under/costume/soviet_families = 20,
		/obj/item/clothing/head/ushanka/soviet = 20,
		/obj/item/clothing/suit/yuri = 20,
		/obj/item/clothing/under/costume/yuri = 20,
		/obj/item/clothing/head/yuri = 20,
		/obj/item/clothing/suit/sybil_slickers = 20,
		/obj/item/clothing/under/costume/sybil_slickers = 20,
		/obj/item/clothing/head/sybil_slickers = 20,
		/obj/item/clothing/shoes/sybil_slickers = 20,
		/obj/item/clothing/suit/basil_boys = 20,
		/obj/item/clothing/under/costume/basil_boys = 20,
		/obj/item/clothing/head/basil_boys = 20,
		/obj/item/clothing/shoes/basil_boys = 20
	)
	contraband = list(
		/obj/item/clothing/under/syndicate/tacticool = 1,
		/obj/item/clothing/under/syndicate/tacticool/skirt = 1,
		/obj/item/clothing/mask/balaclava = 1,
		/obj/item/clothing/head/ushanka = 1,
		/obj/item/clothing/under/costume/soviet = 1,
		/obj/item/storage/belt/fannypack/black = 2,
		/obj/item/clothing/suit/jacket/letterman_syndie = 1,
		/obj/item/clothing/under/costume/jabroni = 1,
		/obj/item/clothing/suit/vapeshirt = 1,
		/obj/item/clothing/under/costume/geisha = 1,
		/obj/item/clothing/under/rank/centcom/officer/replica = 1,
		/obj/item/clothing/under/rank/centcom/officer_skirt/replica = 1
	)
	premium = list(/obj/item/clothing/under/suit/checkered = 1,
		/obj/item/clothing/head/mailman = 1,
		/obj/item/clothing/under/misc/mailman = 1,
		/obj/item/clothing/suit/jacket/leather = 1,
		/obj/item/clothing/suit/jacket/leather/overcoat = 1,
		/obj/item/clothing/under/pants/mustangjeans = 1,
		/obj/item/clothing/neck/necklace/dope = 3,
		/obj/item/clothing/suit/jacket/letterman_nanotrasen = 1,
		/obj/item/clothing/under/costume/swagoutfit = 1,
		/obj/item/clothing/shoes/swagshoes = 1,
		/obj/item/instrument/piano_synth/headphones/spacepods = 1
	)
	refill_canister = /obj/item/vending_refill/clothing
	default_price = PAYCHECK_ASSISTANT * 0.7 //Default of
	extra_price = PAYCHECK_HARD
	payment_department = NO_FREEBIES
	light_mask = "wardrobe-light-mask"
	light_color = LIGHT_COLOR_ELECTRIC_GREEN

/obj/machinery/vending/clothing/canLoadItem(obj/item/I,mob/user)
	return (I.type in products)

/obj/item/vending_refill/clothing
	machine_name = "ClothesMate"
	icon_state = "refill_clothes"


code:
/obj/machinery/vending/coffee
	name = "\improper Solar's Best Hot Drinks"
	desc = "A vending machine which dispenses hot drinks."
	product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies"
	icon_state = "coffee"
	icon_vend = "coffee-vend"
	products = list(
		/obj/item/reagent_containers/food/drinks/coffee = 6,
		/obj/item/reagent_containers/food/drinks/mug/tea = 6,
		/obj/item/reagent_containers/food/drinks/mug/coco = 3
	)
	contraband = list(
		/obj/item/reagent_containers/food/drinks/ice = 12
	)
	refill_canister = /obj/item/vending_refill/coffee
	default_price = PAYCHECK_PRISONER
	extra_price = PAYCHECK_ASSISTANT
	payment_department = ACCOUNT_SRV
	light_mask = "coffee-light-mask"
	light_color = COLOR_DARK_MODERATE_ORANGE

/obj/item/vending_refill/coffee
	machine_name = "Solar's Best Hot Drinks"
	icon_state = "refill_joe"


code:
/obj/machinery/vending/cola
	name = "\improper Robust Softdrinks"
	desc = "A softdrink vendor provided by Robust Industries, LLC."
	icon_state = "Cola_Machine"
	product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!"
	product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space."
	products = list(
		/obj/item/reagent_containers/food/drinks/soda_cans/cola = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/starkist = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/space_up = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/pwr_game = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,
		/obj/item/reagent_containers/food/drinks/soda_cans/sol_dry = 10,
		/obj/item/reagent_containers/food/drinks/waterbottle = 10,
		/obj/item/reagent_containers/food/drinks/bottle/mushi_kombucha = 3
	)
	contraband = list(
		/obj/item/reagent_containers/food/drinks/soda_cans/thirteenloko = 6,
		/obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 6
	)
	premium = list(
		/obj/item/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1,
		/obj/item/reagent_containers/food/drinks/soda_cans/air = 1,
		/obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy = 1,
		/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1
	)
	refill_canister = /obj/item/vending_refill/cola
	default_price = PAYCHECK_ASSISTANT * 0.7
	extra_price = PAYCHECK_MEDIUM
	payment_department = ACCOUNT_SRV

/obj/item/vending_refill/cola
	machine_name = "Robust Softdrinks"
	icon_state = "refill_cola"

/obj/machinery/vending/cola/blue
	icon_state = "Cola_Machine"
	light_mask = "cola-light-mask"
	light_color = COLOR_MODERATE_BLUE

/obj/machinery/vending/cola/black
	icon_state = "cola_black"
	light_mask = "cola-light-mask"

/obj/machinery/vending/cola/red
	icon_state = "red_cola"
	name = "\improper Space Cola Vendor"
	desc = "It vends cola, in space."
	product_slogans = "Cola in space!"
	light_mask = "red_cola-light-mask"
	light_color = COLOR_DARK_RED

/obj/machinery/vending/cola/space_up
	icon_state = "space_up"
	name = "\improper Space-up! Vendor"
	desc = "Indulge in an explosion of flavor."
	product_slogans = "Space-up! Like a hull breach in your mouth."
	light_mask = "space_up-light-mask"
	light_color = COLOR_DARK_MODERATE_LIME_GREEN

/obj/machinery/vending/cola/starkist
	icon_state = "starkist"
	name = "\improper Star-kist Vendor"
	desc = "The taste of a star in liquid form."
	product_slogans = "Drink the stars! Star-kist!"
	light_mask = "starkist-light-mask"
	light_color = COLOR_LIGHT_ORANGE

/obj/machinery/vending/cola/sodie
	icon_state = "soda"
	light_mask = "soda-light-mask"
	light_color = COLOR_WHITE

/obj/machinery/vending/cola/pwr_game
	icon_state = "pwr_game"
	name = "\improper Pwr Game Vendor"
	desc = "You want it, we got it. Brought to you in partnership with Vlad's Salads."
	product_slogans = "The POWER that gamers crave! PWR GAME!"
	light_mask = "pwr_game-light-mask"
	light_color = COLOR_STRONG_VIOLET

/obj/machinery/vending/cola/shamblers
	name = "\improper Shambler's Vendor"
	desc = "~Shake me up some of that Shambler's Juice!~"
	icon_state = "shamblers_juice"
	products = list(/obj/item/reagent_containers/food/drinks/soda_cans/cola = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/starkist = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/space_up = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/pwr_game = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/sol_dry = 10,
					/obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 10)
	product_slogans = "~Shake me up some of that Shambler's Juice!~"
	product_ads = "Refreshing!;Jyrbv dv lg jfdv fw kyrk Jyrdscvi'j Alztv!;Over 1 trillion souls drank!;Thirsty? Nyp efk uizeb kyv uribevjj?;Kyv Jyrdscvi uizebj kyv ezxyk!;Drink up!;Krjkp."
	light_mask = "shamblers-light-mask"
	light_color = COLOR_MOSTLY_PURE_PINK


code:
/obj/machinery/vending/dinnerware
	name = "\improper Plasteel Chef's Dinnerware Vendor"
	desc = "A kitchen and restaurant equipment vendor."
	product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..."
	icon_state = "dinnerware"
	products = list(
		/obj/item/storage/bag/tray = 8,
		/obj/item/reagent_containers/glass/bowl = 20,
		/obj/item/kitchen/fork = 6,
		/obj/item/kitchen/spoon = 6,
		/obj/item/reagent_containers/food/drinks/drinkingglass = 8,
		/obj/item/reagent_containers/food/condiment/pack/ketchup = 5,
		/obj/item/reagent_containers/food/condiment/pack/hotsauce = 5,
		/obj/item/reagent_containers/food/condiment/pack/astrotame = 5,
		/obj/item/reagent_containers/food/condiment/saltshaker = 5,
		/obj/item/reagent_containers/food/condiment/peppermill = 5,
		/obj/item/clothing/suit/apron/chef = 2,
		/obj/item/kitchen/rollingpin = 2,
		/obj/item/knife/kitchen = 2,
		/obj/item/book/granter/crafting_recipe/cooking_sweets_101 = 2,
		/obj/item/plate = 10
	)
	contraband = list(
		/obj/item/kitchen/rollingpin = 2,
		/obj/item/knife/butcher = 2,
	)
	refill_canister = /obj/item/vending_refill/dinnerware
	default_price = PAYCHECK_ASSISTANT * 0.8
	extra_price = PAYCHECK_HARD
	payment_department = ACCOUNT_SRV
	light_mask = "dinnerware-light-mask"

/obj/item/vending_refill/dinnerware
	machine_name = "Plasteel Chef's Dinnerware Vendor"
	icon_state = "refill_smoke"


code:
//This one's from bay12
/obj/machinery/vending/engineering
	name = "\improper Robco Tool Maker"
	desc = "Everything you need for do-it-yourself station repair."
	icon_state = "engi"
	icon_deny = "engi-deny"
	req_access = list(ACCESS_ENGINE_EQUIP)
	products = list(
		/obj/item/clothing/under/rank/engineering/chief_engineer = 4,
		/obj/item/clothing/under/rank/engineering/engineer = 4,
		/obj/item/clothing/shoes/sneakers/orange = 4,
		/obj/item/clothing/head/hardhat = 4,
		/obj/item/storage/belt/utility = 4,
		/obj/item/clothing/glasses/meson/engine = 4,
		/obj/item/clothing/gloves/color/yellow = 4,
		/obj/item/screwdriver = 12,
		/obj/item/crowbar = 12,
		/obj/item/wirecutters = 12,
		/obj/item/multitool = 12,
		/obj/item/wrench = 12,
		/obj/item/t_scanner = 12,
		/obj/item/stock_parts/cell = 8,
		/obj/item/weldingtool = 8,
		/obj/item/clothing/head/welding = 8,
		/obj/item/light/tube = 10,
		/obj/item/clothing/suit/fire = 4,
		/obj/item/stock_parts/scanning_module = 5,
		/obj/item/stock_parts/micro_laser = 5,
		/obj/item/stock_parts/matter_bin = 5,
		/obj/item/stock_parts/manipulator = 5
		)
	refill_canister = /obj/item/vending_refill/engineering
	default_price = PAYCHECK_EASY
	extra_price = PAYCHECK_COMMAND * 1.5
	payment_department = ACCOUNT_ENG
	light_mask = "engi-light-mask"

/obj/item/vending_refill/engineering
	machine_name = "Robco Tool Maker"
	icon_state = "refill_engi"