<commit_before>// TURBINE v2 AKA rev4407 Engine reborn!

// How to use it? - Mappers
//
// This is a very good power generating mechanism. All you need is a blast furnace with soaring flames and output.
// Not everything is included yet so the turbine can run out of fuel quiet quickly. The best thing about the turbine is that even
// though something is on fire that passes through it, it won't be on fire as it passes out of it. So the exhaust fumes can still
// containt unreacted fuel - plasma and oxygen that needs to be filtered out and re-routed back. This of course requires smart piping
// For a computer to work with the turbine the compressor requires a comp_id matching with the turbine computer's id. This will be
// subjected to a change in the near future mind you. Right now this method of generating power is a good backup but don't expect it
// become a main power source unless some work is done. Have fun. At 50k RPM it generates 60k power. So more than one turbine is needed!
//
// - Numbers
//
// Example setup  S - sparker
//  B - Blast doors into space for venting
// *BBB****BBB*  C - Compressor
// S    CT    *  T - Turbine
// * ^ *  * V *  D - Doors with firedoor
// **|***D**|**      ^ - Fuel feed (Not vent, but a gas outlet)
//   |      |        V - Suction vent (Like the ones in atmos
//


/obj/machinery/power/compressor
	name = "compressor"
	desc = "The compressor stage of a gas turbine generator."
	icon = 'icons/obj/atmospherics/pipes/simple.dmi'
	icon_state = "compressor"
	density = TRUE
	resistance_flags = FIRE_PROOF
	CanAtmosPass = ATMOS_PASS_DENSITY
	circuit = /obj/item/circuitboard/machine/power_compressor
	var/obj/machinery/power/turbine/turbine
	var/datum/gas_mixture/gas_contained
	var/turf/inturf
	var/starter = 0
	var/rpm = 0
	var/rpmtarget = 0
	var/capacity = 1e6
	var/comp_id = 0
	var/efficiency

/obj/machinery/power/compressor/Destroy()
	if (turbine && turbine.compressor == src)
		turbine.compressor = null
	turbine = null
	return ..()

/obj/machinery/power/turbine
	name = "gas turbine generator"
	desc = "A gas turbine used for backup power generation."
	icon = 'icons/obj/atmospherics/pipes/simple.dmi'
	icon_state = "turbine"
	density = TRUE
	resistance_flags = FIRE_PROOF
	CanAtmosPass = ATMOS_PASS_DENSITY
	circuit = /obj/item/circuitboard/machine/power_turbine
	var/opened = 0
	var/obj/machinery/power/compressor/compressor
	var/turf/outturf
	var/lastgen
	var/productivity = 1

/obj/machinery/power/turbine/Destroy()
	if (compressor && compressor.turbine == src)
		compressor.turbine = null
	compressor = null
	return ..()

// the inlet stage of the gas turbine electricity generator

/obj/machinery/power/compressor/Initialize()
	. = ..()
	// The inlet of the compressor is the direction it faces
	gas_contained = new
	inturf = get_step(src, dir)
	locate_machinery()
	if(!turbine)
		obj_break()

#define COMPFRICTION 5e5

/obj/machinery/power/compressor/locate_machinery()
	if(turbine)
		return
	turbine = locate() in get_step(src, get_dir(inturf, src))
	if(turbine)
		turbine.locate_machinery()

/obj/machinery/power/compressor/RefreshParts()
	var/E = 0
	for(var/obj/item/stock_parts/manipulator/M in component_parts)
		E += M.rating
	efficiency = E / 6

/obj/machinery/power/compressor/examine(mob/user)
	. = ..()
	if(in_range(user, src) || isobserver(user))
		. += span_notice("The status display reads: Efficiency at <b>[efficiency*100]%</b>.")

/obj/machinery/power/compressor/attackby(obj/item/I, mob/user, params)
	if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I))
		return

	if(default_change_direction_wrench(user, I))
		turbine = null
		inturf = get_step(src, dir)
		locate_machinery()
		if(turbine)
			to_chat(user, span_notice("Turbine connected."))
			set_machine_stat(machine_stat & ~BROKEN)
		else
			to_chat(user, span_alert("Turbine not connected."))
			obj_break()
		return

	default_deconstruction_crowbar(I)

/obj/machinery/power/compressor/process()
	if(!starter)
		return
	if(!turbine || (turbine.machine_stat & BROKEN))
		starter = FALSE
	if(machine_stat & BROKEN || panel_open)
		starter = FALSE
		return
	cut_overlays()

	rpm = 0.9* rpm + 0.1 * rpmtarget
	var/datum/gas_mixture/environment = inturf.return_air()

	// It's a simplified version taking only 1/10 of the moles from the turf nearby. It should be later changed into a better version

	var/transfer_moles = environment.total_moles()/10
	var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles)
	gas_contained.merge(removed)

// RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy

	rpm = min(rpm, (COMPFRICTION*efficiency)/2)
	rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION*efficiency))

	if(starter && !(machine_stat & NOPOWER))
		use_power(2800)<commit_msg>Fix turbine exploit (#59934)<commit_after>// TURBINE v2 AKA rev4407 Engine reborn!

// How to use it? - Mappers
//
// This is a very good power generating mechanism. All you need is a blast furnace with soaring flames and output.
// Not everything is included yet so the turbine can run out of fuel quiet quickly. The best thing about the turbine is that even
// though something is on fire that passes through it, it won't be on fire as it passes out of it. So the exhaust fumes can still
// containt unreacted fuel - plasma and oxygen that needs to be filtered out and re-routed back. This of course requires smart piping
// For a computer to work with the turbine the compressor requires a comp_id matching with the turbine computer's id. This will be
// subjected to a change in the near future mind you. Right now this method of generating power is a good backup but don't expect it
// become a main power source unless some work is done. Have fun. At 50k RPM it generates 60k power. So more than one turbine is needed!
//
// - Numbers
//
// Example setup  S - sparker
//  B - Blast doors into space for venting
// *BBB****BBB*  C - Compressor
// S    CT    *  T - Turbine
// * ^ *  * V *  D - Doors with firedoor
// **|***D**|**      ^ - Fuel feed (Not vent, but a gas outlet)
//   |      |        V - Suction vent (Like the ones in atmos
//


/obj/machinery/power/compressor
	name = "compressor"
	desc = "The compressor stage of a gas turbine generator."
	icon = 'icons/obj/atmospherics/pipes/simple.dmi'
	icon_state = "compressor"
	density = TRUE
	resistance_flags = FIRE_PROOF
	CanAtmosPass = ATMOS_PASS_DENSITY
	circuit = /obj/item/circuitboard/machine/power_compressor
	var/obj/machinery/power/turbine/turbine
	var/datum/gas_mixture/gas_contained
	var/turf/inturf
	var/starter = 0
	var/rpm = 0
	var/rpmtarget = 0
	var/capacity = 1e6
	var/comp_id = 0
	var/efficiency

/obj/machinery/power/compressor/Destroy()
	if (turbine && turbine.compressor == src)
		turbine.compressor = null
	turbine = null
	return ..()

/obj/machinery/power/turbine
	name = "gas turbine generator"
	desc = "A gas turbine used for backup power generation."
	icon = 'icons/obj/atmospherics/pipes/simple.dmi'
	icon_state = "turbine"
	density = TRUE
	resistance_flags = FIRE_PROOF
	CanAtmosPass = ATMOS_PASS_DENSITY
	circuit = /obj/item/circuitboard/machine/power_turbine
	var/opened = 0
	var/obj/machinery/power/compressor/compressor
	var/turf/outturf
	var/lastgen
	var/productivity = 1

/obj/machinery/power/turbine/Destroy()
	if (compressor && compressor.turbine == src)
		compressor.turbine = null
	compressor = null
	return ..()

// the inlet stage of the gas turbine electricity generator

/obj/machinery/power/compressor/Initialize()
	. = ..()
	// The inlet of the compressor is the direction it faces
	gas_contained = new
	inturf = get_step(src, dir)
	locate_machinery()
	if(!turbine)
		obj_break()

#define COMPFRICTION 5e5

/obj/machinery/power/compressor/locate_machinery()
	if(turbine)
		return
	turbine = locate() in get_step(src, get_dir(inturf, src))
	if(turbine)
		turbine.locate_machinery()

/obj/machinery/power/compressor/RefreshParts()
	var/E = 0
	for(var/obj/item/stock_parts/manipulator/M in component_parts)
		E += M.rating
	efficiency = E / 6

/obj/machinery/power/compressor/examine(mob/user)
	. = ..()
	if(in_range(user, src) || isobserver(user))
		. += span_notice("The status display reads: Efficiency at <b>[efficiency*100]%</b>.")

/obj/machinery/power/compressor/attackby(obj/item/I, mob/user, params)
	if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I))
		return

	if(default_change_direction_wrench(user, I))
		turbine = null
		inturf = get_step(src, dir)
		locate_machinery()
		if(turbine)
			to_chat(user, span_notice("Turbine connected."))
			set_machine_stat(machine_stat & ~BROKEN)
		else
			to_chat(user, span_alert("Turbine not connected."))
			obj_break()
		return

	default_deconstruction_crowbar(I)

/obj/machinery/power/compressor/process()
	if(!starter)
		return
	if(!turbine || (turbine.machine_stat & BROKEN))
		starter = FALSE
	if(machine_stat & BROKEN || panel_open)
		starter = FALSE
		return
	cut_overlays()

	if(istype(inturf, /turf/open))
		rpm = 0.9 * rpm + 0.1 * rpmtarget
		var/datum/gas_mixture/environment = inturf.return_air()

		// It's a simplified version taking only 1/10 of the moles from the turf nearby. It should be later changed into a better version

		var/transfer_moles = environment.total_moles()/10
		var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles)
		gas_contained.merge(removed)
	else
		rpm = 0.9 * rpm // rpmtarget is basically 0, the intake is completely blocked with no airflow

// RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy

	rpm = min(rpm, (COMPFRICTION*efficiency)/2)
	rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION*efficiency))

	if(starter && !(machine_stat & NOPOWER))
		use_power(2800)
{'fraction_non_alphanumeric': 0.10605751580664899, 'fraction_numerical': 0.008770140730165205, 'mean_word_length': 3.8815331010452963, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '6692527', 'n_tokens_mistral': 3641, 'n_tokens_neox': 3363, 'n_words': 984}