diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 507b656ed1a..664cdb695f4 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -113,6 +113,7 @@ Class Procs: var/custom_aghost_alerts=0 var/panel_open = 0 var/myArea + var/interact_offline = 0 // Can the machine be interacted with while de-powered. /obj/machinery/New() addAtProcessing() @@ -185,7 +186,7 @@ Class Procs: /obj/machinery/Topic(href, href_list) ..() - if(stat & (NOPOWER|BROKEN)) + if(!interact_offline && stat & (NOPOWER|BROKEN)) return 1 if(usr.restrained() || usr.lying || usr.stat) return 1 @@ -230,7 +231,7 @@ Class Procs: return src.attack_hand(user) /obj/machinery/attack_hand(mob/user as mob) - if(stat & (NOPOWER|BROKEN|MAINT)) + if(!interact_offline && stat & (NOPOWER|BROKEN|MAINT)) return 1 if(user.lying || user.stat) return 1 diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index e86715366d9..c952d0735d3 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -1,144 +1,392 @@ -// It.. uses a lot of power. Everything under power is engineering stuff, at least. -/obj/machinery/computer/gravity_control_computer - name = "Gravity Generator Control" - desc = "A computer to control a local gravity generator. Qualified personnel only." - icon = 'icons/obj/computer.dmi' - icon_state = "airtunnel0e" - anchored = 1 - density = 1 - var/obj/machinery/gravity_generator = null +// +// Gravity Generator +// +var/list/gravity_generators = list() // We will keep track of this by adding new gravity generators to the list, and keying it with the z level. -/obj/machinery/gravity_generator/ - name = "Gravitational Generator" +var/const/POWER_IDLE = 0 +var/const/POWER_UP = 1 +var/const/POWER_DOWN = 2 + +var/const/GRAV_NEEDS_SCREWDRIVER = 0 +var/const/GRAV_NEEDS_WELDING = 1 +var/const/GRAV_NEEDS_PLASTEEL = 2 +var/const/GRAV_NEEDS_WRENCH = 3 + +// +// Abstract Generator +// + +/obj/machinery/gravity_generator + name = "gravitational generator" desc = "A device which produces a gravaton field when set up." - icon = 'icons/obj/singularity.dmi' - icon_state = "TheSingGen" + icon = 'icons/obj/machines/gravity_generator.dmi' anchored = 1 density = 1 + use_power = 0 + unacidable = 1 + var/sprite_number = 0 + +/obj/machinery/gravity_generator/ex_act(severity) + if(severity == 1) // Very sturdy. + set_broken() + +/obj/machinery/gravity_generator/meteorhit() + return + +/obj/machinery/gravity_generator/update_icon() + ..() + icon_state = "[get_status()]_[sprite_number]" + +/obj/machinery/gravity_generator/proc/get_status() + return "off" + +// You aren't allowed to move. +/obj/machinery/gravity_generator/Move() + ..() + qdel(src) + +/obj/machinery/gravity_generator/proc/set_broken() + stat |= BROKEN + +/obj/machinery/gravity_generator/proc/set_fix() + stat &= ~BROKEN + +/obj/machinery/gravity_generator/part/Destroy() + set_broken() + if(main_part) + qdel(main_part) + ..() + +// +// Part generator which is mostly there for looks +// + +/obj/machinery/gravity_generator/part + var/obj/machinery/gravity_generator/main/main_part = null + +/obj/machinery/gravity_generator/part/attackby(obj/item/I as obj, mob/user as mob) + return main_part.attackby(I, user) + +/obj/machinery/gravity_generator/part/get_status() + return main_part.get_status() + +/obj/machinery/gravity_generator/part/attack_hand(mob/user as mob) + return main_part.attack_hand(user) + +/obj/machinery/gravity_generator/part/set_broken() + ..() + if(main_part && !(main_part.stat & BROKEN)) + main_part.set_broken() + +// +// Generator which spawns with the station. +// + +/obj/machinery/gravity_generator/main/station/initialize() + setup_parts() + middle.overlays += "activated" + update_list() + +// +// Generator an admin can spawn +// + +/obj/machinery/gravity_generator/main/station/admin/New() + ..() + initialize() + +// +// Main Generator with the main code +// + +/obj/machinery/gravity_generator/main + icon_state = "on_8" + idle_power_usage = 0 + active_power_usage = 3000 + power_channel = ENVIRON + sprite_number = 8 use_power = 1 - idle_power_usage = 200 - active_power_usage = 1000 + interact_offline = 1 var/on = 1 - var/list/localareas = list() - var/effectiverange = 25 + var/breaker = 1 + var/list/parts = list() + var/obj/middle = null + var/charging_state = POWER_IDLE + var/charge_count = 100 + var/current_overlay = null + var/broken_state = 0 - // Borrows code from cloning computer -/obj/machinery/computer/gravity_control_computer/New() +/obj/machinery/gravity_generator/main/Destroy() // If we somehow get deleted, remove all of our other parts. + investigate_log("was destroyed!", "gravity") + on = 0 + update_list() + for(var/obj/machinery/gravity_generator/part/O in parts) + O.main_part = null + qdel(O) ..() - spawn(5) - updatemodules() - return - return -/obj/machinery/gravity_generator/New() +/obj/machinery/gravity_generator/main/proc/setup_parts() + var/turf/our_turf = get_turf(src) + // 9x9 block obtained from the bottom middle of the block + var/list/spawn_turfs = block(locate(our_turf.x - 1, our_turf.y + 2, our_turf.z), locate(our_turf.x + 1, our_turf.y, our_turf.z)) + var/count = 10 + for(var/turf/T in spawn_turfs) + count-- + if(T == our_turf) // Skip our turf. + continue + var/obj/machinery/gravity_generator/part/part = new(T) + if(count == 5) // Middle + middle = part + part.sprite_number = count; + part.main_part = src + parts += part + part.update_icon() + +/obj/machinery/gravity_generator/main/proc/connected_parts() + return parts.len == 8 + +/obj/machinery/gravity_generator/main/set_broken() ..() - spawn(5) - locatelocalareas() - return - return + for(var/obj/machinery/gravity_generator/M in parts) + if(!(M.stat & BROKEN)) + M.set_broken() + middle.overlays.Cut() + charge_count = 0 + breaker = 0 + set_power() + set_state(0) + investigate_log("has broken down.", "gravity") +/obj/machinery/gravity_generator/main/set_fix() + ..() + for(var/obj/machinery/gravity_generator/M in parts) + if(M.stat & BROKEN) + M.set_fix() + broken_state = 0 + update_icon() + set_power() +// Interaction -/obj/machinery/computer/gravity_control_computer/proc/updatemodules() - src.gravity_generator = findgenerator() - - - -/obj/machinery/gravity_generator/proc/locatelocalareas() - for(var/area/A in range(src,effectiverange)) - if(A.name == "Space") - continue // No (de)gravitizing space. - if(A.master && !( A.master in localareas) ) - localareas += A.master - -/obj/machinery/computer/gravity_control_computer/proc/findgenerator() - var/obj/machinery/gravity_generator/foundgenerator = null - for(dir in list(NORTH,EAST,SOUTH,WEST)) - //world << "SEARCHING IN [dir]" - foundgenerator = locate(/obj/machinery/gravity_generator/, get_step(src, dir)) - if (!isnull(foundgenerator)) - //world << "FOUND" - break - return foundgenerator - - -/obj/machinery/computer/gravity_control_computer/attack_paw(mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/gravity_control_computer/attack_ai(mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/gravity_control_computer/attack_hand(mob/user as mob) - user.set_machine(src) - add_fingerprint(user) - - if(stat & (BROKEN|NOPOWER)) - return - - updatemodules() - - var/dat = "

Generator Control System

" - //dat += "Refresh" - if(gravity_generator) - if(gravity_generator:on) - dat += "
Gravity Status: ON

" +// Fixing the gravity generator. +/obj/machinery/gravity_generator/main/attackby(obj/item/I as obj, mob/user as mob) + var/old_broken_state = broken_state + switch(broken_state) + if(GRAV_NEEDS_SCREWDRIVER) + if(istype(I, /obj/item/weapon/screwdriver)) + user << "You secure the screws of the framework." + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + broken_state++ + if(GRAV_NEEDS_WELDING) + if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = I + if(WT.remove_fuel(1, user)) + user << "You mend the damaged framework." + playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1) + broken_state++ + if(GRAV_NEEDS_PLASTEEL) + if(istype(I, /obj/item/stack/sheet/plasteel)) + var/obj/item/stack/sheet/plasteel/PS = I + if(PS.amount >= 10) + PS.use(10) + user << "You add the plating to the framework." + playsound(src.loc, 'sound/machines/click.ogg', 75, 1) + broken_state++ + else + user << "You need 10 sheets of plasteel." + if(GRAV_NEEDS_WRENCH) + if(istype(I, /obj/item/weapon/wrench)) + user << "You secure the plating to the framework." + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + set_fix() else - dat += "
Gravity Status: OFF

