Advertisement
neuroticfox

DraCon Tier 2

Jul 27th, 2021 (edited)
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.05 KB | None | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local term = require("term")
  4. local gpu = component.gpu
  5. local screen = component.screen
  6.  
  7. -- DynamicRes
  8.  
  9. local ratioX, ratioY = screen.getAspectRatio()
  10. local maxX, maxY = gpu.maxResolution()
  11. gpu.setResolution(math.min(ratioX*55, maxX), math.min(ratioY*25,maxY))
  12.  
  13. -- Safety Checks
  14.  
  15. if not component.isAvailable("draconic_reactor") then
  16. print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
  17. os.exit()
  18. end
  19. reactor = component.draconic_reactor
  20. local flux_gates = {}
  21. for x,y in pairs(component.list("flux_gate")) do
  22. flux_gates[#flux_gates+1] = x
  23. end
  24. if #flux_gates < 2 then
  25. print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  26. os.exit()
  27. end
  28. flux_in = component.proxy(flux_gates[1])
  29. flux_out = component.proxy(flux_gates[2])
  30. if not flux_in or not flux_out then
  31. print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  32. os.exit()
  33. end
  34.  
  35. -- Functions
  36.  
  37. function exit_msg(msg)
  38. term.clear()
  39. print(msg)
  40. os.exit()
  41. end
  42.  
  43. function modifyPow(newPow)
  44. local newPow = outflow
  45. if chaosmode == 1 then
  46. newPow = 0
  47. end
  48. end
  49.  
  50. -- Buttons
  51.  
  52. local adj_button_width = 19
  53. local temp_adjust_x_offset = 68
  54. local temp_adjust_y_offset = 2
  55. local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
  56. local field_adjust_y_offset = 2
  57. local status = "PeFi"
  58. local lowest_field = 100
  59. local lowest_fuel = 100
  60. local highest_temp = 0
  61. local highest_sat = 0
  62. local highest_outflow = 0
  63. local cutoff_field = 0.75
  64.  
  65. -- Inflow PID
  66. local proportional_field_error = 0
  67. local inflow_I_sum = 0
  68. local integral_field_error = 0
  69. local derivative_field_error = 0
  70. local inflow_D_last = 0
  71. local inflow_correction = 0
  72.  
  73. -- Outflow PID
  74. local proportional_temp_error = 0
  75. local outflow_I_sum = 0
  76. local integral_temp_error = 0
  77. local derivative_temp_error = 0
  78. local outflow_D_last = 0
  79. local outflow_correction = 0
  80. local newPow = 1
  81.  
  82. local buttons = {
  83. start={
  84. x=2,
  85. y=1,
  86. width=10,
  87. height=1,
  88. text="Activate",
  89. action=function()
  90. if safe then
  91. state = "Charging"
  92. reactor.chargeReactor()
  93. elseif shutting_down then
  94. state = "Active"
  95. reactor.activateReactor()
  96. end
  97. end,
  98. },
  99. shutdown={
  100. x=2,
  101. y=3,
  102. width=10,
  103. height=1,
  104. text="Shutdown",
  105. action=function()
  106. cutoff_temp = 8001
  107. ideal_temp = 8000
  108. ideal_strength = 75
  109. cutoff_field = 0.75
  110. state = "Manual Shutdown"
  111. reactor.stopReactor()
  112. end,
  113. },
  114. chaosmode={
  115. x=2,
  116. y=5,
  117. width=10,
  118. height=1,
  119. text="ChaosMode",
  120. action=function()
  121. cutoff_temp = 19000
  122. cutoff_field = 12.5
  123. ideal_strength = 75
  124. ideal_temp = 50000
  125. chaosmode = 1
  126. end,
  127. },
  128.  
  129. switch_gates={
  130. x=2,
  131. y=7,
  132. width=10,
  133. height=1,
  134. text="Swap Gates",
  135. action=function()
  136. cutoff_temp = 10500
  137. local old_addr = flux_in.address
  138. flux_in = component.proxy(flux_out.address)
  139. flux_out = component.proxy(old_addr)
  140. end,
  141. },
  142. exit={
  143. x=2,
  144. y=9,
  145. width=10,
  146. height=1,
  147. text="Exit",
  148. action=function()
  149. reactor.stopReactor()
  150. gpu.setResolution(gpu.maxResolution())
  151. event_loop = false
  152. end,
  153. },
  154. }
  155.  
  156. -- main code
  157.  
  158. flux_in.setFlowOverride(0)
  159. flux_out.setFlowOverride(0)
  160. flux_in.setOverrideEnabled(true)
  161. flux_out.setOverrideEnabled(true)
  162.  
  163. local condition = reactor.getReactorInfo()
  164. if not condition then
  165. print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
  166. os.exit()
  167. end
  168.  
  169. ideal_strength = 15
  170.  
  171. ideal_temp = 8000
  172. cutoff_temp = 8001
  173.  
  174. -- tweakable pid gains
  175.  
  176. inflow_P_gain = 1
  177. inflow_I_gain = 0.04
  178. inflow_D_gain = 0.05
  179.  
  180. outflow_P_gain = 500
  181. outflow_I_gain = 0.10
  182. outflow_II_gain = 0.0000003
  183. outflow_D_gain = 30000
  184.  
  185. -- initialize main loop
  186.  
  187. inflow_I_sum = 0
  188. inflow_D_last = 0
  189.  
  190. outflow_I_sum = 0
  191. outflow_II_sum = 0
  192. outflow_D_last = 0
  193.  
  194. state = "Standby"
  195. shutting_down = false
  196.  
  197. if condition.temperature > 25 then
  198. state = "Cooling"
  199. end
  200. if condition.temperature > 2000 then
  201. state = "Active"
  202. end
  203.  
  204. -- Possible states:
  205. --Standby
  206. --Charging
  207. --Active
  208. --Manual Shutdown
  209. --Emergency Shutdown
  210. --Cooling
  211.  
  212. event_loop = true
  213. while event_loop do
  214.  
  215. if not component.isAvailable("draconic_reactor") then
  216. exit_msg("Reactor disconnected, exiting")
  217. end
  218.  
  219. if not component.isAvailable("flux_gate") then
  220. exit_msg("Flux gates disconnected, exiting")
  221. end
  222.  
  223. local info = reactor.getReactorInfo()
  224.  
  225. -- Highest Heat Value
  226.  
  227. if info.temperature > highest_temp then
  228. highest_temp = info.temperature
  229. end
  230.  
  231. -- Highest Sat Value
  232.  
  233. if ((info.energySaturation / info.maxEnergySaturation) * 100) > highest_sat then
  234. highest_sat = ((info.energySaturation / info.maxEnergySaturation) * 100)
  235. end
  236.  
  237. -- Lowest Field Value ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  238.  
  239. if ((info.fieldStrength / info.maxFieldStrength) * 100) < lowest_field then
  240. lowest_field = ((info.fieldStrength / info.maxFieldStrength) * 100)
  241. end
  242.  
  243. -- Lowest Field Value
  244.  
  245. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < lowest_fuel then
  246. lowest_fuel = ((1 - info.fuelConversion / info.maxFuelConversion) * 100)
  247. end
  248.  
  249. local inflow = 0
  250. local outflow = 0
  251.  
  252. shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
  253. running = state == "Charging" or state == "Active"
  254. safe = state == "Standby" or state == "Cooling"
  255.  
  256. if state == "Charging" then
  257. inflow = 5000000
  258.  
  259. if info.temperature > 2000 then
  260. reactor.activateReactor()
  261. state = "Active"
  262. end
  263. elseif state == "Cooling" then
  264. if info.temperature < 25 then
  265. state = "Standby"
  266. end
  267. inflow = 10
  268. outflow = 20
  269. elseif state == "Standby" then
  270. inflow = 10
  271. outflow = 20
  272. else
  273. -- adjust inflow rate based on field strength
  274.  
  275. field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
  276. proportional_field_error = field_error * inflow_P_gain
  277. inflow_I_sum = inflow_I_sum + field_error
  278. integral_field_error = inflow_I_sum * inflow_I_gain
  279. derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  280. inflow_D_last = field_error
  281. inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  282. if inflow_correction < 0 then
  283. inflow_I_sum = inflow_I_sum - field_error
  284. end
  285. inflow = inflow_correction
  286.  
  287. if not shutting_down then
  288.  
  289. -- adjust outflow rate based on core temperature
  290.  
  291. temp_error = ideal_temp - info.temperature
  292. proportional_temp_error = temp_error * outflow_P_gain
  293. outflow_I_sum = outflow_I_sum + temp_error
  294. integral_temp_error = outflow_I_sum * outflow_I_gain
  295. if math.abs(temp_error) < 100 then
  296. outflow_II_sum = outflow_II_sum + integral_temp_error
  297. else
  298. outflow_II_sum = 0
  299. end
  300. second_integral_temp_error = outflow_II_sum * outflow_II_gain
  301. derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  302. outflow_D_last = temp_error
  303. outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  304. if outflow_correction < 0 then
  305. outflow_I_sum = outflow_I_sum - temp_error
  306. end
  307. outflow = outflow_correction
  308.  
  309. -- cut off reactor in case of emergency
  310.  
  311. if info.temperature > cutoff_temp then
  312. print("Reactor Too Hot, shutting down")
  313. state = "Emergency Shutdown"
  314. reactor.stopReactor()
  315. end
  316. if ((info.fieldStrength / info.maxFieldStrength) * 100) < cutoff_field then
  317. print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
  318. state = "Emergency Shutdown"
  319. reactor.stopReactor()
  320. end
  321. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 5 then
  322. print("Reactor Fuel Low, Shutting Down")
  323. state = "Emergency Shutdown"
  324. reactor.stopReactor()
  325. end
  326. else
  327. if info.temperature < 2000 then
  328. state = "Cooling"
  329. end
  330. end
  331. end
  332.  
  333. if state ~= "Active" and not shutting_down then
  334. inflow_I_sum = 0
  335. inflow_D_last = 0
  336. outflow_I_sum = 0
  337. outflow_II_sum = 0
  338. outflow_D_last = 0
  339. end
  340.  
  341. if inflow < 0 then
  342. inflow = 0
  343. end
  344. if outflow < 0 then
  345. outflow = 0
  346. end
  347.  
  348. inflow = math.floor(inflow)
  349. outflow = math.floor(outflow)
  350.  
  351. flux_in.setFlowOverride(inflow)
  352. flux_out.setFlowOverride(outflow)
  353.  
  354. -- Draw screen
  355.  
  356. if term.isAvailable() then
  357.  
  358. -- Draw Values
  359.  
  360. function modify_eff(offset)
  361. local eff = ((outflow / inflow) * 100)
  362. if eff > 100000 then
  363. eff = 1
  364. end
  365. end
  366.  
  367. local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
  368.  
  369. local left_margin = 2
  370. local spacing = 1
  371. local values = {
  372. string.format(" Field: %7.1f%%", ((info.fieldStrength / info.maxFieldStrength) * 100)),
  373. "",
  374. string.format(" Fuel: %7.1f%%", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
  375. "",
  376. string.format(" Temper: %7.1f°c", info.temperature),
  377. "",
  378. string.format(" Energy: %7.0fRF/t", outflow),
  379. "",
  380. " State: " .. state .. "",
  381. "",
  382. "",
  383. "",
  384. "",
  385. "",
  386. "",
  387. string.format("ETA %2dd, %2dh, %2dm, %2ds", secondsToExpire/86400, secondsToExpire/3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
  388. }
  389.  
  390.  
  391. term.clear()
  392.  
  393. for i, v in ipairs(values) do
  394. term.setCursor(left_margin, i * spacing)
  395. term.write(v)
  396. end
  397.  
  398. -- Draw button values
  399.  
  400. term.setCursor(temp_adjust_x_offset, temp_adjust_y_offset+10)
  401. term.write(" ")
  402. term.setCursor(field_adjust_x_offset+1, field_adjust_y_offset+10)
  403. term.write(" ")
  404.  
  405. -- Draw Buttons
  406.  
  407. gpu.setForeground(0x000000)
  408.  
  409. for bname, button in pairs(buttons) do
  410. if button.depressed then
  411.  
  412. button.depressed = button.depressed - 1
  413. if button.depressed == 0 then
  414. button.depressed = nil
  415. end
  416. end
  417. if button.condition == nil or button.condition() then
  418. local center_color = 0xAAAAAA
  419. local highlight_color = 0xCCCCCC
  420. local lowlight_color = 0x808080
  421. if button.depressed then
  422. center_color = 0x999999
  423. highlight_color = 0x707070
  424. lowlight_color = 0xBBBBBB
  425. end
  426. gpu.setBackground(center_color)
  427. gpu.fill(button.x, button.y, button.width, button.height, " ")
  428. if button.width > 1 and button.height > 1 then
  429. gpu.setBackground(lowlight_color)
  430. gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
  431. gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
  432. gpu.setBackground(highlight_color)
  433. gpu.fill(button.x, button.y, 1, button.height, " ")
  434. gpu.fill(button.x, button.y, button.width, 1, " ")
  435. end
  436. gpu.setBackground(center_color)
  437. term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
  438. term.write(button.text)
  439. end
  440. end
  441.  
  442. gpu.setBackground(0x000000)
  443. gpu.setForeground(0xFFFFFF)
  444. end
  445.  
  446. -- Wait for next tick, or manual shutdown
  447.  
  448. local event, id, op1, op2 = event.pull(0.05)
  449. if event == "interrupted" then
  450. if safe then
  451. break
  452. end
  453. elseif event == "touch" then
  454.  
  455. -- Handle Button Presses
  456.  
  457. local x = op1
  458. local y = op2
  459.  
  460. for bname, button in pairs(buttons) do
  461. if (button.condition == nil or button.condition()) and x >= button.x and x <= button.x + button.width and y >= button.y and y <= button.y + button.height then
  462. button.action()
  463. button.depressed = 3
  464. end
  465. end
  466. end
  467. end
  468.  
  469. term.clear()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement