-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathcollector.dm
341 lines (306 loc) · 12.5 KB
/
collector.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// Operation modes
#define POWER "power"
#define SCIENCE "research"
#define MONEY "money"
// stored_power += (pulse_strength-RAD_COLLECTOR_EFFICIENCY)*RAD_COLLECTOR_COEFFICIENT*(machine_tier+power_bonus)
#define RAD_COLLECTOR_EFFICIENCY 80 // radiation needs to be over this amount to get power
#define RAD_COLLECTOR_COEFFICIENT 40
#define RAD_COLLECTOR_STORED_OUT 0.1 // (this*100)% of stored power outputted per tick. Doesn't actualy change output total, lower numbers just means collectors output for longer in absence of a source
#define RAD_COLLECTOR_MINING_CONVERSION_RATE 0.000125 //This is gonna need a lot of tweaking to get right. This is the number used to calculate the conversion of watts to research points per process()
#define RAD_COLLECTOR_OUTPUT min(stored_power, (stored_power*RAD_COLLECTOR_STORED_OUT)+1000) //Produces at least 1000 watts if it has more than that stored
#define RAD_COLLECTOR_PAYOUT_SCALE 300
/obj/machinery/power/rad_collector
name = "Radiation Collector Array"
desc = "A device which uses Hawking Radiation and plasma to produce power."
icon = 'icons/obj/singularity.dmi'
icon_state = "ca"
anchored = FALSE
density = TRUE
req_access = list(ACCESS_ENGINE_EQUIP)
max_integrity = 350
integrity_failure = 80
circuit = /obj/item/circuitboard/machine/rad_collector
rad_insulation = RAD_EXTREME_INSULATION
/// How much power is stored in its buffer
var/stored_power = 0
/// Is it on
var/active = FALSE
// Are the controls and tanks locked
var/locked = FALSE
/// use modifier for gas use
var/drainratio = 0.5
/// How much gas to drain
var/drain = 0.01
/// What is it producing
var/mode = POWER
/// What gasses are we using
var/list/using = list(GAS_PLASMA)
/// Gasses we give
var/list/giving = list(GAS_TRITIUM = 1)
/// Last output used to calculate per minute
var/last_output = 0
// Higher machine tier will give more power
var/machine_tier = 0
// Higher power bonus will give more power
var/power_bonus = 0
// Balance amount of money given to crew
var/creditpayout = 0
var/obj/item/radio/radio
var/obj/item/tank/internals/plasma/loaded_tank = null
/obj/machinery/power/rad_collector/Initialize(mapload)
. = ..()
radio = new(src)
radio.keyslot = new /obj/item/encryptionkey/headset_eng
radio.subspace_transmission = TRUE
radio.canhear_range = 0
radio.recalculateChannels()
/obj/machinery/power/rad_collector/anchored
anchored = TRUE
/obj/machinery/power/rad_collector/Destroy()
QDEL_NULL(radio)
return ..()
/obj/machinery/power/rad_collector/process(delta_time)
if(!loaded_tank || !active)
return
var/gasdrained = drain*drainratio*delta_time
for(var/gasID in using) // Preliminary check before doing it again
if(loaded_tank.air_contents.get_moles(gasID) < gasdrained)
investigate_log("<font color='red'>out of fuel</font>.", INVESTIGATE_SINGULO)
investigate_log("<font color='red'>out of fuel</font>.", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful
playsound(src, 'sound/machines/ding.ogg', 50, 1)
var/area/A = get_area(loc)
var/msg = "Plasma depleted in [A.map_name], replacement tank required."
radio.talk_into(src, msg, RADIO_CHANNEL_ENGINEERING)
eject()
for(var/gasID in using)
loaded_tank.air_contents.adjust_moles(gasID, -gasdrained)
for(var/gasID in giving)
loaded_tank.air_contents.adjust_moles(gasID, giving[gasID]*gasdrained)
var/output = RAD_COLLECTOR_OUTPUT
switch(mode) // Now handle the special interactions
if(POWER)
add_avail(output)
stored_power -= output
last_output = output
if(SCIENCE)
if(is_station_level(z) && SSresearch.science_tech)
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, output*RAD_COLLECTOR_MINING_CONVERSION_RATE)
stored_power -= output
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG)
if(D)
D.adjust_money(output*RAD_COLLECTOR_MINING_CONVERSION_RATE)
last_output = output*RAD_COLLECTOR_MINING_CONVERSION_RATE
if(MONEY)
if(is_station_level(z))
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
var/payout = output/8000
stored_power -= min(payout*20000, stored_power)
creditpayout = log(1 + (payout / RAD_COLLECTOR_PAYOUT_SCALE)) * (RAD_COLLECTOR_PAYOUT_SCALE / log(2))
D.adjust_money(creditpayout)
last_output = payout
/obj/machinery/power/rad_collector/interact(mob/user)
if(anchored)
if(!src.locked)
toggle_power()
user.visible_message("[user.name] turns the [src.name] [active? "on":"off"].", \
span_notice("You turn the [src.name] [active? "on":"off"]."))
var/fuel = loaded_tank?.air_contents?.get_moles(GAS_PLASMA)
investigate_log("turned [active?"<font color='green'>on</font>":"<font color='red'>off</font>"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"<font color='red'>It is empty</font>"].", INVESTIGATE_SINGULO)
investigate_log("turned [active?"<font color='green'>on</font>":"<font color='red'>off</font>"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"<font color='red'>It is empty</font>"].", INVESTIGATE_SUPERMATTER) // yogs - so supermatter investigate is useful
return
else
to_chat(user, span_warning("The controls are locked!"))
return
/obj/machinery/power/rad_collector/can_be_unfasten_wrench(mob/user, silent)
if(loaded_tank)
if(!silent)
to_chat(user, span_warning("Remove the plasma tank first!"))
return FAILED_UNFASTEN
return ..()
/obj/machinery/power/rad_collector/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
connect_to_network()
else
disconnect_from_network()
/obj/machinery/power/rad_collector/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/tank/internals/plasma))
if(!anchored)
to_chat(user, span_warning("[src] needs to be secured to the floor first!"))
return TRUE
if(loaded_tank)
to_chat(user, span_warning("There's already a plasma tank loaded!"))
return TRUE
if(panel_open)
to_chat(user, span_warning("Close the maintenance panel first!"))
return TRUE
if(!user.transferItemToLoc(W, src))
return
loaded_tank = W
update_appearance(UPDATE_ICON)
else if(W.GetID())
if(togglelock(user))
return TRUE
else
return ..()
/obj/machinery/power/rad_collector/MouseDrop_T(atom/dropping, mob/user)
if(istype(dropping, /obj/item/tank/internals/plasma))
attackby(dropping, user)
else
..()
/obj/machinery/power/rad_collector/proc/togglelock(mob/user)
if(!user.canUseTopic(src, BE_CLOSE))
return
if(allowed(user))
if(active)
locked = !locked
to_chat(user, span_notice("You [locked ? "lock" : "unlock"] the controls."))
return TRUE
else
to_chat(user, span_warning("The controls can only be locked when \the [src] is active!"))
else
to_chat(user, span_danger("Access denied."))
/obj/machinery/power/rad_collector/AltClick(mob/user)
if(!user.canUseTopic(src, BE_CLOSE) || issilicon(user))
return
togglelock(user)
/obj/machinery/power/rad_collector/wrench_act(mob/living/user, obj/item/I)
if(!(default_unfasten_wrench(user, I)))
return FALSE
return TRUE
/obj/machinery/power/rad_collector/screwdriver_act(mob/living/user, obj/item/I)
. = TRUE // No afterattacks
if(..())
return
if(loaded_tank)
to_chat(user, "<span class='warning'>Remove the plasma tank first!</span>")
return
if(!(default_deconstruction_screwdriver(user, icon_state, icon_state, I)))
return FALSE // If it returns false probably meant to attack it
/obj/machinery/power/rad_collector/crowbar_act(mob/living/user, obj/item/I)
. = TRUE // Prevents afterattacks
if(loaded_tank)
if(locked)
to_chat(user, "<span class='warning'>The controls are locked!</span>")
return
eject()
if(default_deconstruction_crowbar(I))
return
to_chat(user, "<span class='warning'>There isn't a tank loaded!</span>")
/obj/machinery/power/rad_collector/multitool_act(mob/living/user, obj/item/I)
. = TRUE // No afterattack
if(locked)
to_chat(user, "<span class='warning'>[src] is locked!</span>")
return
if(active)
to_chat(user, "<span class='warning'>[src] is currently active, producing [mode].</span>")
return
var/choice = input(user,"Select a mode","Mode Selection:",null) as null|anything in list(POWER, SCIENCE, MONEY)
if(!choice)
return
switch(choice)
if(POWER)
if(!powernet)
to_chat(user, "<span class='warning'>[src] isn't connected to a powernet!</span>")
return
mode = POWER
using = list(GAS_PLASMA)
giving = list(GAS_TRITIUM = 1)
if(SCIENCE)
if(!is_station_level(z) && !SSresearch.science_tech)
to_chat(user, "<span class='warning'>[src] isn't linked to a research system!</span>")
return // Dont switch over
mode = SCIENCE
using = list(GAS_TRITIUM, GAS_O2)
giving = list(GAS_CO2 = 2) // Conservation of mass
if(MONEY)
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(!D)
to_chat(user, "<span class='warning'>[src] couldn't find the cargo budget!</span>")
return // Dont switch over
mode = MONEY
using = list(GAS_PLASMA)
giving = list(GAS_TRITIUM = 0.5) // money
to_chat(user, "<span class='warning'>You set the [src] mode to [mode] production.</span>")
/obj/machinery/power/rad_collector/return_analyzable_air()
if(loaded_tank)
return loaded_tank.return_analyzable_air()
else
return null
/obj/machinery/power/rad_collector/examine(mob/user)
. = ..()
if(active)
if(mode == POWER)
. += "<span class='notice'>[src]'s display states that it has stored <b>[DisplayJoules(stored_power)]</b>, and processing <b>[DisplayPower(RAD_COLLECTOR_OUTPUT)]</b>.</span>"
else if(mode == SCIENCE)
. += "<span class='notice'>[src]'s display states that it has stored a total of <b>[stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE]</b>, and producing [last_output*60] research points per minute.</span>"
else if(mode == MONEY)
. += "<span class='notice'>[src]'s display states that it has stored a total of <b>[stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE] credits</b>, and producing [creditpayout] credits per minute.</span>"
else
if(mode == POWER)
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Power production mode. Please insert <b>Plasma</b>. Use a multitool to change production modes.\"</span>"
else if(mode == SCIENCE)
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Research point production mode. Please insert <b>Tritium</b> and <b>Oxygen</b>. Use a multitool to change production modes.\"</span>"
else if(mode == MONEY)
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Money production mode. Please insert <b>Plasma</b>. Use a multitool to change production modes.\"</span>"
/obj/machinery/power/rad_collector/atom_break(damage_flag)
. = ..()
if(.)
eject()
/obj/machinery/power/rad_collector/proc/eject()
locked = FALSE
var/obj/item/tank/internals/plasma/Z = src.loaded_tank
if (!Z)
return
Z.forceMove(drop_location())
Z.layer = initial(Z.layer)
SET_PLANE_IMPLICIT(Z, initial(Z.plane))
src.loaded_tank = null
if(active)
toggle_power()
else
update_appearance()
/obj/machinery/power/rad_collector/rad_act(pulse_strength, collectable_radiation)
. = ..()
if(loaded_tank && active && collectable_radiation && pulse_strength > RAD_COLLECTOR_EFFICIENCY)
stored_power += (pulse_strength-RAD_COLLECTOR_EFFICIENCY)*RAD_COLLECTOR_COEFFICIENT*sqrt(machine_tier+power_bonus)
/obj/machinery/power/rad_collector/update_overlays()
. = ..()
if(loaded_tank)
. += "ptank"
if(stat & (NOPOWER|BROKEN))
return
if(active)
. += "on"
//honestly this should be balanced
/obj/machinery/power/rad_collector/RefreshParts()
for(var/obj/item/stock_parts/capacitor/c in component_parts)
power_bonus = initial(power_bonus) + c.rating
for(var/obj/item/stock_parts/manipulator/l in component_parts)
drainratio = initial(drainratio)/l.rating
for(var/obj/item/stock_parts/matter_bin/b in component_parts)
machine_tier = initial(machine_tier) + b.rating
/obj/machinery/power/rad_collector/proc/toggle_power()
active = !active
if(active)
icon_state = "ca_on"
flick("ca_active", src)
else
icon_state = "ca"
flick("ca_deactive", src)
update_appearance(UPDATE_ICON)
/obj/machinery/power/rad_collector/bullet_act(obj/projectile/P)
if(istype(P, /obj/projectile/energy/nuclear_particle))
rad_act(P.irradiate * P.damage, collectable_radiation = TRUE) // equivalent of a 2000 strength rad pulse for each particle
P.nodamage = TRUE
return ..()
#undef RAD_COLLECTOR_EFFICIENCY
#undef RAD_COLLECTOR_COEFFICIENT
#undef RAD_COLLECTOR_STORED_OUT
#undef RAD_COLLECTOR_MINING_CONVERSION_RATE
#undef RAD_COLLECTOR_OUTPUT
#undef POWER
#undef SCIENCE
#undef MONEY