" + ..() + if(old_broken_state != broken_state) + update_icon() - dat += "
Currently Supplying Gravitons To:
" - - for(var/area/A in gravity_generator:localareas) - if(A.has_gravity && gravity_generator:on) - dat += "[A]
" - - else if (A.has_gravity) - dat += "[A]
" - - else - dat += "[A]
" - - dat += "
Maintainence Functions:
" - if(gravity_generator:on) - dat += " TURN GRAVITY GENERATOR OFF. " - else - dat += " TURN GRAVITY GENERATOR ON. " +/obj/machinery/gravity_generator/main/attack_hand(mob/user as mob) + if(!..()) + return interact(user) +/obj/machinery/gravity_generator/main/interact(mob/user as mob) + if(stat & BROKEN) + return + var/dat = "Gravity Generator Breaker: " + if(breaker) + dat += "ON OFF" else - dat += "No local gravity generator detected!" + dat += "ON OFF " - user << browse(dat, "window=gravgen") - onclose(user, "gravgen") + dat += "
Generator Status:
" + if(charging_state != POWER_IDLE) + dat += "WARNING Radiation Detected.
[charging_state == POWER_UP ? "Charging..." : "Discharging..."]" + else if(on) + dat += "Powered." + else + dat += "Unpowered." + + dat += "
Gravity Charge: [charge_count]%
" + + var/datum/browser/popup = new(user, "gravgen", name) + popup.set_content(dat) + popup.open() -/obj/machinery/computer/gravity_control_computer/Topic(href, href_list) - //set background = 1 - ..() +/obj/machinery/gravity_generator/main/Topic(href, href_list) - if ( (get_dist(src, usr) > 1 )) - if (!istype(usr, /mob/living/silicon)) - usr.unset_machine() - usr << browse(null, "window=air_alarm") - return + if(..()) + return if(href_list["gentoggle"]) - if(gravity_generator:on) - gravity_generator:on = 0 - - for(var/area/A in gravity_generator:localareas) - var/obj/machinery/gravity_generator/G - for(G in machines) - if((A.master in G.localareas) && (G.on)) - break - if(!G) - A.gravitychange(0,A) - - - else - for(var/area/A in gravity_generator:localareas) - gravity_generator:on = 1 - A.gravitychange(1,A) - + breaker = !breaker + investigate_log("was toggled [breaker ? "ON" : "OFF"] by [usr.key].", "gravity") + set_power() src.updateUsrDialog() - return \ No newline at end of file + +// Power and Icon States + +/obj/machinery/gravity_generator/main/power_change() + ..() + investigate_log("has [stat & NOPOWER ? "lost" : "regained"] power.", "gravity") + set_power() + +/obj/machinery/gravity_generator/main/get_status() + if(stat & BROKEN) + return "fix[min(broken_state, 3)]" + return on || charging_state != POWER_IDLE ? "on" : "off" + +/obj/machinery/gravity_generator/main/update_icon() + ..() + for(var/obj/O in parts) + O.update_icon() + +// Set the charging state based on power/breaker. +/obj/machinery/gravity_generator/main/proc/set_power() + var/new_state = 0 + if(stat & (NOPOWER|BROKEN) || !breaker) + new_state = 0 + else if(breaker) + new_state = 1 + + charging_state = new_state ? POWER_UP : POWER_DOWN // Startup sequence animation. + investigate_log("is now [charging_state == POWER_UP ? "charging" : "discharging"].", "gravity") + update_icon() + +// Set the state of the gravity. +/obj/machinery/gravity_generator/main/proc/set_state(var/new_state) + charging_state = POWER_IDLE + on = new_state + use_power = on ? 2 : 1 + // Sound the alert if gravity was just enabled or disabled. + var/alert = 0 + var/area/area = get_area(src) + if(new_state) // If we turned on + if(gravity_in_level() == 0) + alert = 1 + investigate_log("was brought online and is now producing gravity for this level.", "gravity") + message_admins("The gravity generator was brought online. ([area.name])") + else + if(gravity_in_level() == 1) + alert = 1 + investigate_log("was brought offline and there is now no gravity for this level.", "gravity") + message_admins("The gravity generator was brought offline with no backup generator. ([area.name])") + + update_icon() + update_list() + src.updateUsrDialog() + if(alert) + shake_everyone() + +// Charge/Discharge and turn on/off gravity when you reach 0/100 percent. +// Also emit radiation and handle the overlays. +/obj/machinery/gravity_generator/main/process() + if(stat & BROKEN) + return + if(charging_state != POWER_IDLE) + if(charging_state == POWER_UP && charge_count >= 100) + set_state(1) + else if(charging_state == POWER_DOWN && charge_count <= 0) + set_state(0) + else + if(charging_state == POWER_UP) + charge_count += 2 + else if(charging_state == POWER_DOWN) + charge_count -= 2 + + if(charge_count % 4 == 0 && prob(75)) // Let them know it is charging/discharging. + playsound(src.loc, 'sound/effects/EMPulse.ogg', 100, 1) + + updateDialog() + if(prob(25)) // To help stop "Your clothes feel warm" spam. + pulse_radiation() + + var/overlay_state = null + switch(charge_count) + if(0 to 20) + overlay_state = null + if(21 to 40) + overlay_state = "startup" + if(41 to 60) + overlay_state = "idle" + if(61 to 80) + overlay_state = "activating" + if(81 to 100) + overlay_state = "activated" + + if(overlay_state != current_overlay) + if(middle) + middle.overlays.Cut() + if(overlay_state) + middle.overlays += overlay_state + current_overlay = overlay_state + + +/obj/machinery/gravity_generator/main/proc/pulse_radiation() + for(var/mob/living/L in view(7, src)) + L.apply_effect(20, IRRADIATE) + +// Shake everyone on the z level to let them know that gravity was enagaged/disenagaged. +/obj/machinery/gravity_generator/main/proc/shake_everyone() + var/turf/our_turf = get_turf(src) + for(var/mob/M in player_list) + var/turf/their_turf = get_turf(M) + if(M.client && their_turf.z == our_turf.z) + shake_camera(M, 15, 1) + M.playsound_local(our_turf, 'sound/effects/alert.ogg', 100, 1, 0.5) + +/obj/machinery/gravity_generator/main/proc/gravity_in_level() + var/turf/T = get_turf(src) + if(!T) + return 0 + if(gravity_generators["[T.z]"]) + return length(gravity_generators["[T.z]"]) + return 0 + +/obj/machinery/gravity_generator/main/proc/update_list() + var/turf/T = get_turf(src.loc) + if(T) + if(!gravity_generators["[T.z]"]) + gravity_generators["[T.z]"] = list() + if(on) + gravity_generators["[T.z]"] |= src + else + gravity_generators["[T.z]"] -= src + +// Misc + +/obj/item/weapon/paper/gravity_gen + name = "paper- 'Generate your own gravity!'" + info = {"

Gravity Generator Instructions For Dummies

+

Surprisingly, gravity isn't that hard to make! All you have to do is inject deadly radioactive minerals into a ball of + energy and you have yourself gravity! You can turn the machine on or off when required but you must remember that the generator + will EMIT RADIATION when charging or discharging, you can tell it is charging or discharging by the noise it makes, so please WEAR PROTECTIVE CLOTHING.

+
+

It blew up!

+

Don't panic! The gravity generator was designed to be easily repaired. If, somehow, the sturdy framework did not survive then + please proceed to panic; otherwise follow these steps.

    +
  1. Secure the screws of the framework with a screwdriver.
  2. +
  3. Mend the damaged framework with a welding tool.
  4. +
  5. Add additional plasteel plating.
  6. +
  7. Secure the additional plating with a wrench.
"} diff --git a/icons/obj/machines/gravity_generator.dmi b/icons/obj/machines/gravity_generator.dmi new file mode 100644 index 00000000000..69395034dc8 Binary files /dev/null and b/icons/obj/machines/gravity_generator.dmi differ