diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index 2223f2f9f98..8e63131cdb4 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -1,45 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
-
-/* new portable generator - work in progress
-
-/obj/machinery/power/port_gen
- name = "portable generator"
- desc = "A portable generator used for emergency backup power."
- icon = 'generator.dmi'
- icon_state = "off"
- density = 1
- anchored = 0
- directwired = 0
- var/t_status = 0
- var/t_per = 5000
- var/filter = 1
- var/tank = null
- var/turf/inturf
- var/starter = 0
- var/rpm = 0
- var/rpmtarget = 0
- var/capacity = 1e6
- var/turf/outturf
- var/lastgen
-
-
-/obj/machinery/power/port_gen/process()
-ideally we're looking to generate 5000
-
-/obj/machinery/power/port_gen/attackby(obj/item/weapon/W, mob/user)
-tank [un]loading stuff
-
-/obj/machinery/power/port_gen/attack_hand(mob/user)
-turn on/off
-
-/obj/machinery/power/port_gen/examine(mob/user)
-display round(lastgen) and phorontank amount
-
-*/
-
-//Previous code been here forever, adding new framework for portable generators
-
-
//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power).
/obj/machinery/power/port_gen
name = "Placeholder Generator" //seriously, don't use this. It can't be anchored without VV magic.
@@ -56,6 +14,9 @@ display round(lastgen) and phorontank amount
var/recent_fault = 0
var/power_output = 1
+/obj/machinery/power/port_gen/proc/IsBroken()
+ return (crit_fail || (stat & BROKEN|EMPED))
+
/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check.
return 1
@@ -69,11 +30,10 @@ display round(lastgen) and phorontank amount
return
/obj/machinery/power/port_gen/process()
- if(active && HasFuel() && !crit_fail && anchored && powernet)
+ if(active && HasFuel() && !IsBroken() && anchored && powernet)
add_avail(power_gen * power_output)
UseFuel()
src.updateDialog()
-
else
active = 0
icon_state = initial(icon_state)
@@ -96,20 +56,57 @@ display round(lastgen) and phorontank amount
else
usr << "\blue The generator is off."
+/obj/machinery/power/port_gen/emp_act(severity)
+ var/duration = 6000 //ten minutes
+ switch(severity)
+ if(1)
+ stat &= BROKEN
+ if(prob(75)) explode()
+ if(2)
+ if(prob(25)) stat &= BROKEN
+ if(prob(10)) explode()
+ if(3)
+ if(prob(10)) stat &= BROKEN
+ duration = 300
+
+ stat |= EMPED
+ if(duration)
+ spawn(duration)
+ stat &= ~EMPED
+
+/obj/machinery/power/port_gen/proc/explode()
+ explosion(src.loc, -1, 3, 5, -1)
+ del(src)
+
+#define TEMPERATURE_DIVISOR 40
+#define TEMPERATURE_CHANGE_MAX 20
+
//A power generator that runs on solid plasma sheets.
/obj/machinery/power/port_gen/pacman
- name = "P.A.C.M.A.N.-type Portable Generator"
- var/sheets = 0
- var/max_sheets = 100
- var/sheet_name = ""
- var/sheet_path = /obj/item/stack/sheet/mineral/phoron
- var/board_path = "/obj/item/weapon/circuitboard/pacman"
- var/sheet_left = 0 // How much is left of the sheet
- var/heat = 0
+ name = "\improper P.A.C.M.A.N.-type Portable Generator"
+ desc = "A power generator that runs on solid plasma sheets. Rated for 80 kW max safe output."
- //produces up to 80 kW and lasts for 20 minutes with 50 sheets
- var/time_per_sheet = 96
- power_gen = 20000
+ var/sheet_name = "solid plasma sheet"
+ var/sheet_path = /obj/item/stack/sheet/mineral/phoron
+ var/board_path = "/obj/item/weapon/circuitboard/pacman"
+
+ /*
+ These values were chosen so that the generator can run safely up to 80 kW
+ A full 50 phoron sheet stack should last 20 minutes at power_output = 4
+ temperature_gain and max_temperature are set so that the max safe power level is 4.
+ Setting to 5 or higher can only be done temporarily before the generator overheats.
+ */
+ power_gen = 20000 //Watts output per power_output level
+ var/max_power_output = 5 //The maximum power setting without emagging.
+ var/time_per_sheet = 96 //fuel efficiency - how long 1 sheet lasts at power level 1
+ var/max_sheets = 100 //max capacity of the hopper
+ var/max_temperature = 300 //max temperature before overheating increases
+ var/temperature_gain = 50 //how much the temperature increases per power output level, in degrees per level
+
+ var/sheets = 0 //How many sheets of material are loaded in the generator
+ var/sheet_left = 0 //How much is left of the current sheet
+ var/temperature = 0 //The current temperature
+ var/overheating = 0 //if this gets high enough the generator explodes
/obj/machinery/power/port_gen/pacman/initialize()
..()
@@ -135,76 +132,127 @@ display round(lastgen) and phorontank amount
/obj/machinery/power/port_gen/pacman/RefreshParts()
var/temp_rating = 0
- var/temp_reliability = 0
for(var/obj/item/weapon/stock_parts/SP in component_parts)
if(istype(SP, /obj/item/weapon/stock_parts/matter_bin))
max_sheets = SP.rating * SP.rating * 50
else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor))
temp_rating += SP.rating
+
+ var/temp_reliability = 0
+ var/part_count = 0
for(var/obj/item/weapon/CP in component_parts)
temp_reliability += CP.reliability
- reliability = min(round(temp_reliability / 4), 100)
+ part_count++
+
+ reliability = min(round(temp_reliability / part_count), 100)
power_gen = round(initial(power_gen) * (max(2, temp_rating) / 2))
/obj/machinery/power/port_gen/pacman/examine(mob/user)
..(user)
- user << "\blue The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle."
- if(crit_fail) user << "\red The generator seems to have broken down."
+ user << "\The [src] appears to be producing [power_gen*power_output] W."
+ user << "There are [sheets] [sheet_name]\s left in the hopper."
+ if(IsBroken()) user << "\The [src] seems to have broken down."
+ if(overheating) user << "\The [src] is overheating!"
/obj/machinery/power/port_gen/pacman/HasFuel()
- if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left)
+ var/needed_sheets = power_output / time_per_sheet
+ if(sheets >= needed_sheets - sheet_left)
return 1
return 0
+//Removes one stack's worth of material from the generator.
/obj/machinery/power/port_gen/pacman/DropFuel()
if(sheets)
- var/fail_safe = 0
- while(sheets > 0 && fail_safe < 100)
- fail_safe += 1
- var/obj/item/stack/sheet/S = new sheet_path(loc)
- var/amount = min(sheets, S.max_amount)
- S.amount = amount
- sheets -= amount
+ var/obj/item/stack/sheet/S = new sheet_path(loc)
+ var/amount = min(sheets, S.max_amount)
+ S.amount = amount
+ sheets -= amount
/obj/machinery/power/port_gen/pacman/UseFuel()
- var/needed_sheets = 1 / (time_per_sheet / power_output)
- var/temp = min(needed_sheets, sheet_left)
- needed_sheets -= temp
- sheet_left -= temp
- sheets -= round(needed_sheets)
- needed_sheets -= round(needed_sheets)
- if (sheet_left <= 0 && sheets > 0)
- sheet_left = 1 - needed_sheets
+ //break down sometimes
+ if (reliability < 100)
+ if (prob(1) && prob(1) && prob(100 - reliability))
+ stat |= BROKEN
+ crit_fail = 1
+ if (prob(100 - reliability))
+ explode()
+
+ //how much material are we using this iteration?
+ var/needed_sheets = power_output / time_per_sheet
+
+ //HasFuel() should guarantee us that there is enough fuel left, so no need to check that
+ //the only thing we need to worry about is if we are going to rollover to the next sheet
+ if (needed_sheets > sheet_left)
sheets--
-
- var/lower_limit = 56 + power_output * 10
- var/upper_limit = 76 + power_output * 10
- var/bias = 0
- if (power_output > 4)
- upper_limit = 400
- bias = power_output * 3
- if (heat < lower_limit)
- heat += 3
+ sheet_left = (1 + sheet_left) - needed_sheets
else
- heat += rand(-7 + bias, 7 + bias)
- if (heat < lower_limit)
- heat = lower_limit
- if (heat > upper_limit)
- heat = upper_limit
+ sheet_left -= needed_sheets
- if (heat > 300)
+ //calculate the "target" temperature range
+ //This should probably depend on the external temperature somehow, but whatever.
+ var/lower_limit = 56 + power_output * temperature_gain
+ var/upper_limit = 76 + power_output * temperature_gain
+
+ /*
+ Hot or cold environments can affect the equilibrium temperature
+ The lower the pressure the less effect it has. I guess it cools using a radiator or something when in vacuum.
+ Gives traitors more opportunities to sabotage the generator or allows enterprising engineers to build additional
+ cooling in order to get more power out.
+ */
+ var/datum/gas_mixture/environment = loc.return_air()
+ if (environment)
+ var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
+ var/ambient = environment.temperature - T20C
+ lower_limit += ambient*ratio
+ upper_limit += ambient*ratio
+
+ var/average = (upper_limit + lower_limit)/2
+
+ //calculate the temperature increase
+ var/bias = 0
+ if (temperature < lower_limit)
+ bias = min(round((average - temperature)/TEMPERATURE_DIVISOR, 1), TEMPERATURE_CHANGE_MAX)
+ else if (temperature > upper_limit)
+ bias = max(round((temperature - average)/TEMPERATURE_DIVISOR, 1), -TEMPERATURE_CHANGE_MAX)
+
+ temperature += rand(-7 + bias, 7 + bias)
+
+ if (temperature > max_temperature)
overheat()
- del(src)
- return
+ else if (overheating > 0)
+ overheating--
/obj/machinery/power/port_gen/pacman/handleInactive()
-
- if (heat > 0)
- heat = max(heat - 2, 0)
+ var/cooling_temperature = 20
+ var/datum/gas_mixture/environment = loc.return_air()
+ if (environment)
+ var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
+ var/ambient = environment.temperature - T20C
+ cooling_temperature += ambient*ratio
+
+ if (temperature > cooling_temperature)
+ var/temp_loss = (temperature - cooling_temperature)/TEMPERATURE_DIVISOR
+ temp_loss = between(2, round(temp_loss, 1), TEMPERATURE_CHANGE_MAX)
+ temperature = max(temperature - temp_loss, cooling_temperature)
src.updateDialog()
/obj/machinery/power/port_gen/pacman/proc/overheat()
- explosion(src.loc, 2, 5, 2, -1)
+ overheating++
+ if (overheating > 60)
+ explode()
+
+/obj/machinery/power/port_gen/pacman/explode()
+ //Vapourize all the phoron
+ //When ground up in a grinder, 1 sheet produces 20 u of phoron -- Chemistry-Machinery.dm
+ //1 mol = 10 u? I dunno. 1 mol of carbon is definitely bigger than a pill
+ var/phoron = (sheets+sheet_left)*20
+ var/datum/gas_mixture/environment = loc.return_air()
+ if (environment)
+ environment.adjust_gas_temp("phoron", phoron/10, temperature + T0C)
+
+ sheets = 0
+ sheet_left = 0
+ ..()
/obj/machinery/power/port_gen/pacman/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(istype(O, sheet_path))
@@ -213,16 +261,16 @@ display round(lastgen) and phorontank amount
if(amount < 1)
user << "\blue The [src.name] is full!"
return
- user << "\blue You add [amount] sheets to the [src.name]."
+ user << "\blue You add [amount] [addstack.singular_name]\s to the [src.name]."
sheets += amount
addstack.use(amount)
updateUsrDialog()
return
else if (istype(O, /obj/item/weapon/card/emag))
emagged = 1
- emp_act(1)
+ if (active && prob(25))
+ explode() //if they're foolish enough to emag while it's running
else if(!active)
-
if(istype(O, /obj/item/weapon/wrench))
if(!anchored)
@@ -245,18 +293,9 @@ display round(lastgen) and phorontank amount
else if(istype(O, /obj/item/weapon/crowbar) && open)
var/obj/machinery/constructable_frame/machine_frame/new_frame = new /obj/machinery/constructable_frame/machine_frame(src.loc)
for(var/obj/item/I in component_parts)
- if(I.reliability < 100)
- I.crit_fail = 1
I.loc = src.loc
while ( sheets > 0 )
- var/obj/item/stack/sheet/G = new sheet_path(src.loc)
-
- if ( sheets > 50 )
- G.amount = 50
- else
- G.amount = sheets
-
- sheets -= G.amount
+ DropFuel()
new_frame.state = 2
new_frame.icon_state = "box_1"
@@ -266,7 +305,6 @@ display round(lastgen) and phorontank amount
..()
if (!anchored)
return
-
interact(user)
/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob)
@@ -289,9 +327,11 @@ display round(lastgen) and phorontank amount
dat += text("[capitalize(sheet_name)]: [sheets] - Eject
")
var/stack_percent = round(sheet_left * 100, 1)
dat += text("Current stack: [stack_percent]%
")
- dat += text("Power output: - [power_gen * power_output] +
")
+ dat += text("Power output: - [power_gen * power_output] Watts+
")
dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]
")
- dat += text("Heat: [heat]
")
+
+ var/tempstr = "Temperature: [temperature]°C
"
+ dat += (overheating)? "[tempstr]" : tempstr
dat += "
Close"
user << browse("[dat]", "window=port_gen")
onclose(user, "port_gen")
@@ -303,7 +343,7 @@ display round(lastgen) and phorontank amount
src.add_fingerprint(usr)
if(href_list["action"])
if(href_list["action"] == "enable")
- if(!active && HasFuel() && !crit_fail)
+ if(!active && HasFuel() && !IsBroken())
active = 1
icon_state = "portgen1"
src.updateUsrDialog()
@@ -321,7 +361,7 @@ display round(lastgen) and phorontank amount
power_output--
src.updateUsrDialog()
if (href_list["action"] == "higher_power")
- if (power_output < 4 || emagged)
+ if (power_output < max_power_output || (emagged && power_output < round(max_power_output*2.5)))
power_output++
src.updateUsrDialog()
if (href_list["action"] == "close")
@@ -330,26 +370,46 @@ display round(lastgen) and phorontank amount
/obj/machinery/power/port_gen/pacman/super
name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator"
+ desc = "A power generator that utilizes uranium sheets as fuel. Can run for much longer than the standard PACMAN type generators. Rated for 80 kW max safe output."
icon_state = "portgen1"
sheet_path = /obj/item/stack/sheet/mineral/uranium
+ time_per_sheet = 576 //same power output, but a 50 sheet stack will last 2 hours at max safe power
board_path = "/obj/item/weapon/circuitboard/pacman/super"
+
+/obj/machinery/power/port_gen/pacman/super/UseFuel()
+ //produces a tiny amount of radiation when in use
+ if (prob(2*power_output))
+ for (var/mob/living/L in range(src, 5))
+ L.apply_effect(1, IRRADIATE) //should amount to ~5 rads per minute at max safe power
+ ..()
+
+/obj/machinery/power/port_gen/pacman/super/explode()
+ //a nice burst of radiation
+ var/rads = 50 + (sheets + sheet_left)*1.5
+ for (var/mob/living/L in range(src, 10))
+ //should really fall with the square of the distance, but that makes the rads value drop too fast
+ //I dunno, maybe physics works different when you live in 2D -- SM radiation also works like this, apparently
+ L.apply_effect(max(20, round(rads/get_dist(L,src))), IRRADIATE)
- //produces 80 kW like the PACMAN but 50 sheets will last for 2 hours
- power_gen = 20000
- time_per_sheet = 576
-
- overheat()
- explosion(src.loc, 3, 3, 3, -1)
+ explosion(src.loc, 3, 3, 5, 3)
+ del(src)
/obj/machinery/power/port_gen/pacman/mrs
name = "M.R.S.P.A.C.M.A.N.-type Portable Generator"
+ desc = "An advanced power generator that runs on tritium. Rated for 200 kW maximum safe output!"
icon_state = "portgen2"
- sheet_path = /obj/item/stack/sheet/mineral/tritium
+ sheet_path = /obj/item/stack/sheet/mineral/tritium
+
+ //I don't think tritium has any other use, so we might as well make this rewarding for players
+ //max safe power output (power level = 8) is 200 kW and lasts for 1 hour - 3 or 4 of these could power the station
+ power_gen = 25000 //watts
+ max_power_output = 10
+ time_per_sheet = 576
+ max_temperature = 800
+ temperature_gain = 90
board_path = "/obj/item/weapon/circuitboard/pacman/mrs"
- //produces 200 kW and lasts for 1 hour with 50 sheets
- power_gen = 50000
- time_per_sheet = 288
-
- overheat()
- explosion(src.loc, 4, 4, 4, -1)
+/obj/machinery/power/port_gen/pacman/mrs/explode()
+ //no special effects, but the explosion is pretty big (same as a supermatter shard).
+ explosion(src.loc, 3, 6, 12, 16, 1)
+ del(src)