<commit_before>var/list/uplink_items = list()

/proc/get_uplink_items()
	// If not already initialized..
	if(!uplink_items.len)
		// Fill in the list	and order it like this:
		// A keyed list, acting as categories, which are lists to the datum.
		var/list/last = list()
		for(var/item in typesof(/datum/uplink_item))

			var/datum/uplink_item/I = new item()
			if(!I.item)
				continue
			if(I.gamemodes.len && ticker && !(ticker.mode.type in I.gamemodes))
				continue
			if(I.excludefrom.len && ticker && (ticker.mode.type in I.excludefrom))
				continue
			if(I.last)
				last += I
				continue

			if(!uplink_items[I.category])
				uplink_items[I.category] = list()

			uplink_items[I.category] += I

		for(var/datum/uplink_item/I in last)

			if(!uplink_items[I.category])
				uplink_items[I.category] = list()

			uplink_items[I.category] += I

	return uplink_items

// You can change the order of the list by putting datums before/after one another OR
// you can use the last variable to make sure it appears last, well have the category appear last.

/datum/uplink_item
	var/name = "item name"
	var/category = "item category"
	var/desc = "item description"
	var/item = null
	var/cost = 0
	var/last = 0 // Appear last
	var/list/gamemodes = list() // Empty list means it is in all the gamemodes. Otherwise place the gamemode name here.
	var/list/excludefrom = list() //Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something.
	var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it)
	var/list/jobs = list() // For job-specific traitor items. Leave empty for all jobs to be allowed to buy it.
	var/list/jobs_exclude = list() //Not sure why would you want to exclude uplink items from some jobs, but okay.

/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U)
	if(item)
		U.uses -= max(cost, 0)
		U.used_TC += cost
		feedback_add_details("traitor_uplink_items_bought", "[item]")
		return new item(loc)

/datum/uplink_item/proc/buy(var/obj/item/device/uplink/U, var/mob/user)

	..()
	if(!istype(U))
		return 0

	if (!user || user.stat || user.restrained())
		return 0

	// If the uplink's holder is in the user's contents
	if ((U.loc in user.contents || (in_range(U.loc, user) && istype(U.loc.loc, /turf))))
		user.set_machine(U)
		if(cost > U.uses)
			return 0

		var/obj/I = spawn_item(get_turf(user), U)

		if(istype(I, /obj/item))
			if(ishuman(user))
				var/mob/living/carbon/human/A = user
				A.put_in_any_hand_if_possible(I)

			if(istype(I,/obj/item/weapon/storage/box/) && I.contents.len>0)
				for(var/atom/o in I)
					U.purchase_log += "<BIG>\icon[o]</BIG>"
			else
				U.purchase_log += "<BIG>\icon[I]</BIG>"

		U.interact(user)
		return 1
	return 0

/*
//
//	UPLINK ITEMS
//
*/

// JOB-SPECIFIC ITEMS

/datum/uplink_item/job_specific //No job-specific support for surplus yet.
	category = "Job-specific Contraband"
	surplus = 0

//ENGINEER DIVISION

/datum/uplink_item/job_specific/rodgun
	name = "<NAME>"
	desc = "Based on the staple gun design, this baby can be loaded with 3 rods that you can shoot for them to embed into people." //This thing may be super OP
	item = /obj/item/weapon/gun/rodgun
	cost = 10 //Costly, but for a good reason
	jobs = list("Station Engineer", "Chief Engineer", "Atmospheric Technician")

//CHEMIST
/datum/uplink_item/job_specific/assX
	name = "<NAME>"
	desc = "A hilarious pill that will force your target to superfart while dealing lots of damage to their stomach. It can be surprisingly effective."
	item = /obj/item/weapon/reagent_containers/pill/assX
	cost = 4
	jobs = list("Chemist")

/datum/uplink_item/job_specific/chemsprayer //This can only end well
	name = "Chemical Sprayer"
	desc = "A powerful industrial spraygun that holds 600 units of any liquid, and can cover area faster than a standard spray bottle."
	item = /obj/item/weapon/reagent_containers/spray/chemsprayer
	cost = 18 //No no-slips thanks
	jobs = list("Chemist")

//LIBRARIAN
/datum/uplink_item/job_specific/soulstone
	name = "Soulstone"
	desc = "This stone will be able to capture your victim's soul and bind them to your will."
	item = /obj/item/device/soulstone
	cost = 5 //nerfed the cost on Chronitonity's request
	jobs = list("Librarian") //Switched soulstones to librarian, gave chaplain skelestones
//TODO: Add flash disguised as camera

//CHAPLAIN
/datum/uplink_item/job_specific/skelestone
	name = "Skelestone"
	desc = "Make a skeleton minion! Has one use."
	item = /obj/item/device/necromantic_stone/oneuse<commit_msg>this is actually just a bad idea<commit_after>var/list/uplink_items = list()

/proc/get_uplink_items()
	// If not already initialized..
	if(!uplink_items.len)
		// Fill in the list	and order it like this:
		// A keyed list, acting as categories, which are lists to the datum.
		var/list/last = list()
		for(var/item in typesof(/datum/uplink_item))

			var/datum/uplink_item/I = new item()
			if(!I.item)
				continue
			if(I.gamemodes.len && ticker && !(ticker.mode.type in I.gamemodes))
				continue
			if(I.excludefrom.len && ticker && (ticker.mode.type in I.excludefrom))
				continue
			if(I.last)
				last += I
				continue

			if(!uplink_items[I.category])
				uplink_items[I.category] = list()

			uplink_items[I.category] += I

		for(var/datum/uplink_item/I in last)

			if(!uplink_items[I.category])
				uplink_items[I.category] = list()

			uplink_items[I.category] += I

	return uplink_items

// You can change the order of the list by putting datums before/after one another OR
// you can use the last variable to make sure it appears last, well have the category appear last.

/datum/uplink_item
	var/name = "item name"
	var/category = "item category"
	var/desc = "item description"
	var/item = null
	var/cost = 0
	var/last = 0 // Appear last
	var/list/gamemodes = list() // Empty list means it is in all the gamemodes. Otherwise place the gamemode name here.
	var/list/excludefrom = list() //Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something.
	var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it)
	var/list/jobs = list() // For job-specific traitor items. Leave empty for all jobs to be allowed to buy it.
	var/list/jobs_exclude = list() //Not sure why would you want to exclude uplink items from some jobs, but okay.

/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U)
	if(item)
		U.uses -= max(cost, 0)
		U.used_TC += cost
		feedback_add_details("traitor_uplink_items_bought", "[item]")
		return new item(loc)

/datum/uplink_item/proc/buy(var/obj/item/device/uplink/U, var/mob/user)

	..()
	if(!istype(U))
		return 0

	if (!user || user.stat || user.restrained())
		return 0

	// If the uplink's holder is in the user's contents
	if ((U.loc in user.contents || (in_range(U.loc, user) && istype(U.loc.loc, /turf))))
		user.set_machine(U)
		if(cost > U.uses)
			return 0

		var/obj/I = spawn_item(get_turf(user), U)

		if(istype(I, /obj/item))
			if(ishuman(user))
				var/mob/living/carbon/human/A = user
				A.put_in_any_hand_if_possible(I)

			if(istype(I,/obj/item/weapon/storage/box/) && I.contents.len>0)
				for(var/atom/o in I)
					U.purchase_log += "<BIG>\icon[o]</BIG>"
			else
				U.purchase_log += "<BIG>\icon[I]</BIG>"

		U.interact(user)
		return 1
	return 0

/*
//
//	UPLINK ITEMS
//
*/

// JOB-SPECIFIC ITEMS

/datum/uplink_item/job_specific //No job-specific support for surplus yet.
	category = "Job-specific Contraband"
	surplus = 0

//ENGINEER DIVISION

/datum/uplink_item/job_specific/rodgun
	name = "<NAME>"
	desc = "Based on the staple gun design, this baby can be loaded with 3 rods that you can shoot for them to embed into people." //This thing may be super OP
	item = /obj/item/weapon/gun/rodgun
	cost = 10 //Costly, but for a good reason
	jobs = list("Station Engineer", "Chief Engineer", "Atmospheric Technician")

//CHEMIST
/datum/uplink_item/job_specific/assX
	name = "<NAME>"
	desc = "A hilarious pill that will force your target to superfart while dealing lots of damage to their stomach. It can be surprisingly effective."
	item = /obj/item/weapon/reagent_containers/pill/assX
	cost = 4
	jobs = list("Chemist")

//LIBRARIAN
/datum/uplink_item/job_specific/soulstone
	name = "Soulstone"
	desc = "This stone will be able to capture your victim's soul and bind them to your will."
	item = /obj/item/device/soulstone
	cost = 5 //nerfed the cost on Chronitonity's request
	jobs = list("Librarian") //Switched soulstones to librarian, gave chaplain skelestones
//TODO: Add flash disguised as camera

//CHAPLAIN
/datum/uplink_item/job_specific/skelestone
	name = "Skelestone"
	desc = "Make a skeleton minion! Has one use."
	item = /obj/item/device/necromantic_stone/oneuse
{'fraction_non_alphanumeric': 0.12081138630505435, 'fraction_numerical': 0.00459486719713101, 'mean_word_length': 3.5484199796126403, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3070398', 'n_tokens_mistral': 3514, 'n_tokens_neox': 3182, 'n_words': 951}