diff --git a/baystation12.dme b/baystation12.dme index 90020c0864..52a2cd5319 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -318,7 +318,6 @@ #include "code\game\machinery\requests_console.dm" #include "code\game\machinery\robot_fabricator.dm" #include "code\game\machinery\seed_extractor.dm" -#include "code\game\machinery\shieldgen.dm" #include "code\game\machinery\Sleeper.dm" #include "code\game\machinery\spaceheater.dm" #include "code\game\machinery\status_display.dm" @@ -1316,6 +1315,13 @@ #include "code\modules\scripting\Scanner\Tokens.dm" #include "code\modules\security levels\keycard authentication.dm" #include "code\modules\security levels\security levels.dm" +#include "code\modules\shieldgen\circuits_and_designs.dm" +#include "code\modules\shieldgen\emergency_shield.dm" +#include "code\modules\shieldgen\energy_field.dm" +#include "code\modules\shieldgen\sheldwallgen.dm" +#include "code\modules\shieldgen\shield_capacitor.dm" +#include "code\modules\shieldgen\shield_gen.dm" +#include "code\modules\shieldgen\shield_gen_external.dm" #include "code\modules\shuttles\antagonist.dm" #include "code\modules\shuttles\departmental.dm" #include "code\modules\shuttles\shuttle.dm" @@ -1388,11 +1394,6 @@ #include "code\WorkInProgress\Cael_Aislinn\Rust\gyrotron_controller.dm" #include "code\WorkInProgress\Cael_Aislinn\Rust\radiation.dm" #include "code\WorkInProgress\Cael_Aislinn\Rust\virtual_particle_catcher.dm" -#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\circuits_and_designs.dm" -#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\energy_field.dm" -#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_capacitor.dm" -#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen.dm" -#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen_external.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\LaserComputer.dm" #include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm" #include "code\WorkInProgress\Chinsky\ashtray.dm" diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm deleted file mode 100644 index dab223aeb6..0000000000 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen_external.dm +++ /dev/null @@ -1,44 +0,0 @@ -//---------- external shield generator -//generates an energy field that loops around any built up area in space (is useless inside) halts movement and airflow, is blocked by walls, windows, airlocks etc - -/obj/machinery/shield_gen/external - name = "hull shield generator" - -/obj/machinery/shield_gen/external/New() - ..() - -/obj/machinery/shield_gen/external/get_shielded_turfs() - var - list - open = list(get_turf(src)) - closed = list() - - while(open.len) - for(var/turf/T in open) - for(var/turf/O in orange(1, T)) - if(get_dist(O,src) > field_radius) - continue - var/add_this_turf = 0 - if(istype(O,/turf/space)) - for(var/turf/simulated/G in orange(1, O)) - add_this_turf = 1 - break - - //uncomment this for structures (but not lattices) to be surrounded by shield as well - /*if(!add_this_turf) - for(var/obj/structure/S in orange(1, O)) - if(!istype(S, /obj/structure/lattice)) - add_this_turf = 1 - break - if(add_this_turf) - for(var/obj/structure/S in O) - if(!istype(S, /obj/structure/lattice)) - add_this_turf = 0 - break*/ - - if(add_this_turf && !(O in open) && !(O in closed)) - open += O - open -= T - closed += T - - return closed diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 3c2db8e064..9a097030d5 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -300,7 +300,7 @@ datum/controller/game_controller/proc/process_machines_power() if(M) //check if the area has power for M's channel //this will keep stat updated in case the machine is moved from one area to another. - M.update_powered_status(A) //we've already made sure A is a master area, above. + M.power_change(A) //we've already made sure A is a master area, above. if(!(M.stat & NOPOWER) && M.use_power) M.auto_use_power() diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index af1fe64a9f..d4450cbb78 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -276,15 +276,15 @@ del(src) /obj/machinery/computer/scan_consolenew/power_change() + ..() if(stat & BROKEN) icon_state = "broken" - else if(powered()) - icon_state = initial(icon_state) - stat &= ~NOPOWER else - spawn(rand(0, 15)) - src.icon_state = "c_unpowered" - stat |= NOPOWER + if (stat & NOPOWER) + spawn(rand(0, 15)) + src.icon_state = "c_unpowered" + else + icon_state = initial(icon_state) /obj/machinery/computer/scan_consolenew/New() ..() diff --git a/code/game/gamemodes/events/ninja_equipment.dm b/code/game/gamemodes/events/ninja_equipment.dm index 8025fa0809..f2f62581f8 100644 --- a/code/game/gamemodes/events/ninja_equipment.dm +++ b/code/game/gamemodes/events/ninja_equipment.dm @@ -1031,8 +1031,7 @@ ________________________________________________________________________________ drain = rand(G.mindrain,G.maxdrain) var/drained = 0 if(PN&&do_after(U,10)) - drained = min(drain, PN.avail) - PN.newload += drained + drained = PN.draw_power(drain) if(drained < drain)//if no power on net, drain apcs for(var/obj/machinery/power/terminal/T in PN.nodes) if(istype(T.master, /obj/machinery/power/apc)) @@ -1083,8 +1082,7 @@ ________________________________________________________________________________ drain = (round((rand(G.mindrain,G.maxdrain))/2)) var/drained = 0 if(PN&&do_after(U,10)) - drained = min(drain, PN.avail) - PN.newload += drained + drained = PN.draw_power(drain) if(drained < drain)//if no power on net, drain apcs for(var/obj/machinery/power/terminal/T in PN.nodes) if(istype(T.master, /obj/machinery/power/apc)) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 119fd2bca0..00d5997814 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -142,9 +142,6 @@ return -/obj/machinery/sleep_console/power_change() - return - // no change - sleeper works without power (you just can't inject more) diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 9196b61a04..9c9cd2b5ab 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -159,15 +159,15 @@ del(src) /obj/machinery/body_scanconsole/power_change() + ..() if(stat & BROKEN) icon_state = "body_scannerconsole-p" - else if(powered()) - icon_state = initial(icon_state) - stat &= ~NOPOWER else - spawn(rand(0, 15)) - src.icon_state = "body_scannerconsole-p" - stat |= NOPOWER + if (stat & NOPOWER) + spawn(rand(0, 15)) + src.icon_state = "body_scannerconsole-p" + else + icon_state = initial(icon_state) /obj/machinery/body_scanconsole var/obj/machinery/bodyscanner/connected diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm index 4df9f2a5a8..ca51a51982 100644 --- a/code/game/machinery/ai_slipper.dm +++ b/code/game/machinery/ai_slipper.dm @@ -14,14 +14,14 @@ req_access = list(access_ai_upload) /obj/machinery/ai_slipper/power_change() + ..() if(stat & BROKEN) return else - if( powered() ) - stat &= ~NOPOWER - else + if (stat & NOPOWER) icon_state = "motion0" - stat |= NOPOWER + else + icon_state = initial(icon_state) /obj/machinery/ai_slipper/proc/setState(var/enabled, var/uses) src.disabled = disabled diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 1cc091ace9..1914e5206c 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -1156,10 +1156,7 @@ table tr:first-child th:first-child { border: none;} return ..() /obj/machinery/alarm/power_change() - if(powered(power_channel)) - stat &= ~NOPOWER - else - stat |= NOPOWER + ..() spawn(rand(0,15)) update_icon() @@ -1367,13 +1364,9 @@ FIRE ALARM return /obj/machinery/firealarm/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER + ..() + spawn(rand(0,15)) update_icon() - else - spawn(rand(0,15)) - stat |= NOPOWER - update_icon() /obj/machinery/firealarm/attack_hand(mob/user as mob) if(user.stat || stat & (NOPOWER|BROKEN)) diff --git a/code/game/machinery/computer/power.dm b/code/game/machinery/computer/power.dm index b3b017565c..40b3783b60 100644 --- a/code/game/machinery/computer/power.dm +++ b/code/game/machinery/computer/power.dm @@ -127,15 +127,14 @@ /obj/machinery/power/monitor/power_change() - + ..() if(stat & BROKEN) icon_state = "broken" else - if( powered() ) - icon_state = initial(icon_state) - stat &= ~NOPOWER - else + if (stat & NOPOWER) spawn(rand(0, 15)) src.icon_state = "c_unpowered" - stat |= NOPOWER + else + icon_state = initial(icon_state) + diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 05a5fc1324..b02cffcee5 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -14,6 +14,10 @@ var/net_id var/list/areas_added var/list/users_to_open + + power_channel = ENVIRON + use_power = 1 + idle_power_usage = 5 /obj/machinery/door/firedoor/New() . = ..() @@ -66,15 +70,6 @@ attack_hand(M) return 0 - -/obj/machinery/door/firedoor/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER - else - stat |= NOPOWER - return - - /obj/machinery/door/firedoor/attack_hand(mob/user as mob) add_fingerprint(user) if(operating) @@ -101,6 +96,9 @@ if(user.stat || user.stunned || user.weakened || user.paralysis || (!user.canmove && !isAI(user)) || (get_dist(src, user) > 1 && !isAI(user))) user << "Sorry, you must remain able bodied and close to \the [src] in order to use it." return + if(density && (stat & (BROKEN|NOPOWER))) //can still close without power + user << "\The [src] is not functioning, you'll have to force it open manually." + return var/needs_to_close = 0 if(density) @@ -163,10 +161,10 @@ else user.visible_message("\red \The [user] forces \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \a [C]!",\ "You force \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \the [C]!",\ - "You hear metal strain and groan, and a door [density ? "open" : "close"].") + "You hear metal strain and groan, and a door [density ? "opening" : "closing"].") if(density) spawn(0) - open() + open(1) else spawn(0) close() @@ -175,7 +173,7 @@ /obj/machinery/door/firedoor/proc/latetoggle() - if(operating || stat & NOPOWER || !nextstate) + if(operating || !nextstate) return switch(nextstate) if(OPEN) @@ -190,7 +188,12 @@ latetoggle() return ..() -/obj/machinery/door/firedoor/open() +/obj/machinery/door/firedoor/open(var/forced = 0) + if (!forced) + if (stat & BROKEN|NOPOWER) + return //needs power to open unless it was forced + else + use_power(360) latetoggle() return ..() diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 8648b33d82..c6744ef96a 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -44,12 +44,11 @@ var/list/doppler_arrays = list() /obj/machinery/doppler_array/power_change() + ..() if(stat & BROKEN) icon_state = "[initial(icon_state)]-broken" else - if( powered() ) + if( !(stat & NOPOWER) ) icon_state = initial(icon_state) - stat &= ~NOPOWER else - icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER \ No newline at end of file + icon_state = "[initial(icon_state)]-off" \ No newline at end of file diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 88c72ec198..cf05308e40 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -28,12 +28,11 @@ src.sd_SetLuminosity(2) */ /obj/machinery/flasher/power_change() - if ( powered() ) - stat &= ~NOPOWER + ..() + if ( !(stat & NOPOWER) ) icon_state = "[base_state]1" // src.sd_SetLuminosity(2) else - stat |= ~NOPOWER icon_state = "[base_state]1-p" // src.sd_SetLuminosity(0) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 56d71e1e0f..26172431f4 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -153,12 +153,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ active_power_usage = 100 var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise. -/obj/machinery/hologram/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= ~NOPOWER - //Destruction procs. /obj/machinery/hologram/ex_act(severity) switch(severity) diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 2f443fdac1..dcc67a5af2 100755 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -38,6 +38,7 @@ icon_state = "igniter[on]" /obj/machinery/igniter/power_change() + ..() if(!( stat & NOPOWER) ) icon_state = "igniter[src.on]" else @@ -60,12 +61,12 @@ ..() /obj/machinery/sparker/power_change() - if ( powered() && disable == 0 ) - stat &= ~NOPOWER + ..() + if ( !(stat & NOPOWER) && disable == 0 ) + icon_state = "[base_state]" // src.sd_SetLuminosity(2) else - stat |= ~NOPOWER icon_state = "[base_state]-p" // src.sd_SetLuminosity(0) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index b3d3552565..d7db1df37e 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -118,17 +118,16 @@ src.throw_item() /obj/machinery/smartfridge/power_change() - if( powered() ) + ..() + if( !(stat & NOPOWER) ) src.ispowered = 1 - stat &= ~NOPOWER if(!isbroken) icon_state = icon_on else spawn(rand(0, 15)) - src.ispowered = 0 - stat |= NOPOWER - if(!isbroken) - icon_state = icon_off + src.ispowered = 0 + if(!isbroken) + icon_state = icon_off /******************* * Item Adding diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index fba4927947..114d24e57b 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -138,14 +138,13 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co /obj/machinery/newscaster/power_change() if(isbroken) //Broken shit can't be powered. return - if( src.powered() ) + ..() + if( !(stat & NOPOWER) ) src.ispowered = 1 - stat &= ~NOPOWER src.update_icon() else spawn(rand(0, 15)) src.ispowered = 0 - stat |= NOPOWER src.update_icon() diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 8107e23cc5..b7a9a781d8 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -264,10 +264,12 @@ Status: []
"}, if(!anchored) icon_state = "turretCover" return + + ..() if(stat & BROKEN) icon_state = "[lasercolor]destroyed_target_prism" else - if( powered() ) + if( !(stat & NOPOWER) ) if (on) if (installation == /obj/item/weapon/gun/energy/laser || installation == /obj/item/weapon/gun/energy/pulse_rifle) // laser guns and pulse rifles have an orange icon @@ -277,11 +279,9 @@ Status: []
"}, icon_state = "[lasercolor]target_prism" else icon_state = "[lasercolor]grey_target_prism" - stat &= ~NOPOWER else spawn(rand(0, 15)) src.icon_state = "[lasercolor]grey_target_prism" - stat |= NOPOWER diff --git a/code/game/machinery/records_scanner.dm b/code/game/machinery/records_scanner.dm index 370e2f3843..af74c7c941 100644 --- a/code/game/machinery/records_scanner.dm +++ b/code/game/machinery/records_scanner.dm @@ -28,13 +28,12 @@ obj/machinery/scanner/New() use_power(50) /obj/machinery/scanner/power_change() - if(!powered()) + ..() + if(stat & NOPOWER) spawn(rand(0, 15)) icon_state = "scanner_off" - stat |= NOPOWER else icon_state = "scanner_idle" - stat &= ~NOPOWER obj/machinery/scanner/attack_hand(mob/living/carbon/human/user) if(stat & NOPOWER) diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm index e7994763dd..bf02e31fdd 100644 --- a/code/game/machinery/robot_fabricator.dm +++ b/code/game/machinery/robot_fabricator.dm @@ -34,12 +34,6 @@ else user << "The robot part maker is full. Please remove metal from the robot part maker in order to insert more." -/obj/machinery/robotic_fabricator/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= NOPOWER - /obj/machinery/robotic_fabricator/attack_paw(user as mob) return src.attack_hand(user) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm deleted file mode 100644 index 439d31d57d..0000000000 --- a/code/game/machinery/shieldgen.dm +++ /dev/null @@ -1,630 +0,0 @@ -/obj/machinery/shield - name = "Emergency energy shield" - desc = "An energy shield used to contain hull breaches." - icon = 'icons/effects/effects.dmi' - icon_state = "shield-old" - density = 1 - opacity = 0 - anchored = 1 - unacidable = 1 - var/const/max_health = 200 - var/health = max_health //The shield can only take so much beating (prevents perma-prisons) - -/obj/machinery/shield/New() - src.dir = pick(1,2,3,4) - ..() - update_nearby_tiles(need_rebuild=1) - -/obj/machinery/shield/Del() - opacity = 0 - density = 0 - update_nearby_tiles() - ..() - -/obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height, air_group) - if(!height || air_group) return 0 - else return ..() - -//Looks like copy/pasted code... I doubt 'need_rebuild' is even used here - Nodrak -/obj/machinery/shield/proc/update_nearby_tiles(need_rebuild) - if(!air_master) - return 0 - - air_master.mark_for_update(get_turf(src)) - - return 1 - - -/obj/machinery/shield/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(!istype(W)) return - - //Calculate damage - var/aforce = W.force - if(W.damtype == BRUTE || W.damtype == BURN) - src.health -= aforce - - //Play a fitting sound - playsound(src.loc, 'sound/effects/EMPulse.ogg', 75, 1) - - - if (src.health <= 0) - visible_message("\blue The [src] dissipates!") - del(src) - return - - opacity = 1 - spawn(20) if(src) opacity = 0 - - ..() - -/obj/machinery/shield/meteorhit() - src.health -= max_health*0.75 //3/4 health as damage - - if(src.health <= 0) - visible_message("\blue The [src] dissipates!") - del(src) - return - - opacity = 1 - spawn(20) if(src) opacity = 0 - return - -/obj/machinery/shield/bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <=0) - visible_message("\blue The [src] dissipates!") - del(src) - return - opacity = 1 - spawn(20) if(src) opacity = 0 - -/obj/machinery/shield/ex_act(severity) - switch(severity) - if(1.0) - if (prob(75)) - del(src) - if(2.0) - if (prob(50)) - del(src) - if(3.0) - if (prob(25)) - del(src) - return - -/obj/machinery/shield/emp_act(severity) - switch(severity) - if(1) - del(src) - if(2) - if(prob(50)) - del(src) - -/obj/machinery/shield/blob_act() - del(src) - - -/obj/machinery/shield/hitby(AM as mob|obj) - //Let everyone know we've been hit! - visible_message("\red [src] was hit by [AM].") - - //Super realistic, resource-intensive, real-time damage calculations. - var/tforce = 0 - if(ismob(AM)) - tforce = 40 - else - tforce = AM:throwforce - - src.health -= tforce - - //This seemed to be the best sound for hitting a force field. - playsound(src.loc, 'sound/effects/EMPulse.ogg', 100, 1) - - //Handle the destruction of the shield - if (src.health <= 0) - visible_message("\blue The [src] dissipates!") - del(src) - return - - //The shield becomes dense to absorb the blow.. purely asthetic. - opacity = 1 - spawn(20) if(src) opacity = 0 - - ..() - return - - - -/obj/machinery/shieldgen - name = "Emergency shield projector" - desc = "Used to seal minor hull breaches." - icon = 'icons/obj/objects.dmi' - icon_state = "shieldoff" - density = 1 - opacity = 0 - anchored = 0 - pressure_resistance = 2*ONE_ATMOSPHERE - req_access = list(access_engine) - var/const/max_health = 100 - var/health = max_health - var/active = 0 - var/malfunction = 0 //Malfunction causes parts of the shield to slowly dissapate - var/list/deployed_shields = list() - var/is_open = 0 //Whether or not the wires are exposed - var/locked = 0 - -/obj/machinery/shieldgen/Del() - for(var/obj/machinery/shield/shield_tile in deployed_shields) - del(shield_tile) - ..() - - -/obj/machinery/shieldgen/proc/shields_up() - if(active) return 0 //If it's already turned on, how did this get called? - - src.active = 1 - update_icon() - - for(var/turf/target_tile in range(2, src)) - if (istype(target_tile,/turf/space) && !(locate(/obj/machinery/shield) in target_tile)) - if (malfunction && prob(33) || !malfunction) - deployed_shields += new /obj/machinery/shield(target_tile) - -/obj/machinery/shieldgen/proc/shields_down() - if(!active) return 0 //If it's already off, how did this get called? - - src.active = 0 - update_icon() - - for(var/obj/machinery/shield/shield_tile in deployed_shields) - del(shield_tile) - -/obj/machinery/shieldgen/process() - if(malfunction && active) - if(deployed_shields.len && prob(5)) - del(pick(deployed_shields)) - - return - -/obj/machinery/shieldgen/proc/checkhp() - if(health <= 30) - src.malfunction = 1 - if(health <= 0) - del(src) - update_icon() - return - -/obj/machinery/shieldgen/meteorhit(obj/O as obj) - src.health -= max_health*0.25 //A quarter of the machine's health - if (prob(5)) - src.malfunction = 1 - src.checkhp() - return - -/obj/machinery/shieldgen/ex_act(severity) - switch(severity) - if(1.0) - src.health -= 75 - src.checkhp() - if(2.0) - src.health -= 30 - if (prob(15)) - src.malfunction = 1 - src.checkhp() - if(3.0) - src.health -= 10 - src.checkhp() - return - -/obj/machinery/shieldgen/emp_act(severity) - switch(severity) - if(1) - src.health /= 2 //cut health in half - malfunction = 1 - locked = pick(0,1) - if(2) - if(prob(50)) - src.health *= 0.3 //chop off a third of the health - malfunction = 1 - checkhp() - -/obj/machinery/shieldgen/attack_hand(mob/user as mob) - if(locked) - user << "The machine is locked, you are unable to use it." - return - if(is_open) - user << "The panel must be closed before operating this machine." - return - - if (src.active) - user.visible_message("\blue \icon[src] [user] deactivated the shield generator.", \ - "\blue \icon[src] You deactivate the shield generator.", \ - "You hear heavy droning fade out.") - src.shields_down() - else - if(anchored) - user.visible_message("\blue \icon[src] [user] activated the shield generator.", \ - "\blue \icon[src] You activate the shield generator.", \ - "You hear heavy droning.") - src.shields_up() - else - user << "The device must first be secured to the floor." - return - -/obj/machinery/shieldgen/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/emag)) - malfunction = 1 - update_icon() - - else if(istype(W, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) - if(is_open) - user << "\blue You close the panel." - is_open = 0 - else - user << "\blue You open the panel and expose the wiring." - is_open = 1 - - else if(istype(W, /obj/item/weapon/cable_coil) && malfunction && is_open) - var/obj/item/weapon/cable_coil/coil = W - user << "\blue You begin to replace the wires." - //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage - if(do_after(user, 30)) - if(!src || !coil) return - coil.use(1) - health = max_health - malfunction = 0 - user << "\blue You repair the [src]!" - update_icon() - - else if(istype(W, /obj/item/weapon/wrench)) - if(locked) - user << "The bolts are covered, unlocking this would retract the covers." - return - if(anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue You unsecure the [src] from the floor!" - if(active) - user << "\blue The [src] shuts off!" - src.shields_down() - anchored = 0 - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue You secure the [src] to the floor!" - anchored = 1 - - - else if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) - if(src.allowed(user)) - src.locked = !src.locked - user << "The controls are now [src.locked ? "locked." : "unlocked."]" - else - user << "\red Access denied." - - else - ..() - - -/obj/machinery/shieldgen/update_icon() - if(active) - src.icon_state = malfunction ? "shieldonbr":"shieldon" - else - src.icon_state = malfunction ? "shieldoffbr":"shieldoff" - return - -////FIELD GEN START //shameless copypasta from fieldgen, powersink, and grille -#define maxstoredpower 500 -/obj/machinery/shieldwallgen - name = "Shield Generator" - desc = "A shield generator." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "Shield_Gen" - anchored = 0 - density = 1 - req_access = list(access_teleporter) - var/active = 0 - var/power = 0 - var/state = 0 - var/steps = 0 - var/last_check = 0 - var/check_delay = 10 - var/recalc = 0 - var/locked = 1 - var/destroyed = 0 - var/directwired = 1 -// var/maxshieldload = 200 - var/obj/structure/cable/attached // the attached cable - var/storedpower = 0 - flags = FPRINT | CONDUCT - use_power = 0 - -/obj/machinery/shieldwallgen/proc/power() - if(!anchored) - power = 0 - return 0 - var/turf/T = src.loc - - var/obj/structure/cable/C = T.get_cable_node() - var/datum/powernet/PN - if(C) PN = C.powernet // find the powernet of the connected cable - - if(!PN) - power = 0 - return 0 - - var/surplus = max(PN.avail-PN.load, 0) - var/shieldload = min(rand(50,200), surplus) - if(shieldload==0 && !storedpower) // no cable or no power, and no power stored - power = 0 - return 0 - else - power = 1 // IVE GOT THE POWER! - if(PN) //runtime errors fixer. They were caused by PN.newload trying to access missing network in case of working on stored power. - storedpower += shieldload - PN.newload += shieldload //uses powernet power. -// message_admins("[PN.load]", 1) -// use_power(250) //uses APC power - -/obj/machinery/shieldwallgen/attack_hand(mob/user as mob) - if(state != 1) - user << "\red The shield generator needs to be firmly secured to the floor first." - return 1 - if(src.locked && !istype(user, /mob/living/silicon)) - user << "\red The controls are locked!" - return 1 - if(power != 1) - user << "\red The shield generator needs to be powered by wire underneath." - return 1 - - if(src.active >= 1) - src.active = 0 - icon_state = "Shield_Gen" - - user.visible_message("[user] turned the shield generator off.", \ - "You turn off the shield generator.", \ - "You hear heavy droning fade out.") - for(var/dir in list(1,2,4,8)) src.cleanup(dir) - else - src.active = 1 - icon_state = "Shield_Gen +a" - user.visible_message("[user] turned the shield generator on.", \ - "You turn on the shield generator.", \ - "You hear heavy droning.") - src.add_fingerprint(user) - -/obj/machinery/shieldwallgen/process() - spawn(100) - power() - if(power) - storedpower -= 50 //this way it can survive longer and survive at all - if(storedpower >= maxstoredpower) - storedpower = maxstoredpower - if(storedpower <= 0) - storedpower = 0 -// if(shieldload >= maxshieldload) //there was a loop caused by specifics of process(), so this was needed. -// shieldload = maxshieldload - - if(src.active == 1) - if(!src.state == 1) - src.active = 0 - return - spawn(1) - setup_field(1) - spawn(2) - setup_field(2) - spawn(3) - setup_field(4) - spawn(4) - setup_field(8) - src.active = 2 - if(src.active >= 1) - if(src.power == 0) - src.visible_message("\red The [src.name] shuts down due to lack of power!", \ - "You hear heavy droning fade out") - icon_state = "Shield_Gen" - src.active = 0 - for(var/dir in list(1,2,4,8)) src.cleanup(dir) - -/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0) - var/turf/T = src.loc - var/turf/T2 = src.loc - var/obj/machinery/shieldwallgen/G - var/steps = 0 - var/oNSEW = 0 - - if(!NSEW)//Make sure its ran right - return - - if(NSEW == 1) - oNSEW = 2 - else if(NSEW == 2) - oNSEW = 1 - else if(NSEW == 4) - oNSEW = 8 - else if(NSEW == 8) - oNSEW = 4 - - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator - T = get_step(T2, NSEW) - T2 = T - steps += 1 - if(locate(/obj/machinery/shieldwallgen) in T) - G = (locate(/obj/machinery/shieldwallgen) in T) - steps -= 1 - if(!G.active) - return - G.cleanup(oNSEW) - break - - if(isnull(G)) - return - - T2 = src.loc - - for(var/dist = 0, dist < steps, dist += 1) // creates each field tile - var/field_dir = get_dir(T2,get_step(T2, NSEW)) - T = get_step(T2, NSEW) - T2 = T - var/obj/machinery/shieldwall/CF = new/obj/machinery/shieldwall/(src, G) //(ref to this gen, ref to connected gen) - CF.loc = T - CF.dir = field_dir - - -/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/wrench)) - if(active) - user << "Turn off the field generator first." - return - - else if(state == 0) - state = 1 - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - user << "You secure the external reinforcing bolts to the floor." - src.anchored = 1 - return - - else if(state == 1) - state = 0 - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - user << "You undo the external reinforcing bolts." - src.anchored = 0 - return - - if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (src.allowed(user)) - src.locked = !src.locked - user << "Controls are now [src.locked ? "locked." : "unlocked."]" - else - user << "\red Access denied." - - else - src.add_fingerprint(user) - visible_message("\red The [src.name] has been hit with \the [W.name] by [user.name]!") - -/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW) - var/obj/machinery/shieldwall/F - var/obj/machinery/shieldwallgen/G - var/turf/T = src.loc - var/turf/T2 = src.loc - - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for fields - T = get_step(T2, NSEW) - T2 = T - if(locate(/obj/machinery/shieldwall) in T) - F = (locate(/obj/machinery/shieldwall) in T) - del(F) - - if(locate(/obj/machinery/shieldwallgen) in T) - G = (locate(/obj/machinery/shieldwallgen) in T) - if(!G.active) - break - -/obj/machinery/shieldwallgen/Del() - src.cleanup(1) - src.cleanup(2) - src.cleanup(4) - src.cleanup(8) - ..() - -/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj) - storedpower -= Proj.damage - ..() - return - - -//////////////Containment Field START -/obj/machinery/shieldwall - name = "Shield" - desc = "An energy shield." - icon = 'icons/effects/effects.dmi' - icon_state = "shieldwall" - anchored = 1 - density = 1 - unacidable = 1 - luminosity = 3 - var/needs_power = 0 - var/active = 1 -// var/power = 10 - var/delay = 5 - var/last_active - var/mob/U - var/obj/machinery/shieldwallgen/gen_primary - var/obj/machinery/shieldwallgen/gen_secondary - -/obj/machinery/shieldwall/New(var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B) - ..() - src.gen_primary = A - src.gen_secondary = B - if(A && B) - needs_power = 1 - -/obj/machinery/shieldwall/attack_hand(mob/user as mob) - return - - -/obj/machinery/shieldwall/process() - if(needs_power) - if(isnull(gen_primary)||isnull(gen_secondary)) - del(src) - return - - if(!(gen_primary.active)||!(gen_secondary.active)) - del(src) - return -// - if(prob(50)) - gen_primary.storedpower -= 10 - else - gen_secondary.storedpower -=10 - - -/obj/machinery/shieldwall/bullet_act(var/obj/item/projectile/Proj) - if(needs_power) - var/obj/machinery/shieldwallgen/G - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= Proj.damage - ..() - return - - -/obj/machinery/shieldwall/ex_act(severity) - if(needs_power) - var/obj/machinery/shieldwallgen/G - switch(severity) - if(1.0) //big boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 200 - - if(2.0) //medium boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 50 - - if(3.0) //lil boom - if(prob(50)) - G = gen_primary - else - G = gen_secondary - G.storedpower -= 20 - return - - -/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSGLASS)) - return prob(20) - else - if (istype(mover, /obj/item/projectile)) - return prob(10) - else - return !src.density \ No newline at end of file diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 2db29d4ab0..c21616811e 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -59,14 +59,13 @@ /obj/machinery/suit_storage_unit/power_change() - if( powered() ) + ..() + if( !(stat & NOPOWER) ) src.ispowered = 1 - stat &= ~NOPOWER src.update_icon() else spawn(rand(0, 15)) src.ispowered = 0 - stat |= NOPOWER src.islocked = 0 src.isopen = 1 src.dump_everything() diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 51ccee7fc5..98af795ca8 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -93,10 +93,11 @@ return (popping!=0) /obj/machinery/turret/power_change() + ..() if(stat & BROKEN) icon_state = "grey_target_prism" else - if( powered() ) + if( !(stat & NOPOWER) ) if (src.enabled) if (src.lasers) icon_state = "orange_target_prism" diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 8bcdd60309..1c18c33263 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -23,6 +23,7 @@ use_power = 1 idle_power_usage = 10 + var/vend_power_usage = 150 //actuators and stuff var/active = 1 //No sales pitches if off! var/delay_product_spawn // If set, uses sleep() in product spawn proc (mostly for seeds to retrieve correct names). @@ -511,7 +512,7 @@ src.speak(src.vend_reply) src.last_reply = world.time - use_power(150) //actuators and stuff + use_power(vend_power_usage) //actuators and stuff if (src.icon_vend) //Show the vending animation if needed flick(src.icon_vend,src) spawn(src.vend_delay) @@ -561,16 +562,15 @@ return /obj/machinery/vending/power_change() + ..() if(stat & BROKEN) icon_state = "[initial(icon_state)]-broken" else - if( powered() ) + if( !(stat & NOPOWER) ) icon_state = initial(icon_state) - stat &= ~NOPOWER else spawn(rand(0, 15)) src.icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER //Oh no we're malfunctioning! Dump out some product and break. /obj/machinery/vending/proc/malfunction() @@ -708,6 +708,7 @@ /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine = 5) contraband = list(/obj/item/weapon/reagent_containers/food/drinks/tea = 10) vend_delay = 15 + idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?" product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!" req_access_txt = "25" @@ -725,6 +726,8 @@ icon_state = "coffee" icon_vend = "coffee-vend" vend_delay = 34 + idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. + vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25) contraband = list(/obj/item/weapon/reagent_containers/food/drinks/ice = 10) prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25, /obj/item/weapon/reagent_containers/food/drinks/tea = 25, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25) @@ -763,6 +766,7 @@ /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1, /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1, /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1) + idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. //This one's from bay12 /obj/machinery/vending/cart @@ -802,6 +806,7 @@ /obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2, /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2) contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,/obj/item/weapon/reagent_containers/pill/stox = 4,/obj/item/weapon/reagent_containers/pill/antitox = 6) + idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. //This one's from bay12 @@ -855,6 +860,7 @@ products = list(/obj/item/weapon/reagent_containers/glass/fertilizer/ez = 35,/obj/item/weapon/reagent_containers/glass/fertilizer/l4z = 25,/obj/item/weapon/reagent_containers/glass/fertilizer/rh = 15,/obj/item/weapon/plantspray/pests = 20, /obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/storage/bag/plants = 5) premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5) + idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. /obj/machinery/vending/hydroseeds name = "MegaSeed Servitor" @@ -901,6 +907,7 @@ product_ads = "For Tsar and Country.;Have you fulfilled your nutrition quota today?;Very nice!;We are simple people, for this is all we eat.;If there is a person, there is a problem. If there is no person, then there is no problem." products = list(/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/soda = 30) contraband = list(/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/cola = 20) + idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan. /obj/machinery/vending/tool name = "YouTool" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 4de06df651..cb4be0d942 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -104,6 +104,7 @@ shock_damage *= siemens_coeff if (shock_damage<1) return 0 + src.take_overall_damage(0,shock_damage,used_weapon="Electrocution") //src.burn_skin(shock_damage) //src.adjustFireLoss(shock_damage) //burn_skin will do this for us @@ -117,6 +118,11 @@ Stun(10)//This should work for now, more is really silly and makes you lay there forever // if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff Weaken(10) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, loc) + s.start() + return shock_damage diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm index 3ba05f6332..de504bcf02 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm @@ -19,11 +19,9 @@ ..() /obj/machinery/drone_fabricator/power_change() - if (powered()) - stat &= ~NOPOWER - else + ..() + if (stat & NOPOWER) icon_state = "drone_fab_nopower" - stat |= NOPOWER /obj/machinery/drone_fabricator/process() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index b08345ff5e..d7b3eef7f6 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -37,6 +37,22 @@ /mob/living/silicon/stun_effect_act(var/stun_amount, var/agony_amount) return //immune +/mob/living/silicon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0) + + if (istype(source, /obj/machinery/containment_field)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, loc) + s.start() + + shock_damage *= 0.75 //take reduced damage + take_overall_damage(0, shock_damage) + visible_message("\red [src] was shocked by \the [source]!", \ + "\red Energy pulse detected, system damaged!", \ + "\red You hear an electrical crack") + if(prob(20)) + Stun(2) + return + /mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0) return diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index b76b152284..fa9fb93d55 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1144,7 +1144,8 @@ /obj/machinery/power/apc/add_load(var/amount) if(terminal && terminal.powernet) - terminal.powernet.newload += amount + return terminal.powernet.draw_power(amount) + return 0 /obj/machinery/power/apc/avail() if(terminal) @@ -1176,13 +1177,7 @@ var/last_ch = charging var/excess = surplus() - - if(!src.avail()) - main_status = 0 - else if(excess < 0) - main_status = 1 - else - main_status = 2 + var/power_excess = 0 var/perapc = 0 if(terminal && terminal.powernet) @@ -1195,36 +1190,35 @@ //var/cell_charge = cell.charge var/cell_maxcharge = cell.maxcharge - // draw power from cell as before - - var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell - cell.use(cellused) - - if(excess > 0 || perapc > lastused_total) // if power excess, or enough anyway, recharge the cell - // by the same amount just used - cell.give(cellused) - add_load(cellused/CELLRATE) // add the load used to recharge the cell - - - else // no excess, and not enough per-apc - - if( (cell.charge/CELLRATE+perapc) >= lastused_total) // can we draw enough from cell+grid to cover last usage? - - cell.give(CELLRATE * perapc) //recharge with what we can - add_load(perapc) // so draw what we can from the grid + // try to draw power from the grid + if (!src.avail()) + main_status = 0 + else + var/power_drawn = add_load(perapc) + + //figure out how much power is left over after meeting demand + power_excess = power_drawn - lastused_total + + if (power_excess < 0) //couldn't get enough power from the grid, we will need to take from the power cell. + main_status = 1 charging = 0 + + var/required_power = -power_excess + if( (cell.charge/CELLRATE) >= required_power) // can we draw enough from cell to cover what's left over? + cell.use(required_power*CELLRATE) - else if (autoflag != 0) // not enough power available to run the last tick! - charging = 0 - chargecount = 0 - // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room. - equipment = autoset(equipment, 0) - lighting = autoset(lighting, 0) - environ = autoset(environ, 0) - autoflag = 0 + else if (autoflag != 0) // not enough power available to run the last tick! + chargecount = 0 + // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room. + equipment = autoset(equipment, 0) + lighting = autoset(lighting, 0) + environ = autoset(environ, 0) + autoflag = 0 + + else + main_status = 2 - - // set channels depending on how much charge we have left + // Set channels depending on how much charge we have left // Allow the APC to operate as normal if the cell can charge if(charging && longtermpower < 10) @@ -1267,10 +1261,9 @@ // now trickle-charge the cell if(chargemode && charging == 1 && operating) - if(excess > 0) // check to make sure we have enough to charge - // Max charge is perapc share, capped to cell capacity, or % per second constant (Whichever is smallest) - var/ch = min(perapc*CELLRATE, (cell_maxcharge - cell.charge), (cell_maxcharge*CHARGELEVEL)) - add_load(ch/CELLRATE) // Removes the power we're taking from the grid + if(power_excess > 0) // check to make sure we have enough to charge + // Max charge is available excess power, capped to cell capacity, or % per second constant (Whichever is smallest) + var/ch = min(power_excess*CELLRATE, (cell_maxcharge - cell.charge), (cell_maxcharge*CHARGELEVEL)) cell.give(ch) // actually recharge the cell else @@ -1278,13 +1271,13 @@ chargecount = 0 // show cell as fully charged if so - if(cell.charge >= cell_maxcharge) charging = 2 + //if we have excess power for long enough, think about re-enable charging. if(chargemode) if(!charging) - if(excess > cell_maxcharge*CHARGELEVEL) + if(power_excess*CELLRATE >= cell_maxcharge*CHARGELEVEL) chargecount++ else chargecount = 0 @@ -1320,21 +1313,21 @@ src.updateDialog() // val 0=off, 1=off(auto) 2=on 3=on(auto) -// on 0=off, 1=on, 2=autooff +// on 0=off, 1=auto-on, 2=auto-off /proc/autoset(var/val, var/on) - if(on==0) + if(on==0) // turn things off if(val==2) // if on, return off return 0 else if(val==3) // if auto-on, return auto-off return 1 - else if(on==1) + else if(on==1) // turn things auto-on if(val==1) // if auto-off, return auto-on return 3 - else if(on==2) + else if(on==2) // turn things auto-off if(val==3) // if auto-on, return auto-off return 1 diff --git a/code/modules/power/batteryrack.dm b/code/modules/power/batteryrack.dm index 5f327495a7..e7a46b60fd 100644 --- a/code/modules/power/batteryrack.dm +++ b/code/modules/power/batteryrack.dm @@ -222,8 +222,9 @@ if(charging) if(excess >= 0) // if there's power available, try to charge var/load = min((capacity * 1.5 - charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity + load = add_load(load) // add the load to the terminal side network charge += load * SMESRATE // increase the charge - add_load(load) // add the load to the terminal side network + else // if not enough capacity charging = 0 // stop charging diff --git a/code/modules/power/cable_logic.dm b/code/modules/power/cable_logic.dm index 3a3b6f9180..a6e6e07b2b 100644 --- a/code/modules/power/cable_logic.dm +++ b/code/modules/power/cable_logic.dm @@ -130,7 +130,7 @@ if( !(pn_input.avail >= LOGIC_HIGH)) pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + pn_output.draw_power(LOGIC_HIGH) //Otherwise increase the load to 5 @@ -202,7 +202,7 @@ if( (pn_input1.avail >= LOGIC_HIGH) && (pn_input2.avail >= LOGIC_HIGH) ) pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + pn_output.draw_power(LOGIC_HIGH) //Otherwise increase the load to 5 //OR GATE /obj/machinery/logic/twoinput/or/process() @@ -222,7 +222,7 @@ if( (pn_input1.avail >= LOGIC_HIGH) || (pn_input2.avail >= LOGIC_HIGH) ) pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + pn_output.draw_power(LOGIC_HIGH) //Otherwise increase the load to 5 //XOR GATE /obj/machinery/logic/twoinput/xor/process() @@ -242,7 +242,7 @@ if( (pn_input1.avail >= LOGIC_HIGH) != (pn_input2.avail >= LOGIC_HIGH) ) pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + pn_output.draw_power(LOGIC_HIGH) //Otherwise increase the load to 5 //XNOR GATE (EQUIVALENCE) /obj/machinery/logic/twoinput/xnor/process() @@ -262,7 +262,7 @@ if( (pn_input1.avail >= LOGIC_HIGH) == (pn_input2.avail >= LOGIC_HIGH) ) pn_output.newavail = max(pn_output.avail, LOGIC_HIGH) //Set the output avilable power to 5 or whatever it was before. else - pn_output.newload += LOGIC_HIGH //Otherwise increase the load to 5 + pn_output.draw_power(LOGIC_HIGH) //Otherwise increase the load to 5 #define RELAY_POWER_TRANSFER 2000 //How much power a relay transfers through. @@ -284,7 +284,7 @@ return if(pn_input2.avail >= RELAY_POWER_TRANSFER) - pn_input2.newload += RELAY_POWER_TRANSFER + pn_input2.draw_power(RELAY_POWER_TRANSFER) pn_output.newavail += RELAY_POWER_TRANSFER diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 67f9b2b4ad..2fb3171104 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -20,11 +20,12 @@ /obj/machinery/power/proc/add_load(var/amount) if(powernet) - powernet.newload += amount + return powernet.draw_power(amount) + return 0 /obj/machinery/power/proc/surplus() if(powernet) - return powernet.avail-powernet.load + return powernet.surplus() else return 0 @@ -67,25 +68,23 @@ log_power_update_request(A.master, src) A.master.powerupdate = 2 // Decremented by 2 each GC tick, since it's not auto power change we're going to update power twice. -/obj/machinery/proc/power_change() // called whenever the power settings of the containing area change +//The master_area optional argument can be used to save on a lot of processing if the master area is already known. This is mainly intended for when this proc is called by the master controller. +/obj/machinery/proc/power_change(var/area/master_area = null) // called whenever the power settings of the containing area change // by default, check equipment channel & set flag // can override if needed - if(powered(power_channel)) + var/has_power + if (master_area) + has_power = master_area.powered(power_channel) + else + has_power = powered(power_channel) + + if(has_power) stat &= ~NOPOWER else stat |= NOPOWER return -//This is used by the master controller to update the NOPOWER flag -//This will allow machines to update NOPOWER if they are moved from one area to another. -//Does the same thing as power_change() but is optimized for the master controller. -/obj/machinery/proc/update_powered_status(var/area/master_area) - if(master_area.powered(power_channel)) - stat &= ~NOPOWER - else - stat |= NOPOWER - // the powernet datum // each contiguous network of cables & nodes @@ -402,6 +401,19 @@ error("[S.name] (\ref[S]) had a [S.powernet ? "different (\ref[S.powernet])" : "null"] powernet to our powernet (\ref[src]).") nodes.Remove(S) + +//Returns the amount of available power +/datum/powernet/proc/surplus() + return max(avail - newload, 0) + +//Attempts to draw power from a powernet. Returns the actual amount of power drawn +/datum/powernet/proc/draw_power(var/requested_amount) + var/surplus = max(avail - newload, 0) + var/actual_draw = min(requested_amount, surplus) + newload += actual_draw + + return actual_draw + /datum/powernet/proc/get_electrocute_damage() switch(avail)/* if (1300000 to INFINITY) @@ -551,11 +563,11 @@ var/drained_energy = drained_hp*20 if (source_area) - source_area.use_power(drained_energy/CELLRATE) + source_area.use_power(drained_energy) else if (istype(power_source,/datum/powernet)) - var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts" - PN.newload+=drained_power + //var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts" <<< NO. THIS IS WRONG. CELLRATE DOES NOT CONVERT TO OR FROM JOULES. + PN.draw_power(drained_energy) else if (istype(power_source, /obj/item/weapon/cell)) - cell.use(drained_energy) + cell.use(drained_energy*CELLRATE) //convert to units of charge. return drained_energy diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index 123ed28c9a..2c24eba108 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -56,49 +56,17 @@ if(!FG1 || !FG2) del(src) return 0 - if(iscarbon(user)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, user.loc) - s.start() - + if(isliving(user)) hasShocked = 1 var/shock_damage = min(rand(30,40),rand(30,40)) - user.burn_skin(shock_damage) - user.updatehealth() - user.visible_message("\red [user.name] was shocked by the [src.name]!", \ - "\red You feel a powerful shock course through your body sending you flying!", \ - "\red You hear a heavy electrical crack") + user.electrocute_act(shock_damage, src) - var/stun = min(shock_damage, 15) - user.Stun(stun) - user.Weaken(10) - - user.updatehealth() var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src))) user.throw_at(target, 200, 4) sleep(20) + hasShocked = 0 - return - - else if(issilicon(user)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, user.loc) - s.start() - - hasShocked = 1 - var/shock_damage = rand(15,30) - user.take_overall_damage(0,shock_damage) - user.visible_message("\red [user.name] was shocked by the [src.name]!", \ - "\red Energy pulse detected, system damaged!", \ - "\red You hear an electrical crack") - if(prob(20)) - user.Stun(2) - - sleep(20) - hasShocked = 0 - return - return /obj/machinery/containment_field/proc/set_master(var/master1,var/master2) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index a520cf3166..ce059c757e 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -1,4 +1,5 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 +#define EMITTER_DAMAGE_POWER_TRANSFER 350 //used to transfer power to containment field generators /obj/machinery/power/emitter name = "Emitter" @@ -10,13 +11,15 @@ req_access = list(access_engine_equip) var/id = null - use_power = 0 - idle_power_usage = 10 - active_power_usage = 300 + use_power = 0 //uses powernet power, not APC power + active_power_usage = 30000 //30 kW laser. I guess that means 30 kJ per shot. var/active = 0 var/powered = 0 var/fire_delay = 100 + var/max_burst_delay = 100 + var/min_burst_delay = 20 + var/burst_shots = 3 var/last_shot = 0 var/shot_number = 0 var/state = 0 @@ -104,8 +107,7 @@ return if(((src.last_shot + src.fire_delay) <= world.time) && (src.active == 1)) - if(!active_power_usage || avail(active_power_usage)) - add_load(active_power_usage) + if(surplus() >= active_power_usage && add_load(active_power_usage) >= active_power_usage) //does the laser have enough power to shoot? if(!powered) powered = 1 update_icon() @@ -118,13 +120,19 @@ return src.last_shot = world.time - if(src.shot_number < 3) + if(src.shot_number < burst_shots) src.fire_delay = 2 src.shot_number ++ else - src.fire_delay = rand(20,100) + src.fire_delay = rand(min_burst_delay, max_burst_delay) src.shot_number = 0 + + //need to calculate the power per shot as the emitter doesn't fire continuously. + var/burst_time = (min_burst_delay + max_burst_delay)/2 + 2*(burst_shots-1) + var/power_per_shot = active_power_usage * (burst_time/10) / burst_shots var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) + A.damage = round(power_per_shot/EMITTER_DAMAGE_POWER_TRANSFER) + playsound(src.loc, 'sound/weapons/emitter.ogg', 25, 1) if(prob(35)) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 315068792d..cf339eff30 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -12,7 +12,7 @@ field_generator power level display -Aygar */ -#define field_generator_max_power 250 +#define field_generator_max_power 250000 /obj/machinery/field_generator name = "Field Generator" desc = "A large thermal battery that projects a high amount of energy when powered." @@ -25,12 +25,16 @@ field_generator power level display var/Varedit_start = 0 var/Varpower = 0 var/active = 0 - var/power = 20 // Current amount of power + var/power = 30000 // Current amount of power var/state = 0 var/warming_up = 0 var/list/obj/machinery/containment_field/fields var/list/obj/machinery/field_generator/connected_gens var/clean_up = 0 + + //If keeping field generators powered is hard then increase the emitter active power usage. + var/gen_power_draw = 5500 //power needed per generator + var/field_power_draw = 2000 //power needed per field object /obj/machinery/field_generator/update_icon() @@ -167,8 +171,8 @@ field_generator power level display return 0 /obj/machinery/field_generator/bullet_act(var/obj/item/projectile/Proj) - if(Proj.flag != "bullet") - power += Proj.damage + if(istype(Proj, /obj/item/projectile/beam)) + power += Proj.damage * EMITTER_DAMAGE_POWER_TRANSFER update_icon() return 0 @@ -206,51 +210,44 @@ field_generator power level display if(src.power > field_generator_max_power) src.power = field_generator_max_power - var/power_draw = 2 + var/power_draw = gen_power_draw + for(var/obj/machinery/field_generator/FG in connected_gens) + if (!isnull(FG)) + power_draw += gen_power_draw for (var/obj/machinery/containment_field/F in fields) - if (isnull(F)) - continue - power_draw++ - if(draw_power(round(power_draw/2,1))) + if (!isnull(F)) + power_draw += field_power_draw + power_draw /= 2 //because this will be mirrored for both generators + if(draw_power(round(power_draw)) >= power_draw) return 1 else for(var/mob/M in viewers(src)) - M.show_message("\red The [src.name] shuts down!") + M.show_message("\red \The [src] shuts down!") turn_off() investigate_log("ran out of power and deactivated","singulo") src.power = 0 return 0 -//This could likely be better, it tends to start loopin if you have a complex generator loop setup. Still works well enough to run the engine fields will likely recode the field gens and fields sometime -Mport -/obj/machinery/field_generator/proc/draw_power(var/draw = 0, var/failsafe = 0, var/obj/machinery/field_generator/G = null, var/obj/machinery/field_generator/last = null) - if(Varpower) - return 1 - if((G && G == src) || (failsafe >= 8))//Loopin, set fail - return 0 - else - failsafe++ +//Tries to draw the needed power from our own power reserve, or connected generators if we can. Returns the amount of power we were able to get. +/obj/machinery/field_generator/proc/draw_power(var/draw = 0, var/list/flood_list = list()) + flood_list += src + if(src.power >= draw)//We have enough power src.power -= draw - return 1 - else//Need more power - draw -= src.power - src.power = 0 - for(var/obj/machinery/field_generator/FG in connected_gens) - if(isnull(FG)) - continue - if(FG == last)//We just asked you - continue - if(G)//Another gen is askin for power and we dont have it - if(FG.draw_power(draw,failsafe,G,src))//Can you take the load - return 1 - else - return 0 - else//We are askin another for power - if(FG.draw_power(draw,failsafe,src,src)) - return 1 - else - return 0 - + return draw + + //Need more power + var/actual_draw = src.power //already checked that power < draw + src.power = 0 + + for(var/obj/machinery/field_generator/FG in connected_gens) + if (FG in flood_list) + continue + actual_draw += FG.draw_power(draw - actual_draw, flood_list) //since the flood list reference is shared this actually works. + if (actual_draw >= draw) + return actual_draw + + return actual_draw /obj/machinery/field_generator/proc/start_fields() if(!src.state == 2 || !anchored) diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index a78a964870..c4be677ca5 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -6,7 +6,8 @@ proc emit_particle() 1 power box -the only part of this thing that uses power, can hack to mess with the pa/make it better +the only part of this thing that uses power, can hack to mess with the pa/make it better. +Lies, only the control computer draws power. 1 fuel chamber contains procs for mixing gas and whatever other fuel it uses diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index 12dc2f5f22..0ae6a5c3bb 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -10,7 +10,7 @@ density = 1 use_power = 0 idle_power_usage = 500 - active_power_usage = 10000 + active_power_usage = 70000 //70 kW per unit of strength construction_state = 0 active = 0 dir = 1 @@ -20,6 +20,7 @@ /obj/machinery/particle_accelerator/control_box/New() connected_parts = list() + active_power_usage = initial(active_power_usage) * (strength + 1) ..() @@ -29,7 +30,7 @@ /obj/machinery/particle_accelerator/control_box/update_state() if(construction_state < 3) - use_power = 0 + update_use_power(0) assembled = 0 active = 0 for(var/obj/structure/particle_accelerator/part in connected_parts) @@ -39,7 +40,7 @@ connected_parts = list() return if(!part_scan()) - use_power = 1 + update_use_power(1) active = 0 connected_parts = list() @@ -87,6 +88,7 @@ else if(href_list["scan"]) src.part_scan() else if(href_list["strengthup"]) + var/old_strength = strength strength++ if(strength > 2) strength = 2 @@ -97,8 +99,13 @@ for(var/obj/structure/particle_accelerator/part in connected_parts) part.strength = strength part.update_icon() + + if (strength != old_strength) + active_power_usage = initial(active_power_usage) * (strength + 1) + use_power(0) //update power usage else if(href_list["strengthdown"]) + var/old_strength = strength strength-- if(strength < 0) strength = 0 @@ -107,6 +114,10 @@ for(var/obj/structure/particle_accelerator/part in connected_parts) part.strength = strength part.update_icon() + + if (strength != old_strength) + active_power_usage = initial(active_power_usage) * (strength + 1) + use_power(0) //update power usage src.updateDialog() src.update_icon() return @@ -116,9 +127,9 @@ ..() if(stat & NOPOWER) active = 0 - use_power = 0 + update_use_power(0) else if(!stat && construction_state == 3) - use_power = 1 + update_use_power(1) return @@ -188,13 +199,13 @@ /obj/machinery/particle_accelerator/control_box/proc/toggle_power() src.active = !src.active if(src.active) - src.use_power = 2 + update_use_power(2) for(var/obj/structure/particle_accelerator/part in connected_parts) part.strength = src.strength part.powered = 1 part.update_icon() else - src.use_power = 1 + update_use_power(1) for(var/obj/structure/particle_accelerator/part in connected_parts) part.strength = null part.powered = 0 diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 92e7f8240a..6b782ca33b 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -88,8 +88,8 @@ if(charging) if(excess >= 0) // if there's power available, try to charge var/load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity + load = add_load(load) // add the load to the terminal side network charge += load * SMESRATE // increase the charge - add_load(load) // add the load to the terminal side network else // if not enough capcity charging = 0 // stop charging @@ -186,7 +186,8 @@ /obj/machinery/power/smes/add_load(var/amount) if(terminal && terminal.powernet) - terminal.powernet.newload += amount + return terminal.powernet.draw_power(amount) + return 0 /obj/machinery/power/smes/attack_ai(mob/user) diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 6dff673e1e..1fd0c09008 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -488,12 +488,11 @@ var/list/solars_list = list() /obj/machinery/power/solar_control/power_change() - if(powered()) - stat &= ~NOPOWER + ..() + if(!(stat & NOPOWER)) update_icon() else spawn(rand(0, 15)) - stat |= NOPOWER update_icon() diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm index 3312ff9dee..bb8762dad2 100644 --- a/code/modules/power/tracker.dm +++ b/code/modules/power/tracker.dm @@ -11,7 +11,8 @@ anchored = 1 density = 1 directwired = 1 - use_power = 0 + use_power = 0 // doesn't use APC power + var/power_usage = 500 //W var/sun_angle = 0 // sun angle as set by sun datum @@ -73,10 +74,7 @@ // make sure we can draw power from the powernet /obj/machinery/power/tracker/process() - var/avail = surplus() - - if(avail > 500) - add_load(500) + if(surplus() >= power_usage && add_load(power_usage) >= power_usage) stat &= ~NOPOWER else stat |= NOPOWER diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index ce6017d2b9..8c46f14605 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -34,11 +34,7 @@ nanomanager.update_uis(src) // update all UIs attached to src /obj/machinery/chem_dispenser/power_change() - if(powered()) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - stat |= NOPOWER + ..() nanomanager.update_uis(src) // update all UIs attached to src /obj/machinery/chem_dispenser/process() @@ -316,13 +312,6 @@ del(src) return -/obj/machinery/chem_master/power_change() - if(powered()) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - stat |= NOPOWER - /obj/machinery/chem_master/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob) if(istype(B, /obj/item/weapon/reagent_containers/glass)) @@ -614,18 +603,16 @@ /obj/machinery/computer/pandemic/power_change() - + ..() if(stat & BROKEN) icon_state = (src.beaker?"mixer1_b":"mixer0_b") - else if(powered()) + else if(!(stat & NOPOWER)) icon_state = (src.beaker?"mixer1":"mixer0") - stat &= ~NOPOWER else spawn(rand(0, 15)) src.icon_state = (src.beaker?"mixer1_nopower":"mixer0_nopower") - stat |= NOPOWER /obj/machinery/computer/pandemic/Topic(href, href_list) diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security levels/keycard authentication.dm index 3e9f1e437e..33f40e4193 100644 --- a/code/modules/security levels/keycard authentication.dm +++ b/code/modules/security levels/keycard authentication.dm @@ -45,11 +45,9 @@ broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices /obj/machinery/keycard_auth/power_change() - if(powered(ENVIRON)) - stat &= ~NOPOWER + ..() + if(stat &NOPOWER) icon_state = "auth_off" - else - stat |= NOPOWER /obj/machinery/keycard_auth/attack_hand(mob/user as mob) if(user.stat || stat & (NOPOWER|BROKEN)) diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/circuits_and_designs.dm b/code/modules/shieldgen/circuits_and_designs.dm similarity index 100% rename from code/WorkInProgress/Cael_Aislinn/ShieldGen/circuits_and_designs.dm rename to code/modules/shieldgen/circuits_and_designs.dm diff --git a/code/modules/shieldgen/emergency_shield.dm b/code/modules/shieldgen/emergency_shield.dm new file mode 100644 index 0000000000..7ab3afd006 --- /dev/null +++ b/code/modules/shieldgen/emergency_shield.dm @@ -0,0 +1,348 @@ +/obj/machinery/shield + name = "Emergency energy shield" + desc = "An energy shield used to contain hull breaches." + icon = 'icons/effects/effects.dmi' + icon_state = "shield-old" + density = 1 + opacity = 0 + anchored = 1 + unacidable = 1 + var/const/max_health = 200 + var/health = max_health //The shield can only take so much beating (prevents perma-prisons) + var/shield_generate_power = 7500 //how much power we use when regenerating + var/shield_idle_power = 1500 //how much power we use when just being sustained. + +/obj/machinery/shield/New() + src.dir = pick(1,2,3,4) + ..() + update_nearby_tiles(need_rebuild=1) + +/obj/machinery/shield/Del() + opacity = 0 + density = 0 + update_nearby_tiles() + ..() + +/obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height, air_group) + if(!height || air_group) return 0 + else return ..() + +//Looks like copy/pasted code... I doubt 'need_rebuild' is even used here - Nodrak +/obj/machinery/shield/proc/update_nearby_tiles(need_rebuild) + if(!air_master) + return 0 + + air_master.mark_for_update(get_turf(src)) + + return 1 + + +/obj/machinery/shield/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(!istype(W)) return + + //Calculate damage + var/aforce = W.force + if(W.damtype == BRUTE || W.damtype == BURN) + src.health -= aforce + + //Play a fitting sound + playsound(src.loc, 'sound/effects/EMPulse.ogg', 75, 1) + + + if (src.health <= 0) + visible_message("\blue The [src] dissipates!") + del(src) + return + + opacity = 1 + spawn(20) if(src) opacity = 0 + + ..() + +/obj/machinery/shield/meteorhit() + src.health -= max_health*0.75 //3/4 health as damage + + if(src.health <= 0) + visible_message("\blue The [src] dissipates!") + del(src) + return + + opacity = 1 + spawn(20) if(src) opacity = 0 + return + +/obj/machinery/shield/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <=0) + visible_message("\blue The [src] dissipates!") + del(src) + return + opacity = 1 + spawn(20) if(src) opacity = 0 + +/obj/machinery/shield/ex_act(severity) + switch(severity) + if(1.0) + if (prob(75)) + del(src) + if(2.0) + if (prob(50)) + del(src) + if(3.0) + if (prob(25)) + del(src) + return + +/obj/machinery/shield/emp_act(severity) + switch(severity) + if(1) + del(src) + if(2) + if(prob(50)) + del(src) + +/obj/machinery/shield/blob_act() + del(src) + + +/obj/machinery/shield/hitby(AM as mob|obj) + //Let everyone know we've been hit! + visible_message("\red [src] was hit by [AM].") + + //Super realistic, resource-intensive, real-time damage calculations. + var/tforce = 0 + if(ismob(AM)) + tforce = 40 + else + tforce = AM:throwforce + + src.health -= tforce + + //This seemed to be the best sound for hitting a force field. + playsound(src.loc, 'sound/effects/EMPulse.ogg', 100, 1) + + //Handle the destruction of the shield + if (src.health <= 0) + visible_message("\blue The [src] dissipates!") + del(src) + return + + //The shield becomes dense to absorb the blow.. purely asthetic. + opacity = 1 + spawn(20) if(src) opacity = 0 + + ..() + return + + + +/obj/machinery/shieldgen + name = "Emergency shield projector" + desc = "Used to seal minor hull breaches." + icon = 'icons/obj/objects.dmi' + icon_state = "shieldoff" + density = 1 + opacity = 0 + anchored = 0 + pressure_resistance = 2*ONE_ATMOSPHERE + req_access = list(access_engine) + var/const/max_health = 100 + var/health = max_health + var/active = 0 + var/malfunction = 0 //Malfunction causes parts of the shield to slowly dissapate + var/list/deployed_shields = list() + var/list/regenerating = list() + var/is_open = 0 //Whether or not the wires are exposed + var/locked = 0 + var/check_delay = 60 //periodically recheck if we need to rebuild a shield + use_power = 0 + idle_power_usage = 0 + +/obj/machinery/shieldgen/Del() + for(var/obj/machinery/shield/shield_tile in deployed_shields) + del(shield_tile) + ..() + + +/obj/machinery/shieldgen/proc/shields_up() + if(active) return 0 //If it's already turned on, how did this get called? + + src.active = 1 + update_icon() + + create_shields() + + idle_power_usage = 0 + for(var/obj/machinery/shield/shield_tile in deployed_shields) + idle_power_usage += shield_tile.shield_idle_power + update_use_power(1) + +/obj/machinery/shieldgen/proc/shields_down() + if(!active) return 0 //If it's already off, how did this get called? + + src.active = 0 + update_icon() + + for(var/obj/machinery/shield/shield_tile in deployed_shields) + del(shield_tile) + + update_use_power(0) + +/obj/machinery/shieldgen/proc/create_shields() + for(var/turf/target_tile in range(2, src)) + if (istype(target_tile,/turf/space) && !(locate(/obj/machinery/shield) in target_tile)) + if (malfunction && prob(33) || !malfunction) + var/obj/machinery/shield/S = new/obj/machinery/shield(target_tile) + deployed_shields += S + use_power(S.shield_generate_power) + +/obj/machinery/shieldgen/process() + if (!active) + return + + if(malfunction) + if(deployed_shields.len && prob(5)) + del(pick(deployed_shields)) + else + if (check_delay <= 0) + create_shields() + + var/new_power_usage = 0 + for(var/obj/machinery/shield/shield_tile in deployed_shields) + new_power_usage += shield_tile.shield_idle_power + + if (new_power_usage != idle_power_usage) + idle_power_usage = new_power_usage + use_power(0) + + check_delay = 60 + else + check_delay-- + +/obj/machinery/shieldgen/proc/checkhp() + if(health <= 30) + src.malfunction = 1 + if(health <= 0) + del(src) + update_icon() + return + +/obj/machinery/shieldgen/meteorhit(obj/O as obj) + src.health -= max_health*0.25 //A quarter of the machine's health + if (prob(5)) + src.malfunction = 1 + src.checkhp() + return + +/obj/machinery/shieldgen/ex_act(severity) + switch(severity) + if(1.0) + src.health -= 75 + src.checkhp() + if(2.0) + src.health -= 30 + if (prob(15)) + src.malfunction = 1 + src.checkhp() + if(3.0) + src.health -= 10 + src.checkhp() + return + +/obj/machinery/shieldgen/emp_act(severity) + switch(severity) + if(1) + src.health /= 2 //cut health in half + malfunction = 1 + locked = pick(0,1) + if(2) + if(prob(50)) + src.health *= 0.3 //chop off a third of the health + malfunction = 1 + checkhp() + +/obj/machinery/shieldgen/attack_hand(mob/user as mob) + if(locked) + user << "The machine is locked, you are unable to use it." + return + if(is_open) + user << "The panel must be closed before operating this machine." + return + + if (src.active) + user.visible_message("\blue \icon[src] [user] deactivated the shield generator.", \ + "\blue \icon[src] You deactivate the shield generator.", \ + "You hear heavy droning fade out.") + src.shields_down() + else + if(anchored) + user.visible_message("\blue \icon[src] [user] activated the shield generator.", \ + "\blue \icon[src] You activate the shield generator.", \ + "You hear heavy droning.") + src.shields_up() + else + user << "The device must first be secured to the floor." + return + +/obj/machinery/shieldgen/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/card/emag)) + malfunction = 1 + update_icon() + + else if(istype(W, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + if(is_open) + user << "\blue You close the panel." + is_open = 0 + else + user << "\blue You open the panel and expose the wiring." + is_open = 1 + + else if(istype(W, /obj/item/weapon/cable_coil) && malfunction && is_open) + var/obj/item/weapon/cable_coil/coil = W + user << "\blue You begin to replace the wires." + //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage + if(do_after(user, 30)) + if(!src || !coil) return + coil.use(1) + health = max_health + malfunction = 0 + user << "\blue You repair the [src]!" + update_icon() + + else if(istype(W, /obj/item/weapon/wrench)) + if(locked) + user << "The bolts are covered, unlocking this would retract the covers." + return + if(anchored) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "\blue You unsecure the [src] from the floor!" + if(active) + user << "\blue The [src] shuts off!" + src.shields_down() + anchored = 0 + else + if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "\blue You secure the [src] to the floor!" + anchored = 1 + + + else if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) + if(src.allowed(user)) + src.locked = !src.locked + user << "The controls are now [src.locked ? "locked." : "unlocked."]" + else + user << "\red Access denied." + + else + ..() + + +/obj/machinery/shieldgen/update_icon() + if(active) + src.icon_state = malfunction ? "shieldonbr":"shieldon" + else + src.icon_state = malfunction ? "shieldoffbr":"shieldoff" + return \ No newline at end of file diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm b/code/modules/shieldgen/energy_field.dm similarity index 92% rename from code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm rename to code/modules/shieldgen/energy_field.dm index a8bda3d14f..06dd2bdade 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/energy_field.dm +++ b/code/modules/shieldgen/energy_field.dm @@ -1,59 +1,61 @@ - -//---------- actual energy field - -/obj/effect/energy_field - name = "energy field" - desc = "Impenetrable field of energy, capable of blocking anything as long as it's active." - icon = 'code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi' - icon_state = "shieldsparkles" - anchored = 1 - layer = 4.1 //just above mobs - density = 0 - invisibility = 101 - var/strength = 0 - var/ticks_recovering = 10 - -/obj/effect/energy_field/ex_act(var/severity) - Stress(0.5 + severity) - -/obj/effect/energy_field/bullet_act(var/obj/item/projectile/Proj) - Stress(Proj.damage / 10) - -/obj/effect/energy_field/meteorhit(obj/effect/meteor/M as obj) - if(M) - walk(M,0) - Stress(2) - -/obj/effect/energy_field/proc/Stress(var/severity) - strength -= severity - - //if we take too much damage, drop out - the generator will bring us back up if we have enough power - ticks_recovering = min(ticks_recovering + 2, 10) - if(strength < 1) - invisibility = 101 - density = 0 - ticks_recovering = 10 - strength = 0 - else if(strength >= 1) - invisibility = 0 - density = 1 - -/obj/effect/energy_field/proc/Strengthen(var/severity) - strength += severity - - //if we take too much damage, drop out - the generator will bring us back up if we have enough power - if(strength >= 1) - invisibility = 0 - density = 1 - else if(strength < 1) - invisibility = 101 - density = 0 - -/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) - //Purpose: Determines if the object (or airflow) can pass this atom. - //Called by: Movement, airflow. - //Inputs: The moving atom (optional), target turf, "height" and air group - //Outputs: Boolean if can pass. - - //return (!density || !height || air_group) - return !density + +//---------- actual energy field + +/obj/effect/energy_field + name = "energy field" + desc = "Impenetrable field of energy, capable of blocking anything as long as it's active." + icon = 'icons/obj/machines/shielding.dmi' + icon_state = "shieldsparkles" + anchored = 1 + layer = 4.1 //just above mobs + density = 0 + invisibility = 101 + var/strength = 0 + var/ticks_recovering = 10 + +/obj/effect/energy_field/ex_act(var/severity) + Stress(0.5 + severity) + +/obj/effect/energy_field/bullet_act(var/obj/item/projectile/Proj) + Stress(Proj.damage / 10) + +/obj/effect/energy_field/meteorhit(obj/effect/meteor/M as obj) + if(M) + walk(M,0) + Stress(2) + +/obj/effect/energy_field/proc/Stress(var/severity) + strength -= severity + + //if we take too much damage, drop out - the generator will bring us back up if we have enough power + ticks_recovering = min(ticks_recovering + 2, 10) + if(strength < 1) + invisibility = 101 + density = 0 + ticks_recovering = 10 + strength = 0 + else if(strength >= 1) + invisibility = 0 + density = 1 + +/obj/effect/energy_field/proc/Strengthen(var/severity) + strength += severity + if (strength < 0) + strength = 0 + + //if we take too much damage, drop out - the generator will bring us back up if we have enough power + if(strength >= 1) + invisibility = 0 + density = 1 + else if(strength < 1) + invisibility = 101 + density = 0 + +/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + //Purpose: Determines if the object (or airflow) can pass this atom. + //Called by: Movement, airflow. + //Inputs: The moving atom (optional), target turf, "height" and air group + //Outputs: Boolean if can pass. + + //return (!density || !height || air_group) + return !density diff --git a/code/modules/shieldgen/sheldwallgen.dm b/code/modules/shieldgen/sheldwallgen.dm new file mode 100644 index 0000000000..0c084abdef --- /dev/null +++ b/code/modules/shieldgen/sheldwallgen.dm @@ -0,0 +1,324 @@ +////FIELD GEN START //shameless copypasta from fieldgen, powersink, and grille +/obj/machinery/shieldwallgen + name = "Shield Generator" + desc = "A shield generator." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "Shield_Gen" + anchored = 0 + density = 1 + req_access = list(access_teleporter) + var/active = 0 + var/power = 0 + var/state = 0 + var/steps = 0 + var/last_check = 0 + var/check_delay = 10 + var/recalc = 0 + var/locked = 1 + var/destroyed = 0 + var/directwired = 1 +// var/maxshieldload = 200 + var/obj/structure/cable/attached // the attached cable + var/storedpower = 0 + flags = FPRINT | CONDUCT + //There have to be at least two posts, so these are effectively doubled + var/power_draw = 30000 //30 kW. How much power is drawn from powernet. Increase this to allow the generator to sustain longer shields, at the cost of more power draw. + var/max_stored_power = 50000 //50 kW + use_power = 0 //Draws directly from power net. Does not use APC power. + +/obj/machinery/shieldwallgen/attack_hand(mob/user as mob) + if(state != 1) + user << "\red The shield generator needs to be firmly secured to the floor first." + return 1 + if(src.locked && !istype(user, /mob/living/silicon)) + user << "\red The controls are locked!" + return 1 + if(power != 1) + user << "\red The shield generator needs to be powered by wire underneath." + return 1 + + if(src.active >= 1) + src.active = 0 + icon_state = "Shield_Gen" + + user.visible_message("[user] turned the shield generator off.", \ + "You turn off the shield generator.", \ + "You hear heavy droning fade out.") + for(var/dir in list(1,2,4,8)) src.cleanup(dir) + else + src.active = 1 + icon_state = "Shield_Gen +a" + user.visible_message("[user] turned the shield generator on.", \ + "You turn on the shield generator.", \ + "You hear heavy droning.") + src.add_fingerprint(user) + +/obj/machinery/shieldwallgen/proc/power() + if(!anchored) + power = 0 + return 0 + var/turf/T = src.loc + + var/obj/structure/cable/C = T.get_cable_node() + var/datum/powernet/PN + if(C) PN = C.powernet // find the powernet of the connected cable + + if(!PN) + power = 0 + return 0 + + var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw + shieldload = PN.draw_power(shieldload) //what we actually get + storedpower += shieldload + + //If we're still in the red, then there must not be enough available power to cover our load. + if(storedpower <= 0) + power = 0 + return 0 + + power = 1 // IVE GOT THE POWER! + return 1 + +/obj/machinery/shieldwallgen/process() + spawn(100) + power() + if(power) + storedpower -= 2500 //the generator post itself uses some power + if(storedpower >= max_stored_power) + storedpower = max_stored_power + if(storedpower <= 0) + storedpower = 0 +// if(shieldload >= maxshieldload) //there was a loop caused by specifics of process(), so this was needed. +// shieldload = maxshieldload + + if(src.active == 1) + if(!src.state == 1) + src.active = 0 + return + spawn(1) + setup_field(1) + spawn(2) + setup_field(2) + spawn(3) + setup_field(4) + spawn(4) + setup_field(8) + src.active = 2 + if(src.active >= 1) + if(src.power == 0) + src.visible_message("\red The [src.name] shuts down due to lack of power!", \ + "You hear heavy droning fade out") + icon_state = "Shield_Gen" + src.active = 0 + for(var/dir in list(1,2,4,8)) src.cleanup(dir) + +/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0) + var/turf/T = src.loc + var/turf/T2 = src.loc + var/obj/machinery/shieldwallgen/G + var/steps = 0 + var/oNSEW = 0 + + if(!NSEW)//Make sure its ran right + return + + if(NSEW == 1) + oNSEW = 2 + else if(NSEW == 2) + oNSEW = 1 + else if(NSEW == 4) + oNSEW = 8 + else if(NSEW == 8) + oNSEW = 4 + + for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator + T = get_step(T2, NSEW) + T2 = T + steps += 1 + if(locate(/obj/machinery/shieldwallgen) in T) + G = (locate(/obj/machinery/shieldwallgen) in T) + steps -= 1 + if(!G.active) + return + G.cleanup(oNSEW) + break + + if(isnull(G)) + return + + T2 = src.loc + + for(var/dist = 0, dist < steps, dist += 1) // creates each field tile + var/field_dir = get_dir(T2,get_step(T2, NSEW)) + T = get_step(T2, NSEW) + T2 = T + var/obj/machinery/shieldwall/CF = new/obj/machinery/shieldwall/(src, G) //(ref to this gen, ref to connected gen) + CF.loc = T + CF.dir = field_dir + + +/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/wrench)) + if(active) + user << "Turn off the field generator first." + return + + else if(state == 0) + state = 1 + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + user << "You secure the external reinforcing bolts to the floor." + src.anchored = 1 + return + + else if(state == 1) + state = 0 + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + user << "You undo the external reinforcing bolts." + src.anchored = 0 + return + + if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (src.allowed(user)) + src.locked = !src.locked + user << "Controls are now [src.locked ? "locked." : "unlocked."]" + else + user << "\red Access denied." + + else + src.add_fingerprint(user) + visible_message("\red The [src.name] has been hit with \the [W.name] by [user.name]!") + +/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW) + var/obj/machinery/shieldwall/F + var/obj/machinery/shieldwallgen/G + var/turf/T = src.loc + var/turf/T2 = src.loc + + for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for fields + T = get_step(T2, NSEW) + T2 = T + if(locate(/obj/machinery/shieldwall) in T) + F = (locate(/obj/machinery/shieldwall) in T) + del(F) + + if(locate(/obj/machinery/shieldwallgen) in T) + G = (locate(/obj/machinery/shieldwallgen) in T) + if(!G.active) + break + +/obj/machinery/shieldwallgen/Del() + src.cleanup(1) + src.cleanup(2) + src.cleanup(4) + src.cleanup(8) + ..() + +/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj) + storedpower -= 400 * Proj.damage + ..() + return + + +//////////////Containment Field START +/obj/machinery/shieldwall + name = "Shield" + desc = "An energy shield." + icon = 'icons/effects/effects.dmi' + icon_state = "shieldwall" + anchored = 1 + density = 1 + unacidable = 1 + luminosity = 3 + var/needs_power = 0 + var/active = 1 +// var/power = 10 + var/delay = 5 + var/last_active + var/mob/U + var/obj/machinery/shieldwallgen/gen_primary + var/obj/machinery/shieldwallgen/gen_secondary + var/power_usage = 2500 //how much power it takes to sustain the shield + var/generate_power_usage = 7500 //how much power it takes to start up the shield + +/obj/machinery/shieldwall/New(var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B) + ..() + src.gen_primary = A + src.gen_secondary = B + if(A && B && A.active && B.active) + needs_power = 1 + if(prob(50)) + A.storedpower -= generate_power_usage + else + B.storedpower -= generate_power_usage + else + del(src) //need at least two generator posts + +/obj/machinery/shieldwall/attack_hand(mob/user as mob) + return + + +/obj/machinery/shieldwall/process() + if(needs_power) + if(isnull(gen_primary)||isnull(gen_secondary)) + del(src) + return + + if(!(gen_primary.active)||!(gen_secondary.active)) + del(src) + return + + if(prob(50)) + gen_primary.storedpower -= power_usage + else + gen_secondary.storedpower -= power_usage + + +/obj/machinery/shieldwall/bullet_act(var/obj/item/projectile/Proj) + if(needs_power) + var/obj/machinery/shieldwallgen/G + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 400 * Proj.damage + ..() + return + + +/obj/machinery/shieldwall/ex_act(severity) + if(needs_power) + var/obj/machinery/shieldwallgen/G + switch(severity) + if(1.0) //big boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 120000 + + if(2.0) //medium boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 30000 + + if(3.0) //lil boom + if(prob(50)) + G = gen_primary + else + G = gen_secondary + G.storedpower -= 12000 + return + + +/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 1 + + if(istype(mover) && mover.checkpass(PASSGLASS)) + return prob(20) + else + if (istype(mover, /obj/item/projectile)) + return prob(10) + else + return !src.density \ No newline at end of file diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm b/code/modules/shieldgen/shield_capacitor.dm similarity index 73% rename from code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm rename to code/modules/shieldgen/shield_capacitor.dm index b95c0ffb6f..6bfc5b664f 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm +++ b/code/modules/shieldgen/shield_capacitor.dm @@ -5,22 +5,18 @@ /obj/machinery/shield_capacitor name = "shield capacitor" desc = "Machine that charges a shield generator." - icon = 'code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi' + icon = 'icons/obj/machines/shielding.dmi' icon_state = "capacitor" - var/active = 1 + var/active = 0 density = 1 - var/stored_charge = 0 + var/stored_charge = 0 //not to be confused with power cell charge, this is in Joules + var/last_stored_charge = 0 var/time_since_fail = 100 - var/max_charge = 5e6 - var/charge_limit = 200000 + var/max_charge = 8e6 //8 MJ + var/max_charge_rate = 400000 //400 kW var/locked = 0 - // - use_power = 1 //0 use nothing - //1 use idle power - //2 use active power - idle_power_usage = 10 - active_power_usage = 100 - var/charge_rate = 100 + use_power = 0 //doesn't use APC power + var/charge_rate = 100000 //100 kW var/obj/machinery/shield_gen/owned_gen /obj/machinery/shield_capacitor/New() @@ -75,12 +71,12 @@ return src.attack_hand(user) /obj/machinery/shield_capacitor/attack_hand(mob/user) - if(stat & (NOPOWER|BROKEN)) + if(stat & (BROKEN)) return interact(user) /obj/machinery/shield_capacitor/interact(mob/user) - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) + if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN)) ) if (!istype(user, /mob/living/silicon)) user.unset_machine() user << browse(null, "window=shield_capacitor") @@ -90,13 +86,13 @@ t += "Swipe your ID card to begin." else t += "This capacitor is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
" - t += "[time_since_fail > 2 ? "Charging stable." : "Warning, low charge!"]
" - t += "Charge: [stored_charge] Watts ([100 * stored_charge/max_charge]%)
" - t += "Charge rate: \ + t += "Capacitor Status: [time_since_fail > 2 ? "OK." : "Discharging!"]
" + t += "Stored Energy: [round(stored_charge/1000, 0.1)] kJ ([100 * round(stored_charge/max_charge, 0.1)]%)
" + t += "Charge Rate: \ \[----\] \ \[---\] \ \[--\] \ - \[-\][charge_rate] Watts/sec \ + \[-\][charge_rate] W \ \[+\] \ \[++\] \ \[+++\] \ @@ -109,20 +105,25 @@ user.set_machine(src) /obj/machinery/shield_capacitor/process() - // - if(active) - use_power = 2 - if(stored_charge + charge_rate > max_charge) - active_power_usage = max_charge - stored_charge - else - active_power_usage = charge_rate - stored_charge += active_power_usage - else - use_power = 1 + if (!anchored) + active = 0 + + //see if we can connect to a power net. + var/datum/powernet/PN + var/turf/T = src.loc + var/obj/structure/cable/C = T.get_cable_node() + if (C) + PN = C.powernet + + if (PN) + var/power_draw = between(0, max_charge - stored_charge, charge_rate) //what we are trying to draw + power_draw = PN.draw_power(power_draw) //what we actually get + stored_charge += power_draw time_since_fail++ - if(stored_charge < active_power_usage * 1.5) - time_since_fail = 0 + if(stored_charge < last_stored_charge) + time_since_fail = 0 //losing charge faster than we can draw from PN + last_stored_charge = stored_charge /obj/machinery/shield_capacitor/Topic(href, href_list[]) ..() @@ -131,34 +132,20 @@ usr.unset_machine() return if( href_list["toggle"] ) + if(!active && !anchored) + usr << "\red The [src] needs to be firmly secured to the floor first." + return active = !active - if(active) - use_power = 2 - else - use_power = 1 if( href_list["charge_rate"] ) - charge_rate += text2num(href_list["charge_rate"]) - if(charge_rate > charge_limit) - charge_rate = charge_limit - else if(charge_rate < 0) - charge_rate = 0 - // + charge_rate = between(10000, charge_rate + text2num(href_list["charge_rate"]), max_charge_rate) + updateDialog() /obj/machinery/shield_capacitor/power_change() if(stat & BROKEN) icon_state = "broke" else - if( powered() ) - if (src.active) - icon_state = "capacitor" - else - icon_state = "capacitor" - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - src.icon_state = "capacitor" - stat |= NOPOWER + ..() /obj/machinery/shield_capacitor/verb/rotate() set name = "Rotate capacitor clockwise" diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm similarity index 56% rename from code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm rename to code/modules/shieldgen/shield_gen.dm index e6f206a21e..b330b7cac9 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -6,30 +6,29 @@ //explosion damage is cumulative. if a tile is in range of light, medium and heavy damage, it will take a hit from all three /obj/machinery/shield_gen - name = "shield generator" + name = "bubble shield generator" desc = "Machine that generates an impenetrable field of energy when activated." - icon = 'code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi' + icon = 'icons/obj/machines/shielding.dmi' icon_state = "generator0" var/active = 0 var/field_radius = 3 + var/max_field_radius = 100 var/list/field density = 1 var/locked = 0 var/average_field_strength = 0 var/strengthen_rate = 0.2 - var/max_strengthen_rate = 0.2 + var/max_strengthen_rate = 0.5 //the maximum rate that the generator can increase the average field strength + var/dissipation_rate = 0.030 //the percentage of the shield strength that needs to be replaced each second + var/min_dissipation = 0.1 //will dissipate by at least this rate in renwicks per field tile (otherwise field would never dissipate completely as dissipation is a percentage) var/powered = 0 var/check_powered = 1 var/obj/machinery/shield_capacitor/owned_capacitor var/target_field_strength = 10 + var/max_field_strength = 10 var/time_since_fail = 100 - var/energy_conversion_rate = 0.01 //how many renwicks per watt? - // - use_power = 1 //0 use nothing - //1 use idle power - //2 use active power - idle_power_usage = 20 - active_power_usage = 100 + var/energy_conversion_rate = 0.0002 //how many renwicks per watt? + use_power = 0 //doesn't use APC power /obj/machinery/shield_gen/New() spawn(10) @@ -88,12 +87,12 @@ return src.attack_hand(user) /obj/machinery/shield_gen/attack_hand(mob/user) - if(stat & (NOPOWER|BROKEN)) + if(stat & (BROKEN)) return interact(user) /obj/machinery/shield_gen/interact(mob/user) - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) + if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN)) ) if (!istype(user, /mob/living/silicon)) user.unset_machine() user << browse(null, "window=shield_generator") @@ -104,29 +103,29 @@ else t += "[owned_capacitor ? "Charge capacitor connected." : "Unable to locate charge capacitor!"]
" t += "This generator is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
" - t += "[time_since_fail > 2 ? "Field is stable." : "Warning, field is unstable!"]
" - t += "Coverage radius (restart required): \ + t += "Field Status: [time_since_fail > 2 ? "Stable" : "Unstable"]
" + t += "Coverage Radius (restart required): \ --- \ -- \ - \ - [field_radius * 2]m \ + [field_radius] m \ + \ ++ \ +++
" - t += "Overall field strength: [average_field_strength] Renwicks ([target_field_strength ? 100 * average_field_strength / target_field_strength : "NA"]%)
" - t += "Upkeep energy: [field.len * average_field_strength / energy_conversion_rate] Watts/sec
" - t += "Charge rate: -- \ - [strengthen_rate] Renwicks/sec \ + t += "Overall Field Strength: [round(average_field_strength, 0.01)] Renwick ([target_field_strength ? round(100 * average_field_strength / target_field_strength, 0.1) : "NA"]%)
" + t += "Upkeep Power: [round(field.len * max(average_field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate)] W
" + t += "Charge Rate: -- \ + [strengthen_rate] Renwick/s \ ++
" - t += "Additional energy required to charge: [field.len * strengthen_rate / energy_conversion_rate] Watts/sec
" - t += "Maximum field strength: \ - \[min\] \ - -- \ + t += "Shield Generation Power: [round(field.len * min(strengthen_rate, target_field_strength - average_field_strength) / energy_conversion_rate)] W
" + t += "Maximum Field Strength: \ + \[min\] \ + -- \ - \ - [target_field_strength] Renwicks \ + [target_field_strength] Renwick \ + \ - ++ \ - \[max\]
" + ++ \ + \[max\]
" t += "
" t += "Refresh " t += "Close
" @@ -134,34 +133,39 @@ user.set_machine(src) /obj/machinery/shield_gen/process() + if (!anchored && active) + toggle() + + average_field_strength = max(average_field_strength, 0) if(field.len) time_since_fail++ - var/stored_renwicks = 0 - var/target_strength_this_update = min(strengthen_rate + max(average_field_strength, 0), target_field_strength) + var/total_renwick_increase = 0 //the amount of renwicks that the generator can add this tick, over the entire field + var/renwick_upkeep_per_field = max(average_field_strength * dissipation_rate, min_dissipation) - if(active && owned_capacitor) - var/required_energy = field.len * target_strength_this_update / energy_conversion_rate + //figure out how much energy we need to draw from the capacitor + if(active && owned_capacitor && owned_capacitor.active) + var/target_renwick_increase = min(target_field_strength - average_field_strength, strengthen_rate) + renwick_upkeep_per_field //per field tile + + var/required_energy = field.len * target_renwick_increase / energy_conversion_rate var/assumed_charge = min(owned_capacitor.stored_charge, required_energy) - stored_renwicks = assumed_charge * energy_conversion_rate + total_renwick_increase = assumed_charge * energy_conversion_rate owned_capacitor.stored_charge -= assumed_charge - - average_field_strength = 0 - var/renwicks_per_field = 0 - if(stored_renwicks != 0) - renwicks_per_field = stored_renwicks / field.len - + else + renwick_upkeep_per_field = max(renwick_upkeep_per_field, 0.5) + + var/renwick_increase_per_field = total_renwick_increase/field.len //per field tile + + average_field_strength = 0 //recalculate the average field strength for(var/obj/effect/energy_field/E in field) - if(active && renwicks_per_field > 0) - var/amount_to_strengthen = min(renwicks_per_field - E.strength, strengthen_rate) - if(E.ticks_recovering > 0 && amount_to_strengthen > 0) - E.Strengthen( min(amount_to_strengthen / 10, 0.1) ) - E.ticks_recovering -= 1 - else - E.Strengthen(amount_to_strengthen) - average_field_strength += E.strength + var/amount_to_strengthen = renwick_increase_per_field - renwick_upkeep_per_field + if(E.ticks_recovering > 0 && amount_to_strengthen > 0) + E.Strengthen( min(amount_to_strengthen / 10, 0.1) ) + E.ticks_recovering -= 1 else - E.Strengthen(-E.strength) + E.Strengthen(amount_to_strengthen) + + average_field_strength += E.strength average_field_strength /= field.len if(average_field_strength < 1) @@ -176,87 +180,29 @@ usr.unset_machine() return else if( href_list["toggle"] ) + if (!active && !anchored) + usr << "\red The [src] needs to be firmly secured to the floor first." + return toggle() else if( href_list["change_radius"] ) - field_radius += text2num(href_list["change_radius"]) - if(field_radius > 200) - field_radius = 200 - else if(field_radius < 0) - field_radius = 0 + field_radius = between(0, field_radius + text2num(href_list["change_radius"]), max_field_radius) else if( href_list["strengthen_rate"] ) - strengthen_rate += text2num(href_list["strengthen_rate"]) - if(strengthen_rate > 1) - strengthen_rate = 1 - else if(strengthen_rate < 0) - strengthen_rate = 0 + strengthen_rate = between(0, strengthen_rate + text2num(href_list["strengthen_rate"]), max_strengthen_rate) else if( href_list["target_field_strength"] ) - target_field_strength += text2num(href_list["target_field_strength"]) - if(target_field_strength > 1000) - target_field_strength = 1000 - else if(target_field_strength < 0) - target_field_strength = 0 - // + target_field_strength = between(1, target_field_strength + text2num(href_list["target_field_strength"]), max_field_strength) + updateDialog() -/obj/machinery/shield_gen/power_change() - if(stat & BROKEN) - icon_state = "broke" - else - if( powered() ) - if (src.active) - icon_state = "generator1" - else - icon_state = "generator0" - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - src.icon_state = "generator0" - stat |= NOPOWER - if (src.active) - toggle() - /obj/machinery/shield_gen/ex_act(var/severity) if(active) toggle() return ..() -/* -/obj/machinery/shield_gen/proc/check_powered() - check_powered = 1 - if(!anchored) - powered = 0 - return 0 - var/turf/T = src.loc - var/obj/structure/cable/C = T.get_cable_node() - var/net - if (C) - net = C.netnum // find the powernet of the connected cable - - if(!net) - powered = 0 - return 0 - var/datum/powernet/PN = powernets[net] // find the powernet. Magic code, voodoo code. - - if(!PN) - powered = 0 - return 0 - var/surplus = max(PN.avail-PN.load, 0) - var/shieldload = min(rand(50,200), surplus) - if(shieldload==0 && !storedpower) // no cable or no power, and no power stored - powered = 0 - return 0 - else - powered = 1 - if(PN) - storedpower += shieldload - PN.newload += shieldload //uses powernet power. - */ - /obj/machinery/shield_gen/proc/toggle() set background = 1 active = !active - power_change() + update_icon() if(active) var/list/covered_turfs = get_shielded_turfs() var/turf/T = get_turf(src) @@ -277,10 +223,37 @@ for(var/mob/M in view(5,src)) M << "\icon[src] You hear heavy droning fade out." +/obj/machinery/shield_gen/update_icon() + if(stat & BROKEN) + icon_state = "broke" + else + if (src.active) + icon_state = "generator1" + else + icon_state = "generator0" + +//TODO MAKE THIS MULTIZ COMPATIBLE //grab the border tiles in a circle around this machine /obj/machinery/shield_gen/proc/get_shielded_turfs() var/list/out = list() - for(var/turf/T in range(field_radius, src)) - if(get_dist(src,T) == field_radius) - out.Add(T) + + var/turf/gen_turf = get_turf(src) + if (!gen_turf) + return + + var/turf/T + for (var/x_offset = -field_radius; x_offset <= field_radius; x_offset++) + T = locate(gen_turf.x + x_offset, gen_turf.y - field_radius, gen_turf.z) + if (T) out += T + + T = locate(gen_turf.x + x_offset, gen_turf.y + field_radius, gen_turf.z) + if (T) out += T + + for (var/y_offset = -field_radius+1; y_offset < field_radius; y_offset++) + T = locate(gen_turf.x - field_radius, gen_turf.y + y_offset, gen_turf.z) + if (T) out += T + + T = locate(gen_turf.x + field_radius, gen_turf.y + y_offset, gen_turf.z) + if (T) out += T + return out diff --git a/code/modules/shieldgen/shield_gen_external.dm b/code/modules/shieldgen/shield_gen_external.dm new file mode 100644 index 0000000000..182339d64e --- /dev/null +++ b/code/modules/shieldgen/shield_gen_external.dm @@ -0,0 +1,27 @@ +//---------- external shield generator +//generates an energy field that loops around any built up area in space (is useless inside) halts movement and airflow, is blocked by walls, windows, airlocks etc + +/obj/machinery/shield_gen/external + name = "hull shield generator" + +/obj/machinery/shield_gen/external/New() + ..() + +//NOT MULTIZ COMPATIBLE +//Search for space turfs within range that are adjacent to a simulated turf. +/obj/machinery/shield_gen/external/get_shielded_turfs() + var/list/out = list() + + var/turf/gen_turf = get_turf(src) + if (!gen_turf) + return + + var/turf/T + for (var/x_offset = -field_radius; x_offset <= field_radius; x_offset++) + for (var/y_offset = -field_radius; y_offset <= field_radius; y_offset++) + T = locate(gen_turf.x + x_offset, gen_turf.y + y_offset, gen_turf.z) + if (istype(T, /turf/space)) + //check neighbors of T + if (locate(/turf/simulated/) in orange(1, T)) + out += T + return out diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi b/icons/obj/machines/shielding.dmi similarity index 100% rename from code/WorkInProgress/Cael_Aislinn/ShieldGen/shielding.dmi rename to icons/obj/machines/shielding.dmi