This commit is contained in:
Hatterhat
2020-01-12 12:39:17 -06:00
945 changed files with 189410 additions and 189403 deletions
+232 -232
View File
@@ -1,232 +1,232 @@
// stored_power += (pulse_strength-RAD_COLLECTOR_EFFICIENCY)*RAD_COLLECTOR_COEFFICIENT
#define RAD_COLLECTOR_EFFICIENCY 80 // radiation needs to be over this amount to get power
#define RAD_COLLECTOR_COEFFICIENT 100
#define RAD_COLLECTOR_STORED_OUT 0.04 // (this*100)% of stored power outputted per tick. Doesn't actualy change output total, lower numbers just means collectors output for longer in absence of a source
#define RAD_COLLECTOR_MINING_CONVERSION_RATE 0.00001 //This is gonna need a lot of tweaking to get right. This is the number used to calculate the conversion of watts to research points per process()
#define RAD_COLLECTOR_OUTPUT min(stored_power, (stored_power*RAD_COLLECTOR_STORED_OUT)+1000) //Produces at least 1000 watts if it has more than that stored
/obj/machinery/power/rad_collector
name = "Radiation Collector Array"
desc = "A device which uses Hawking Radiation and plasma to produce power."
icon = 'icons/obj/singularity.dmi'
icon_state = "ca"
anchored = FALSE
density = TRUE
req_access = list(ACCESS_ENGINE_EQUIP)
// use_power = NO_POWER_USE
max_integrity = 350
integrity_failure = 80
circuit = /obj/item/circuitboard/machine/rad_collector
var/obj/item/tank/internals/plasma/loaded_tank = null
var/stored_power = 0
var/last_push
var/active = 0
var/locked = FALSE
var/drainratio = 1
var/powerproduction_drain = 0.001
var/bitcoinproduction_drain = 0.15
var/bitcoinmining = FALSE
rad_insulation = RAD_EXTREME_INSULATION
/obj/machinery/power/rad_collector/anchored
anchored = TRUE
/obj/machinery/power/rad_collector/Destroy()
return ..()
/obj/machinery/power/rad_collector/process()
if(!loaded_tank)
return
if(!bitcoinmining)
if(!loaded_tank.air_contents.gases[/datum/gas/plasma])
investigate_log("<font color='red'>out of fuel</font>.", INVESTIGATE_SINGULO)
playsound(src, 'sound/machines/ding.ogg', 50, 1)
eject()
else
var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.gases[/datum/gas/plasma])
loaded_tank.air_contents.gases[/datum/gas/plasma] -= 2.7 * gasdrained
loaded_tank.air_contents.gases[/datum/gas/tritium] += 2.7 * gasdrained
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
var/power_produced = RAD_COLLECTOR_OUTPUT
add_avail(power_produced)
stored_power-=power_produced
else if(is_station_level(z) && SSresearch.science_tech)
if(!loaded_tank.air_contents.gases[/datum/gas/tritium] || !loaded_tank.air_contents.gases[/datum/gas/oxygen])
playsound(src, 'sound/machines/ding.ogg', 50, 1)
eject()
else
var/gasdrained = bitcoinproduction_drain*drainratio
loaded_tank.air_contents.gases[/datum/gas/tritium] -= gasdrained
loaded_tank.air_contents.gases[/datum/gas/oxygen] -= gasdrained
loaded_tank.air_contents.gases[/datum/gas/carbon_dioxide] += gasdrained*2
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE)
last_push = stored_power
stored_power = 0
/obj/machinery/power/rad_collector/interact(mob/user)
if(anchored)
if(!src.locked)
toggle_power()
user.visible_message("[user.name] turns the [src.name] [active? "on":"off"].", \
"<span class='notice'>You turn the [src.name] [active? "on":"off"].</span>")
var/fuel
if(loaded_tank)
fuel = loaded_tank.air_contents.gases[/datum/gas/plasma]
investigate_log("turned [active?"<font color='green'>on</font>":"<font color='red'>off</font>"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"<font color='red'>It is empty</font>"].", INVESTIGATE_SINGULO)
return
else
to_chat(user, "<span class='warning'>The controls are locked!</span>")
return
/obj/machinery/power/rad_collector/can_be_unfasten_wrench(mob/user, silent)
if(loaded_tank)
if(!silent)
to_chat(user, "<span class='warning'>Remove the plasma tank first!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/power/rad_collector/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
connect_to_network()
else
disconnect_from_network()
/obj/machinery/power/rad_collector/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/tank/internals/plasma))
if(!anchored)
to_chat(user, "<span class='warning'>[src] needs to be secured to the floor first!</span>")
return TRUE
if(loaded_tank)
to_chat(user, "<span class='warning'>There's already a plasma tank loaded!</span>")
return TRUE
if(panel_open)
to_chat(user, "<span class='warning'>Close the maintenance panel first!</span>")
return TRUE
if(!user.transferItemToLoc(W, src))
return
loaded_tank = W
update_icon()
else if(W.GetID())
if(allowed(user))
if(active)
locked = !locked
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] the controls.</span>")
else
to_chat(user, "<span class='warning'>The controls can only be locked when \the [src] is active!</span>")
else
to_chat(user, "<span class='danger'>Access denied.</span>")
return TRUE
else
return ..()
/obj/machinery/power/rad_collector/wrench_act(mob/living/user, obj/item/I)
default_unfasten_wrench(user, I)
return TRUE
/obj/machinery/power/rad_collector/screwdriver_act(mob/living/user, obj/item/I)
if(..())
return TRUE
if(loaded_tank)
to_chat(user, "<span class='warning'>Remove the plasma tank first!</span>")
else
default_deconstruction_screwdriver(user, icon_state, icon_state, I)
return TRUE
/obj/machinery/power/rad_collector/crowbar_act(mob/living/user, obj/item/I)
if(loaded_tank)
if(locked)
to_chat(user, "<span class='warning'>The controls are locked!</span>")
return TRUE
eject()
return TRUE
if(default_deconstruction_crowbar(I))
return TRUE
to_chat(user, "<span class='warning'>There isn't a tank loaded!</span>")
return TRUE
/obj/machinery/power/rad_collector/multitool_act(mob/living/user, obj/item/I)
if(!is_station_level(z) && !SSresearch.science_tech)
to_chat(user, "<span class='warning'>[src] isn't linked to a research system!</span>")
return TRUE
if(locked)
to_chat(user, "<span class='warning'>[src] is locked!</span>")
return TRUE
if(active)
to_chat(user, "<span class='warning'>[src] is currently active, producing [bitcoinmining ? "research points":"power"].</span>")
return TRUE
bitcoinmining = !bitcoinmining
to_chat(user, "<span class='warning'>You [bitcoinmining ? "enable":"disable"] the research point production feature of [src].</span>")
return TRUE
/obj/machinery/power/rad_collector/analyzer_act(mob/living/user, obj/item/I)
if(loaded_tank)
loaded_tank.analyzer_act(user, I)
/obj/machinery/power/rad_collector/examine(mob/user)
. = ..()
if(active)
if(!bitcoinmining)
. += "<span class='notice'>[src]'s display states that it has stored <b>[DisplayPower(stored_power)]</b>, and is processing <b>[DisplayPower((RAD_COLLECTOR_OUTPUT)*((60 SECONDS)/SSmachines.wait))]</b> per minute. <br>The <b>plasma</b> within it's tank is being irradiated into <b>tritium</b>.</span>"
else
. += "<span class='notice'>[src]'s display states that it's producing a total of <b>[(last_push*RAD_COLLECTOR_MINING_CONVERSION_RATE)*((60 SECONDS)/SSmachines.wait)]</b> research points per minute. <br>The <b>tritium</b> and <b>oxygen</b> within it's tank is being combusted into <b>carbon dioxide</b>.</span>"
else
if(!bitcoinmining)
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Power production mode. Please insert <b>Plasma</b>. Use a multitool to change production modes.\"</span>"
else
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Research point production mode. Please insert <b>Tritium</b> and <b>Oxygen</b>. Use a multitool to change production modes.\"</span>"
/obj/machinery/power/rad_collector/obj_break(damage_flag)
if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1))
eject()
stat |= BROKEN
/obj/machinery/power/rad_collector/proc/eject()
locked = FALSE
var/obj/item/tank/internals/plasma/Z = src.loaded_tank
if (!Z)
return
Z.forceMove(drop_location())
Z.layer = initial(Z.layer)
Z.plane = initial(Z.plane)
src.loaded_tank = null
if(active)
toggle_power()
else
update_icon()
/obj/machinery/power/rad_collector/rad_act(pulse_strength)
. = ..()
if(loaded_tank && active && pulse_strength > RAD_COLLECTOR_EFFICIENCY)
stored_power += (pulse_strength-RAD_COLLECTOR_EFFICIENCY)*RAD_COLLECTOR_COEFFICIENT
/obj/machinery/power/rad_collector/update_icon()
cut_overlays()
if(loaded_tank)
add_overlay("ptank")
if(stat & (NOPOWER|BROKEN))
return
if(active)
add_overlay("on")
/obj/machinery/power/rad_collector/proc/toggle_power()
active = !active
if(active)
icon_state = "ca_on"
flick("ca_active", src)
else
icon_state = "ca"
flick("ca_deactive", src)
update_icon()
return
#undef RAD_COLLECTOR_EFFICIENCY
#undef RAD_COLLECTOR_COEFFICIENT
#undef RAD_COLLECTOR_STORED_OUT
#undef RAD_COLLECTOR_MINING_CONVERSION_RATE
#undef RAD_COLLECTOR_OUTPUT
// stored_power += (pulse_strength-RAD_COLLECTOR_EFFICIENCY)*RAD_COLLECTOR_COEFFICIENT
#define RAD_COLLECTOR_EFFICIENCY 80 // radiation needs to be over this amount to get power
#define RAD_COLLECTOR_COEFFICIENT 100
#define RAD_COLLECTOR_STORED_OUT 0.04 // (this*100)% of stored power outputted per tick. Doesn't actualy change output total, lower numbers just means collectors output for longer in absence of a source
#define RAD_COLLECTOR_MINING_CONVERSION_RATE 0.00001 //This is gonna need a lot of tweaking to get right. This is the number used to calculate the conversion of watts to research points per process()
#define RAD_COLLECTOR_OUTPUT min(stored_power, (stored_power*RAD_COLLECTOR_STORED_OUT)+1000) //Produces at least 1000 watts if it has more than that stored
/obj/machinery/power/rad_collector
name = "Radiation Collector Array"
desc = "A device which uses Hawking Radiation and plasma to produce power."
icon = 'icons/obj/singularity.dmi'
icon_state = "ca"
anchored = FALSE
density = TRUE
req_access = list(ACCESS_ENGINE_EQUIP)
// use_power = NO_POWER_USE
max_integrity = 350
integrity_failure = 80
circuit = /obj/item/circuitboard/machine/rad_collector
var/obj/item/tank/internals/plasma/loaded_tank = null
var/stored_power = 0
var/last_push
var/active = 0
var/locked = FALSE
var/drainratio = 1
var/powerproduction_drain = 0.001
var/bitcoinproduction_drain = 0.15
var/bitcoinmining = FALSE
rad_insulation = RAD_EXTREME_INSULATION
/obj/machinery/power/rad_collector/anchored
anchored = TRUE
/obj/machinery/power/rad_collector/Destroy()
return ..()
/obj/machinery/power/rad_collector/process()
if(!loaded_tank)
return
if(!bitcoinmining)
if(!loaded_tank.air_contents.gases[/datum/gas/plasma])
investigate_log("<font color='red'>out of fuel</font>.", INVESTIGATE_SINGULO)
playsound(src, 'sound/machines/ding.ogg', 50, 1)
eject()
else
var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.gases[/datum/gas/plasma])
loaded_tank.air_contents.gases[/datum/gas/plasma] -= 2.7 * gasdrained
loaded_tank.air_contents.gases[/datum/gas/tritium] += 2.7 * gasdrained
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
var/power_produced = RAD_COLLECTOR_OUTPUT
add_avail(power_produced)
stored_power-=power_produced
else if(is_station_level(z) && SSresearch.science_tech)
if(!loaded_tank.air_contents.gases[/datum/gas/tritium] || !loaded_tank.air_contents.gases[/datum/gas/oxygen])
playsound(src, 'sound/machines/ding.ogg', 50, 1)
eject()
else
var/gasdrained = bitcoinproduction_drain*drainratio
loaded_tank.air_contents.gases[/datum/gas/tritium] -= gasdrained
loaded_tank.air_contents.gases[/datum/gas/oxygen] -= gasdrained
loaded_tank.air_contents.gases[/datum/gas/carbon_dioxide] += gasdrained*2
GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases)
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE)
last_push = stored_power
stored_power = 0
/obj/machinery/power/rad_collector/interact(mob/user)
if(anchored)
if(!src.locked)
toggle_power()
user.visible_message("[user.name] turns the [src.name] [active? "on":"off"].", \
"<span class='notice'>You turn the [src.name] [active? "on":"off"].</span>")
var/fuel
if(loaded_tank)
fuel = loaded_tank.air_contents.gases[/datum/gas/plasma]
investigate_log("turned [active?"<font color='green'>on</font>":"<font color='red'>off</font>"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"<font color='red'>It is empty</font>"].", INVESTIGATE_SINGULO)
return
else
to_chat(user, "<span class='warning'>The controls are locked!</span>")
return
/obj/machinery/power/rad_collector/can_be_unfasten_wrench(mob/user, silent)
if(loaded_tank)
if(!silent)
to_chat(user, "<span class='warning'>Remove the plasma tank first!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/power/rad_collector/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
connect_to_network()
else
disconnect_from_network()
/obj/machinery/power/rad_collector/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/tank/internals/plasma))
if(!anchored)
to_chat(user, "<span class='warning'>[src] needs to be secured to the floor first!</span>")
return TRUE
if(loaded_tank)
to_chat(user, "<span class='warning'>There's already a plasma tank loaded!</span>")
return TRUE
if(panel_open)
to_chat(user, "<span class='warning'>Close the maintenance panel first!</span>")
return TRUE
if(!user.transferItemToLoc(W, src))
return
loaded_tank = W
update_icon()
else if(W.GetID())
if(allowed(user))
if(active)
locked = !locked
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] the controls.</span>")
else
to_chat(user, "<span class='warning'>The controls can only be locked when \the [src] is active!</span>")
else
to_chat(user, "<span class='danger'>Access denied.</span>")
return TRUE
else
return ..()
/obj/machinery/power/rad_collector/wrench_act(mob/living/user, obj/item/I)
default_unfasten_wrench(user, I)
return TRUE
/obj/machinery/power/rad_collector/screwdriver_act(mob/living/user, obj/item/I)
if(..())
return TRUE
if(loaded_tank)
to_chat(user, "<span class='warning'>Remove the plasma tank first!</span>")
else
default_deconstruction_screwdriver(user, icon_state, icon_state, I)
return TRUE
/obj/machinery/power/rad_collector/crowbar_act(mob/living/user, obj/item/I)
if(loaded_tank)
if(locked)
to_chat(user, "<span class='warning'>The controls are locked!</span>")
return TRUE
eject()
return TRUE
if(default_deconstruction_crowbar(I))
return TRUE
to_chat(user, "<span class='warning'>There isn't a tank loaded!</span>")
return TRUE
/obj/machinery/power/rad_collector/multitool_act(mob/living/user, obj/item/I)
if(!is_station_level(z) && !SSresearch.science_tech)
to_chat(user, "<span class='warning'>[src] isn't linked to a research system!</span>")
return TRUE
if(locked)
to_chat(user, "<span class='warning'>[src] is locked!</span>")
return TRUE
if(active)
to_chat(user, "<span class='warning'>[src] is currently active, producing [bitcoinmining ? "research points":"power"].</span>")
return TRUE
bitcoinmining = !bitcoinmining
to_chat(user, "<span class='warning'>You [bitcoinmining ? "enable":"disable"] the research point production feature of [src].</span>")
return TRUE
/obj/machinery/power/rad_collector/analyzer_act(mob/living/user, obj/item/I)
if(loaded_tank)
loaded_tank.analyzer_act(user, I)
/obj/machinery/power/rad_collector/examine(mob/user)
. = ..()
if(active)
if(!bitcoinmining)
. += "<span class='notice'>[src]'s display states that it has stored <b>[DisplayPower(stored_power)]</b>, and is processing <b>[DisplayPower((RAD_COLLECTOR_OUTPUT)*((60 SECONDS)/SSmachines.wait))]</b> per minute. <br>The <b>plasma</b> within it's tank is being irradiated into <b>tritium</b>.</span>"
else
. += "<span class='notice'>[src]'s display states that it's producing a total of <b>[(last_push*RAD_COLLECTOR_MINING_CONVERSION_RATE)*((60 SECONDS)/SSmachines.wait)]</b> research points per minute. <br>The <b>tritium</b> and <b>oxygen</b> within it's tank is being combusted into <b>carbon dioxide</b>.</span>"
else
if(!bitcoinmining)
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Power production mode. Please insert <b>Plasma</b>. Use a multitool to change production modes.\"</span>"
else
. += "<span class='notice'><b>[src]'s display displays the words:</b> \"Research point production mode. Please insert <b>Tritium</b> and <b>Oxygen</b>. Use a multitool to change production modes.\"</span>"
/obj/machinery/power/rad_collector/obj_break(damage_flag)
if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1))
eject()
stat |= BROKEN
/obj/machinery/power/rad_collector/proc/eject()
locked = FALSE
var/obj/item/tank/internals/plasma/Z = src.loaded_tank
if (!Z)
return
Z.forceMove(drop_location())
Z.layer = initial(Z.layer)
Z.plane = initial(Z.plane)
src.loaded_tank = null
if(active)
toggle_power()
else
update_icon()
/obj/machinery/power/rad_collector/rad_act(pulse_strength)
. = ..()
if(loaded_tank && active && pulse_strength > RAD_COLLECTOR_EFFICIENCY)
stored_power += (pulse_strength-RAD_COLLECTOR_EFFICIENCY)*RAD_COLLECTOR_COEFFICIENT
/obj/machinery/power/rad_collector/update_icon()
cut_overlays()
if(loaded_tank)
add_overlay("ptank")
if(stat & (NOPOWER|BROKEN))
return
if(active)
add_overlay("on")
/obj/machinery/power/rad_collector/proc/toggle_power()
active = !active
if(active)
icon_state = "ca_on"
flick("ca_active", src)
else
icon_state = "ca"
flick("ca_deactive", src)
update_icon()
return
#undef RAD_COLLECTOR_EFFICIENCY
#undef RAD_COLLECTOR_COEFFICIENT
#undef RAD_COLLECTOR_STORED_OUT
#undef RAD_COLLECTOR_MINING_CONVERSION_RATE
#undef RAD_COLLECTOR_OUTPUT
@@ -1,134 +1,134 @@
/obj/machinery/field/containment
name = "containment field"
desc = "An energy field."
icon = 'icons/obj/singularity.dmi'
icon_state = "Contain_F"
density = FALSE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
use_power = NO_POWER_USE
interaction_flags_atom = NONE
interaction_flags_machine = NONE
light_range = 4
layer = ABOVE_OBJ_LAYER
var/obj/machinery/field/generator/FG1 = null
var/obj/machinery/field/generator/FG2 = null
/obj/machinery/field/containment/Destroy()
FG1.fields -= src
FG2.fields -= src
return ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/machinery/field/containment/attack_hand(mob/user)
if(get_dist(src, user) > 1)
return FALSE
else
shock(user)
return TRUE
/obj/machinery/field/containment/attackby(obj/item/W, mob/user, params)
shock(user)
return TRUE
/obj/machinery/field/containment/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BURN)
playsound(loc, 'sound/effects/empulse.ogg', 75, 1)
if(BRUTE)
playsound(loc, 'sound/effects/empulse.ogg', 75, 1)
/obj/machinery/field/containment/blob_act(obj/structure/blob/B)
return FALSE
/obj/machinery/field/containment/ex_act(severity, target)
return FALSE
/obj/machinery/field/containment/attack_animal(mob/living/simple_animal/M)
if(!FG1 || !FG2)
qdel(src)
return
if(ismegafauna(M))
M.visible_message("<span class='warning'>[M] glows fiercely as the containment field flickers out!</span>")
FG1.calc_power(INFINITY) //rip that 'containment' field
M.adjustHealth(-M.obj_damage)
else
..()
/obj/machinery/field/containment/Crossed(mob/mover)
if(isliving(mover))
shock(mover)
if(ismachinery(mover) || isstructure(mover) || ismecha(mover))
bump_field(mover)
/obj/machinery/field/containment/proc/set_master(master1,master2)
if(!master1 || !master2)
return FALSE
FG1 = master1
FG2 = master2
return TRUE
/obj/machinery/field/containment/shock(mob/living/user)
if(!FG1 || !FG2)
qdel(src)
return FALSE
..()
/obj/machinery/field/containment/Move()
qdel(src)
return FALSE
// Abstract Field Class
// Used for overriding certain procs
/obj/machinery/field
var/hasShocked = FALSE //Used to add a delay between shocks. In some cases this used to crash servers by spawning hundreds of sparks every second.
/obj/machinery/field/Bumped(atom/movable/mover)
if(hasShocked)
return
if(isliving(mover))
shock(mover)
return
if(ismachinery(mover) || isstructure(mover) || ismecha(mover))
bump_field(mover)
return
/obj/machinery/field/CanPass(atom/movable/mover, turf/target)
if(hasShocked || isliving(mover) || ismachinery(mover) || isstructure(mover) || ismecha(mover))
return FALSE
return ..()
/obj/machinery/field/proc/shock(mob/living/user)
var/shock_damage = min(rand(30,40),rand(30,40))
if(iscarbon(user))
user.Knockdown(300)
user.electrocute_act(shock_damage, src, 1)
else if(issilicon(user))
if(prob(20))
user.Stun(40)
user.take_overall_damage(0, shock_damage)
user.visible_message("<span class='danger'>[user.name] was shocked by the [src.name]!</span>", \
"<span class='userdanger'>Energy pulse detected, system damaged!</span>", \
"<span class='italics'>You hear an electrical crack.</span>")
user.updatehealth()
bump_field(user)
/obj/machinery/field/proc/clear_shock()
hasShocked = FALSE
/obj/machinery/field/proc/bump_field(atom/movable/AM as mob|obj)
if(hasShocked)
return FALSE
hasShocked = TRUE
do_sparks(5, TRUE, AM.loc)
var/atom/target = get_edge_target_turf(AM, get_dir(src, get_step_away(AM, src)))
AM.throw_at(target, 200, 4)
addtimer(CALLBACK(src, .proc/clear_shock), 5)
/obj/machinery/field/containment
name = "containment field"
desc = "An energy field."
icon = 'icons/obj/singularity.dmi'
icon_state = "Contain_F"
density = FALSE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
use_power = NO_POWER_USE
interaction_flags_atom = NONE
interaction_flags_machine = NONE
light_range = 4
layer = ABOVE_OBJ_LAYER
var/obj/machinery/field/generator/FG1 = null
var/obj/machinery/field/generator/FG2 = null
/obj/machinery/field/containment/Destroy()
FG1.fields -= src
FG2.fields -= src
return ..()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/machinery/field/containment/attack_hand(mob/user)
if(get_dist(src, user) > 1)
return FALSE
else
shock(user)
return TRUE
/obj/machinery/field/containment/attackby(obj/item/W, mob/user, params)
shock(user)
return TRUE
/obj/machinery/field/containment/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BURN)
playsound(loc, 'sound/effects/empulse.ogg', 75, 1)
if(BRUTE)
playsound(loc, 'sound/effects/empulse.ogg', 75, 1)
/obj/machinery/field/containment/blob_act(obj/structure/blob/B)
return FALSE
/obj/machinery/field/containment/ex_act(severity, target)
return FALSE
/obj/machinery/field/containment/attack_animal(mob/living/simple_animal/M)
if(!FG1 || !FG2)
qdel(src)
return
if(ismegafauna(M))
M.visible_message("<span class='warning'>[M] glows fiercely as the containment field flickers out!</span>")
FG1.calc_power(INFINITY) //rip that 'containment' field
M.adjustHealth(-M.obj_damage)
else
..()
/obj/machinery/field/containment/Crossed(mob/mover)
if(isliving(mover))
shock(mover)
if(ismachinery(mover) || isstructure(mover) || ismecha(mover))
bump_field(mover)
/obj/machinery/field/containment/proc/set_master(master1,master2)
if(!master1 || !master2)
return FALSE
FG1 = master1
FG2 = master2
return TRUE
/obj/machinery/field/containment/shock(mob/living/user)
if(!FG1 || !FG2)
qdel(src)
return FALSE
..()
/obj/machinery/field/containment/Move()
qdel(src)
return FALSE
// Abstract Field Class
// Used for overriding certain procs
/obj/machinery/field
var/hasShocked = FALSE //Used to add a delay between shocks. In some cases this used to crash servers by spawning hundreds of sparks every second.
/obj/machinery/field/Bumped(atom/movable/mover)
if(hasShocked)
return
if(isliving(mover))
shock(mover)
return
if(ismachinery(mover) || isstructure(mover) || ismecha(mover))
bump_field(mover)
return
/obj/machinery/field/CanPass(atom/movable/mover, turf/target)
if(hasShocked || isliving(mover) || ismachinery(mover) || isstructure(mover) || ismecha(mover))
return FALSE
return ..()
/obj/machinery/field/proc/shock(mob/living/user)
var/shock_damage = min(rand(30,40),rand(30,40))
if(iscarbon(user))
user.Knockdown(300)
user.electrocute_act(shock_damage, src, 1)
else if(issilicon(user))
if(prob(20))
user.Stun(40)
user.take_overall_damage(0, shock_damage)
user.visible_message("<span class='danger'>[user.name] was shocked by the [src.name]!</span>", \
"<span class='userdanger'>Energy pulse detected, system damaged!</span>", \
"<span class='italics'>You hear an electrical crack.</span>")
user.updatehealth()
bump_field(user)
/obj/machinery/field/proc/clear_shock()
hasShocked = FALSE
/obj/machinery/field/proc/bump_field(atom/movable/AM as mob|obj)
if(hasShocked)
return FALSE
hasShocked = TRUE
do_sparks(5, TRUE, AM.loc)
var/atom/target = get_edge_target_turf(AM, get_dir(src, get_step_away(AM, src)))
AM.throw_at(target, 200, 4)
addtimer(CALLBACK(src, .proc/clear_shock), 5)
File diff suppressed because it is too large Load Diff
+353 -353
View File
@@ -1,353 +1,353 @@
/*
field_generator power level display
The icon used for the field_generator need to have 'num_power_levels' number of icon states
named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_power_levels'
The power level is displayed using overlays. The current displayed power level is stored in 'powerlevel'.
The overlay in use and the powerlevel variable must be kept in sync. A powerlevel equal to 0 means that
no power level overlay is currently in the overlays list.
-Aygar
*/
#define field_generator_max_power 250
#define FG_OFFLINE 0
#define FG_CHARGING 1
#define FG_ONLINE 2
//field generator construction defines
#define FG_UNSECURED 0
#define FG_SECURED 1
#define FG_WELDED 2
/obj/machinery/field/generator
name = "field generator"
desc = "A large thermal battery that projects a high amount of energy when powered."
icon = 'icons/obj/machines/field_generator.dmi'
icon_state = "Field_Gen"
anchored = FALSE
density = TRUE
use_power = NO_POWER_USE
max_integrity = 500
//100% immune to lasers and energy projectiles since it absorbs their energy.
armor = list("melee" = 25, "bullet" = 10, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
var/const/num_power_levels = 6 // Total number of power level icon has
var/power_level = 0
var/active = FG_OFFLINE
var/power = 20 // Current amount of power
var/state = FG_UNSECURED
var/warming_up = 0
var/list/obj/machinery/field/containment/fields
var/list/obj/machinery/field/generator/connected_gens
var/clean_up = 0
/obj/machinery/field/generator/update_icon()
cut_overlays()
if(warming_up)
add_overlay("+a[warming_up]")
if(fields.len)
add_overlay("+on")
if(power_level)
add_overlay("+p[power_level]")
/obj/machinery/field/generator/Initialize()
. = ..()
fields = list()
connected_gens = list()
/obj/machinery/field/generator/ComponentInitialize()
. = ..()
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
/obj/machinery/field/generator/process()
if(active == FG_ONLINE)
calc_power()
/obj/machinery/field/generator/interact(mob/user)
if(state == FG_WELDED)
if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on
if(active >= FG_CHARGING)
to_chat(user, "<span class='warning'>You are unable to turn off [src] once it is online!</span>")
return 1
else
user.visible_message("[user] turns on [src].", \
"<span class='notice'>You turn on [src].</span>", \
"<span class='italics'>You hear heavy droning.</span>")
turn_on()
investigate_log("<font color='green'>activated</font> by [key_name(user)].", INVESTIGATE_SINGULO)
add_fingerprint(user)
else
to_chat(user, "<span class='warning'>[src] needs to be firmly secured to the floor first!</span>")
/obj/machinery/field/generator/can_be_unfasten_wrench(mob/user, silent)
if(active)
if(!silent)
to_chat(user, "<span class='warning'>Turn \the [src] off first!</span>")
return FAILED_UNFASTEN
else if(state == FG_WELDED)
if(!silent)
to_chat(user, "<span class='warning'>[src] is welded to the floor!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/field/generator/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
state = FG_SECURED
else
state = FG_UNSECURED
/obj/machinery/field/generator/wrench_act(mob/living/user, obj/item/I)
default_unfasten_wrench(user, I)
return TRUE
/obj/machinery/field/generator/welder_act(mob/living/user, obj/item/I)
if(active)
to_chat(user, "<span class='warning'>[src] needs to be off!</span>")
return TRUE
switch(state)
if(FG_UNSECURED)
to_chat(user, "<span class='warning'>[src] needs to be wrenched to the floor!</span>")
if(FG_SECURED)
if(!I.tool_start_check(user, amount=0))
return TRUE
user.visible_message("[user] starts to weld [src] to the floor.", \
"<span class='notice'>You start to weld \the [src] to the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 20, volume=50) && state == FG_SECURED)
state = FG_WELDED
to_chat(user, "<span class='notice'>You weld the field generator to the floor.</span>")
if(FG_WELDED)
if(!I.tool_start_check(user, amount=0))
return TRUE
user.visible_message("[user] starts to cut [src] free from the floor.", \
"<span class='notice'>You start to cut \the [src] free from the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 20, volume=50) && state == FG_WELDED)
state = FG_SECURED
to_chat(user, "<span class='notice'>You cut \the [src] free from the floor.</span>")
return TRUE
/obj/machinery/field/generator/attack_animal(mob/living/simple_animal/M)
if(M.environment_smash & ENVIRONMENT_SMASH_RWALLS && active == FG_OFFLINE && state != FG_UNSECURED)
state = FG_UNSECURED
anchored = FALSE
M.visible_message("<span class='warning'>[M] rips [src] free from its moorings!</span>")
else
..()
if(!anchored)
step(src, get_dir(M, src))
/obj/machinery/field/generator/blob_act(obj/structure/blob/B)
if(active)
return 0
else
..()
/obj/machinery/field/generator/bullet_act(obj/item/projectile/Proj)
if(Proj.flag != "bullet")
power = min(power + Proj.damage, field_generator_max_power)
check_power_level()
..()
/obj/machinery/field/generator/Destroy()
cleanup()
return ..()
/obj/machinery/field/generator/proc/check_power_level()
var/new_level = round(num_power_levels * power / field_generator_max_power)
if(new_level != power_level)
power_level = new_level
update_icon()
/obj/machinery/field/generator/proc/turn_off()
active = FG_OFFLINE
spawn(1)
cleanup()
while (warming_up>0 && !active)
sleep(50)
warming_up--
update_icon()
/obj/machinery/field/generator/proc/turn_on()
active = FG_CHARGING
spawn(1)
while (warming_up<3 && active)
sleep(50)
warming_up++
update_icon()
if(warming_up >= 3)
start_fields()
/obj/machinery/field/generator/proc/calc_power(set_power_draw)
var/power_draw = 2 + fields.len
if(set_power_draw)
power_draw = set_power_draw
if(draw_power(round(power_draw/2,1)))
check_power_level()
return 1
else
visible_message("<span class='danger'>The [name] shuts down!</span>", "<span class='italics'>You hear something shutting down.</span>")
turn_off()
investigate_log("ran out of power and <font color='red'>deactivated</font>", INVESTIGATE_SINGULO)
power = 0
check_power_level()
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(draw = 0, failsafe = FALSE, obj/machinery/field/generator/G = null, obj/machinery/field/generator/last = null)
if((G && (G == src)) || (failsafe >= 8))//Loopin, set fail
return 0
else
failsafe++
if(power >= draw)//We have enough power
power -= draw
return 1
else//Need more power
draw -= power
power = 0
for(var/CG in connected_gens)
var/obj/machinery/field/generator/FG = CG
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
/obj/machinery/field/generator/proc/start_fields()
if(state != FG_WELDED || !anchored)
turn_off()
return
spawn(1)
setup_field(1)
spawn(2)
setup_field(2)
spawn(3)
setup_field(4)
spawn(4)
setup_field(8)
spawn(5)
active = FG_ONLINE
/obj/machinery/field/generator/proc/setup_field(NSEW)
var/turf/T = loc
if(!istype(T))
return 0
var/obj/machinery/field/generator/G = null
var/steps = 0
if(!NSEW)//Make sure its ran right
return 0
for(var/dist in 0 to 7) // checks out to 8 tiles away for another generator
T = get_step(T, NSEW)
if(T.density)//We cant shoot a field though this
return 0
G = locate(/obj/machinery/field/generator) in T
if(G)
steps -= 1
if(!G.active)
return 0
break
for(var/TC in T.contents)
var/atom/A = TC
if(ismob(A))
continue
if(A.density)
return 0
steps++
if(!G)
return 0
T = loc
for(var/dist in 0 to steps) // creates each field tile
var/field_dir = get_dir(T,get_step(G.loc, NSEW))
T = get_step(T, NSEW)
if(!locate(/obj/machinery/field/containment) in T)
var/obj/machinery/field/containment/CF = new(T)
CF.set_master(src,G)
CF.setDir(field_dir)
fields += CF
G.fields += CF
for(var/mob/living/L in T)
CF.Crossed(L)
connected_gens |= G
G.connected_gens |= src
update_icon()
/obj/machinery/field/generator/proc/cleanup()
clean_up = 1
for (var/F in fields)
qdel(F)
for(var/CG in connected_gens)
var/obj/machinery/field/generator/FG = CG
FG.connected_gens -= src
if(!FG.clean_up)//Makes the other gens clean up as well
FG.cleanup()
connected_gens -= FG
clean_up = 0
update_icon()
//This is here to help fight the "hurr durr, release singulo cos nobody will notice before the
//singulo eats the evidence". It's not fool-proof but better than nothing.
//I want to avoid using global variables.
spawn(1)
var/temp = 1 //stops spam
for(var/obj/singularity/O in GLOB.singularities)
if(O.last_warning && temp)
if((world.time - O.last_warning) > 50) //to stop message-spam
temp = 0
var/turf/T = get_turf(src)
message_admins("A singulo exists and a containment field has failed at [ADMIN_VERBOSEJMP(T)].")
investigate_log("has <font color='red'>failed</font> whilst a singulo exists at [AREACOORD(T)].", INVESTIGATE_SINGULO)
O.last_warning = world.time
/obj/machinery/field/generator/shock(mob/living/user)
if(fields.len)
..()
/obj/machinery/field/generator/bump_field(atom/movable/AM as mob|obj)
if(fields.len)
..()
#undef FG_UNSECURED
#undef FG_SECURED
#undef FG_WELDED
#undef FG_OFFLINE
#undef FG_CHARGING
#undef FG_ONLINE
/*
field_generator power level display
The icon used for the field_generator need to have 'num_power_levels' number of icon states
named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_power_levels'
The power level is displayed using overlays. The current displayed power level is stored in 'powerlevel'.
The overlay in use and the powerlevel variable must be kept in sync. A powerlevel equal to 0 means that
no power level overlay is currently in the overlays list.
-Aygar
*/
#define field_generator_max_power 250
#define FG_OFFLINE 0
#define FG_CHARGING 1
#define FG_ONLINE 2
//field generator construction defines
#define FG_UNSECURED 0
#define FG_SECURED 1
#define FG_WELDED 2
/obj/machinery/field/generator
name = "field generator"
desc = "A large thermal battery that projects a high amount of energy when powered."
icon = 'icons/obj/machines/field_generator.dmi'
icon_state = "Field_Gen"
anchored = FALSE
density = TRUE
use_power = NO_POWER_USE
max_integrity = 500
//100% immune to lasers and energy projectiles since it absorbs their energy.
armor = list("melee" = 25, "bullet" = 10, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70)
var/const/num_power_levels = 6 // Total number of power level icon has
var/power_level = 0
var/active = FG_OFFLINE
var/power = 20 // Current amount of power
var/state = FG_UNSECURED
var/warming_up = 0
var/list/obj/machinery/field/containment/fields
var/list/obj/machinery/field/generator/connected_gens
var/clean_up = 0
/obj/machinery/field/generator/update_icon()
cut_overlays()
if(warming_up)
add_overlay("+a[warming_up]")
if(fields.len)
add_overlay("+on")
if(power_level)
add_overlay("+p[power_level]")
/obj/machinery/field/generator/Initialize()
. = ..()
fields = list()
connected_gens = list()
/obj/machinery/field/generator/ComponentInitialize()
. = ..()
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
/obj/machinery/field/generator/process()
if(active == FG_ONLINE)
calc_power()
/obj/machinery/field/generator/interact(mob/user)
if(state == FG_WELDED)
if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on
if(active >= FG_CHARGING)
to_chat(user, "<span class='warning'>You are unable to turn off [src] once it is online!</span>")
return 1
else
user.visible_message("[user] turns on [src].", \
"<span class='notice'>You turn on [src].</span>", \
"<span class='italics'>You hear heavy droning.</span>")
turn_on()
investigate_log("<font color='green'>activated</font> by [key_name(user)].", INVESTIGATE_SINGULO)
add_fingerprint(user)
else
to_chat(user, "<span class='warning'>[src] needs to be firmly secured to the floor first!</span>")
/obj/machinery/field/generator/can_be_unfasten_wrench(mob/user, silent)
if(active)
if(!silent)
to_chat(user, "<span class='warning'>Turn \the [src] off first!</span>")
return FAILED_UNFASTEN
else if(state == FG_WELDED)
if(!silent)
to_chat(user, "<span class='warning'>[src] is welded to the floor!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/field/generator/default_unfasten_wrench(mob/user, obj/item/I, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
state = FG_SECURED
else
state = FG_UNSECURED
/obj/machinery/field/generator/wrench_act(mob/living/user, obj/item/I)
default_unfasten_wrench(user, I)
return TRUE
/obj/machinery/field/generator/welder_act(mob/living/user, obj/item/I)
if(active)
to_chat(user, "<span class='warning'>[src] needs to be off!</span>")
return TRUE
switch(state)
if(FG_UNSECURED)
to_chat(user, "<span class='warning'>[src] needs to be wrenched to the floor!</span>")
if(FG_SECURED)
if(!I.tool_start_check(user, amount=0))
return TRUE
user.visible_message("[user] starts to weld [src] to the floor.", \
"<span class='notice'>You start to weld \the [src] to the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 20, volume=50) && state == FG_SECURED)
state = FG_WELDED
to_chat(user, "<span class='notice'>You weld the field generator to the floor.</span>")
if(FG_WELDED)
if(!I.tool_start_check(user, amount=0))
return TRUE
user.visible_message("[user] starts to cut [src] free from the floor.", \
"<span class='notice'>You start to cut \the [src] free from the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 20, volume=50) && state == FG_WELDED)
state = FG_SECURED
to_chat(user, "<span class='notice'>You cut \the [src] free from the floor.</span>")
return TRUE
/obj/machinery/field/generator/attack_animal(mob/living/simple_animal/M)
if(M.environment_smash & ENVIRONMENT_SMASH_RWALLS && active == FG_OFFLINE && state != FG_UNSECURED)
state = FG_UNSECURED
anchored = FALSE
M.visible_message("<span class='warning'>[M] rips [src] free from its moorings!</span>")
else
..()
if(!anchored)
step(src, get_dir(M, src))
/obj/machinery/field/generator/blob_act(obj/structure/blob/B)
if(active)
return 0
else
..()
/obj/machinery/field/generator/bullet_act(obj/item/projectile/Proj)
if(Proj.flag != "bullet")
power = min(power + Proj.damage, field_generator_max_power)
check_power_level()
..()
/obj/machinery/field/generator/Destroy()
cleanup()
return ..()
/obj/machinery/field/generator/proc/check_power_level()
var/new_level = round(num_power_levels * power / field_generator_max_power)
if(new_level != power_level)
power_level = new_level
update_icon()
/obj/machinery/field/generator/proc/turn_off()
active = FG_OFFLINE
spawn(1)
cleanup()
while (warming_up>0 && !active)
sleep(50)
warming_up--
update_icon()
/obj/machinery/field/generator/proc/turn_on()
active = FG_CHARGING
spawn(1)
while (warming_up<3 && active)
sleep(50)
warming_up++
update_icon()
if(warming_up >= 3)
start_fields()
/obj/machinery/field/generator/proc/calc_power(set_power_draw)
var/power_draw = 2 + fields.len
if(set_power_draw)
power_draw = set_power_draw
if(draw_power(round(power_draw/2,1)))
check_power_level()
return 1
else
visible_message("<span class='danger'>The [name] shuts down!</span>", "<span class='italics'>You hear something shutting down.</span>")
turn_off()
investigate_log("ran out of power and <font color='red'>deactivated</font>", INVESTIGATE_SINGULO)
power = 0
check_power_level()
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(draw = 0, failsafe = FALSE, obj/machinery/field/generator/G = null, obj/machinery/field/generator/last = null)
if((G && (G == src)) || (failsafe >= 8))//Loopin, set fail
return 0
else
failsafe++
if(power >= draw)//We have enough power
power -= draw
return 1
else//Need more power
draw -= power
power = 0
for(var/CG in connected_gens)
var/obj/machinery/field/generator/FG = CG
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
/obj/machinery/field/generator/proc/start_fields()
if(state != FG_WELDED || !anchored)
turn_off()
return
spawn(1)
setup_field(1)
spawn(2)
setup_field(2)
spawn(3)
setup_field(4)
spawn(4)
setup_field(8)
spawn(5)
active = FG_ONLINE
/obj/machinery/field/generator/proc/setup_field(NSEW)
var/turf/T = loc
if(!istype(T))
return 0
var/obj/machinery/field/generator/G = null
var/steps = 0
if(!NSEW)//Make sure its ran right
return 0
for(var/dist in 0 to 7) // checks out to 8 tiles away for another generator
T = get_step(T, NSEW)
if(T.density)//We cant shoot a field though this
return 0
G = locate(/obj/machinery/field/generator) in T
if(G)
steps -= 1
if(!G.active)
return 0
break
for(var/TC in T.contents)
var/atom/A = TC
if(ismob(A))
continue
if(A.density)
return 0
steps++
if(!G)
return 0
T = loc
for(var/dist in 0 to steps) // creates each field tile
var/field_dir = get_dir(T,get_step(G.loc, NSEW))
T = get_step(T, NSEW)
if(!locate(/obj/machinery/field/containment) in T)
var/obj/machinery/field/containment/CF = new(T)
CF.set_master(src,G)
CF.setDir(field_dir)
fields += CF
G.fields += CF
for(var/mob/living/L in T)
CF.Crossed(L)
connected_gens |= G
G.connected_gens |= src
update_icon()
/obj/machinery/field/generator/proc/cleanup()
clean_up = 1
for (var/F in fields)
qdel(F)
for(var/CG in connected_gens)
var/obj/machinery/field/generator/FG = CG
FG.connected_gens -= src
if(!FG.clean_up)//Makes the other gens clean up as well
FG.cleanup()
connected_gens -= FG
clean_up = 0
update_icon()
//This is here to help fight the "hurr durr, release singulo cos nobody will notice before the
//singulo eats the evidence". It's not fool-proof but better than nothing.
//I want to avoid using global variables.
spawn(1)
var/temp = 1 //stops spam
for(var/obj/singularity/O in GLOB.singularities)
if(O.last_warning && temp)
if((world.time - O.last_warning) > 50) //to stop message-spam
temp = 0
var/turf/T = get_turf(src)
message_admins("A singulo exists and a containment field has failed at [ADMIN_VERBOSEJMP(T)].")
investigate_log("has <font color='red'>failed</font> whilst a singulo exists at [AREACOORD(T)].", INVESTIGATE_SINGULO)
O.last_warning = world.time
/obj/machinery/field/generator/shock(mob/living/user)
if(fields.len)
..()
/obj/machinery/field/generator/bump_field(atom/movable/AM as mob|obj)
if(fields.len)
..()
#undef FG_UNSECURED
#undef FG_SECURED
#undef FG_WELDED
#undef FG_OFFLINE
#undef FG_CHARGING
#undef FG_ONLINE
+35 -35
View File
@@ -1,35 +1,35 @@
/////SINGULARITY SPAWNER
/obj/machinery/the_singularitygen
name = "Gravitational Singularity Generator"
desc = "An odd device which produces a Gravitational Singularity when set up."
icon = 'icons/obj/singularity.dmi'
icon_state = "TheSingGen"
anchored = FALSE
density = TRUE
use_power = NO_POWER_USE
resistance_flags = FIRE_PROOF
// You can buckle someone to the singularity generator, then start the engine. Fun!
can_buckle = TRUE
buckle_lying = FALSE
buckle_requires_restraints = TRUE
var/energy = 0
var/creation_type = /obj/singularity
/obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/wrench))
default_unfasten_wrench(user, W, 0)
else
return ..()
/obj/machinery/the_singularitygen/process()
if(energy > 0)
if(energy >= 200)
var/turf/T = get_turf(src)
SSblackbox.record_feedback("tally", "engine_started", 1, type)
var/obj/singularity/S = new creation_type(T, 50)
transfer_fingerprints_to(S)
qdel(src)
else
energy -= 1
/////SINGULARITY SPAWNER
/obj/machinery/the_singularitygen
name = "Gravitational Singularity Generator"
desc = "An odd device which produces a Gravitational Singularity when set up."
icon = 'icons/obj/singularity.dmi'
icon_state = "TheSingGen"
anchored = FALSE
density = TRUE
use_power = NO_POWER_USE
resistance_flags = FIRE_PROOF
// You can buckle someone to the singularity generator, then start the engine. Fun!
can_buckle = TRUE
buckle_lying = FALSE
buckle_requires_restraints = TRUE
var/energy = 0
var/creation_type = /obj/singularity
/obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/wrench))
default_unfasten_wrench(user, W, 0)
else
return ..()
/obj/machinery/the_singularitygen/process()
if(energy > 0)
if(energy >= 200)
var/turf/T = get_turf(src)
SSblackbox.record_feedback("tally", "engine_started", 1, type)
var/obj/singularity/S = new creation_type(T, 50)
transfer_fingerprints_to(S)
qdel(src)
else
energy -= 1
@@ -1,4 +1,4 @@
/area/engine/engineering/poweralert(state, source)
if (state != poweralm)
investigate_log("has a power alarm!", INVESTIGATE_SINGULO)
/area/engine/engineering/poweralert(state, source)
if (state != poweralm)
investigate_log("has a power alarm!", INVESTIGATE_SINGULO)
..()
@@ -1,68 +1,68 @@
/obj/effect/accelerated_particle
name = "Accelerated Particles"
desc = "Small things moving very fast."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "particle"
anchored = TRUE
density = FALSE
var/movement_range = 10
var/energy = 10
var/speed = 1
/obj/effect/accelerated_particle/weak
movement_range = 8
energy = 5
/obj/effect/accelerated_particle/strong
movement_range = 15
energy = 15
/obj/effect/accelerated_particle/powerful
movement_range = 20
energy = 50
/obj/effect/accelerated_particle/New(loc)
..()
addtimer(CALLBACK(src, .proc/move), 1)
/obj/effect/accelerated_particle/Bump(atom/A)
if(A)
if(isliving(A))
toxmob(A)
else if(istype(A, /obj/machinery/the_singularitygen))
var/obj/machinery/the_singularitygen/S = A
S.energy += energy
else if(istype(A, /obj/singularity))
var/obj/singularity/S = A
S.energy += energy
else if(istype(A, /obj/structure/blob))
var/obj/structure/blob/B = A
B.take_damage(energy*0.6)
movement_range = 0
/obj/effect/accelerated_particle/Crossed(atom/A)
if(isliving(A))
toxmob(A)
/obj/effect/accelerated_particle/ex_act(severity, target)
qdel(src)
/obj/effect/accelerated_particle/singularity_pull()
return
/obj/effect/accelerated_particle/proc/toxmob(mob/living/M)
M.rad_act(energy*6)
/obj/effect/accelerated_particle/proc/move()
if(!step(src,dir))
forceMove(get_step(src,dir))
movement_range--
if(movement_range == 0)
qdel(src)
else
sleep(speed)
move()
/obj/effect/accelerated_particle
name = "Accelerated Particles"
desc = "Small things moving very fast."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "particle"
anchored = TRUE
density = FALSE
var/movement_range = 10
var/energy = 10
var/speed = 1
/obj/effect/accelerated_particle/weak
movement_range = 8
energy = 5
/obj/effect/accelerated_particle/strong
movement_range = 15
energy = 15
/obj/effect/accelerated_particle/powerful
movement_range = 20
energy = 50
/obj/effect/accelerated_particle/New(loc)
..()
addtimer(CALLBACK(src, .proc/move), 1)
/obj/effect/accelerated_particle/Bump(atom/A)
if(A)
if(isliving(A))
toxmob(A)
else if(istype(A, /obj/machinery/the_singularitygen))
var/obj/machinery/the_singularitygen/S = A
S.energy += energy
else if(istype(A, /obj/singularity))
var/obj/singularity/S = A
S.energy += energy
else if(istype(A, /obj/structure/blob))
var/obj/structure/blob/B = A
B.take_damage(energy*0.6)
movement_range = 0
/obj/effect/accelerated_particle/Crossed(atom/A)
if(isliving(A))
toxmob(A)
/obj/effect/accelerated_particle/ex_act(severity, target)
qdel(src)
/obj/effect/accelerated_particle/singularity_pull()
return
/obj/effect/accelerated_particle/proc/toxmob(mob/living/M)
M.rad_act(energy*6)
/obj/effect/accelerated_particle/proc/move()
if(!step(src,dir))
forceMove(get_step(src,dir))
movement_range--
if(movement_range == 0)
qdel(src)
else
sleep(speed)
move()
@@ -1,172 +1,172 @@
/*Composed of 7 parts :
3 Particle Emitters
1 Power Box
1 Fuel Chamber
1 End Cap
1 Control computer
Setup map
|EC|
CC|FC|
|PB|
PE|PE|PE
*/
#define PA_CONSTRUCTION_UNSECURED 0
#define PA_CONSTRUCTION_UNWIRED 1
#define PA_CONSTRUCTION_PANEL_OPEN 2
#define PA_CONSTRUCTION_COMPLETE 3
/obj/structure/particle_accelerator
name = "Particle Accelerator"
desc = "Part of a Particle Accelerator."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "none"
anchored = FALSE
density = TRUE
max_integrity = 500
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 80)
var/obj/machinery/particle_accelerator/control_box/master = null
var/construction_state = PA_CONSTRUCTION_UNSECURED
var/reference = null
var/powered = 0
var/strength = null
/obj/structure/particle_accelerator/examine(mob/user)
. = ..()
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
. += "Looks like it's not attached to the flooring."
if(PA_CONSTRUCTION_UNWIRED)
. += "It is missing some cables."
if(PA_CONSTRUCTION_PANEL_OPEN)
. += "The panel is open."
/obj/structure/particle_accelerator/Destroy()
construction_state = PA_CONSTRUCTION_UNSECURED
if(master)
master.connected_parts -= src
master.assembled = 0
master = null
return ..()
/obj/structure/particle_accelerator/ComponentInitialize()
. = ..()
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS )
/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user, params)
var/did_something = FALSE
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
if(istype(W, /obj/item/wrench) && !isinspace())
W.play_tool_sound(src, 75)
anchored = TRUE
user.visible_message("[user.name] secures the [name] to the floor.", \
"You secure the external bolts.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
if(PA_CONSTRUCTION_UNWIRED)
if(istype(W, /obj/item/wrench))
W.play_tool_sound(src, 75)
anchored = FALSE
user.visible_message("[user.name] detaches the [name] from the floor.", \
"You remove the external bolts.")
construction_state = PA_CONSTRUCTION_UNSECURED
did_something = TRUE
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if(CC.use(1))
user.visible_message("[user.name] adds wires to the [name].", \
"You add some wires.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(PA_CONSTRUCTION_PANEL_OPEN)
if(istype(W, /obj/item/wirecutters))//TODO:Shock user if its on?
user.visible_message("[user.name] removes some wires from the [name].", \
"You remove some wires.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
else if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] closes the [name]'s access panel.", \
"You close the access panel.")
construction_state = PA_CONSTRUCTION_COMPLETE
did_something = TRUE
if(PA_CONSTRUCTION_COMPLETE)
if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] opens the [name]'s access panel.", \
"You open the access panel.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(did_something)
user.changeNext_move(CLICK_CD_MELEE)
update_state()
update_icon()
return
return ..()
/obj/structure/particle_accelerator/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
new /obj/item/stack/sheet/metal (loc, 5)
qdel(src)
/obj/structure/particle_accelerator/Move()
. = ..()
if(master && master.active)
master.toggle_power()
investigate_log("was moved whilst active; it <font color='red'>powered down</font>.", INVESTIGATE_SINGULO)
/obj/structure/particle_accelerator/update_icon()
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED,PA_CONSTRUCTION_UNWIRED)
icon_state="[reference]"
if(PA_CONSTRUCTION_PANEL_OPEN)
icon_state="[reference]w"
if(PA_CONSTRUCTION_COMPLETE)
if(powered)
icon_state="[reference]p[strength]"
else
icon_state="[reference]c"
/obj/structure/particle_accelerator/proc/update_state()
if(master)
master.update_state()
/obj/structure/particle_accelerator/proc/connect_master(obj/O)
if(O.dir == dir)
master = O
return 1
return 0
///////////
// PARTS //
///////////
/obj/structure/particle_accelerator/end_cap
name = "Alpha Particle Generation Array"
desc = "This is where Alpha particles are generated from \[REDACTED\]."
icon_state = "end_cap"
reference = "end_cap"
/obj/structure/particle_accelerator/power_box
name = "Particle Focusing EM Lens"
desc = "This uses electromagnetic waves to focus the Alpha particles."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "power_box"
reference = "power_box"
/obj/structure/particle_accelerator/fuel_chamber
name = "EM Acceleration Chamber"
desc = "This is where the Alpha particles are accelerated to <b><i>radical speeds</i></b>."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "fuel_chamber"
reference = "fuel_chamber"
/*Composed of 7 parts :
3 Particle Emitters
1 Power Box
1 Fuel Chamber
1 End Cap
1 Control computer
Setup map
|EC|
CC|FC|
|PB|
PE|PE|PE
*/
#define PA_CONSTRUCTION_UNSECURED 0
#define PA_CONSTRUCTION_UNWIRED 1
#define PA_CONSTRUCTION_PANEL_OPEN 2
#define PA_CONSTRUCTION_COMPLETE 3
/obj/structure/particle_accelerator
name = "Particle Accelerator"
desc = "Part of a Particle Accelerator."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "none"
anchored = FALSE
density = TRUE
max_integrity = 500
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 80)
var/obj/machinery/particle_accelerator/control_box/master = null
var/construction_state = PA_CONSTRUCTION_UNSECURED
var/reference = null
var/powered = 0
var/strength = null
/obj/structure/particle_accelerator/examine(mob/user)
. = ..()
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
. += "Looks like it's not attached to the flooring."
if(PA_CONSTRUCTION_UNWIRED)
. += "It is missing some cables."
if(PA_CONSTRUCTION_PANEL_OPEN)
. += "The panel is open."
/obj/structure/particle_accelerator/Destroy()
construction_state = PA_CONSTRUCTION_UNSECURED
if(master)
master.connected_parts -= src
master.assembled = 0
master = null
return ..()
/obj/structure/particle_accelerator/ComponentInitialize()
. = ..()
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS )
/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user, params)
var/did_something = FALSE
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
if(istype(W, /obj/item/wrench) && !isinspace())
W.play_tool_sound(src, 75)
anchored = TRUE
user.visible_message("[user.name] secures the [name] to the floor.", \
"You secure the external bolts.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
if(PA_CONSTRUCTION_UNWIRED)
if(istype(W, /obj/item/wrench))
W.play_tool_sound(src, 75)
anchored = FALSE
user.visible_message("[user.name] detaches the [name] from the floor.", \
"You remove the external bolts.")
construction_state = PA_CONSTRUCTION_UNSECURED
did_something = TRUE
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if(CC.use(1))
user.visible_message("[user.name] adds wires to the [name].", \
"You add some wires.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(PA_CONSTRUCTION_PANEL_OPEN)
if(istype(W, /obj/item/wirecutters))//TODO:Shock user if its on?
user.visible_message("[user.name] removes some wires from the [name].", \
"You remove some wires.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
else if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] closes the [name]'s access panel.", \
"You close the access panel.")
construction_state = PA_CONSTRUCTION_COMPLETE
did_something = TRUE
if(PA_CONSTRUCTION_COMPLETE)
if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] opens the [name]'s access panel.", \
"You open the access panel.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(did_something)
user.changeNext_move(CLICK_CD_MELEE)
update_state()
update_icon()
return
return ..()
/obj/structure/particle_accelerator/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
new /obj/item/stack/sheet/metal (loc, 5)
qdel(src)
/obj/structure/particle_accelerator/Move()
. = ..()
if(master && master.active)
master.toggle_power()
investigate_log("was moved whilst active; it <font color='red'>powered down</font>.", INVESTIGATE_SINGULO)
/obj/structure/particle_accelerator/update_icon()
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED,PA_CONSTRUCTION_UNWIRED)
icon_state="[reference]"
if(PA_CONSTRUCTION_PANEL_OPEN)
icon_state="[reference]w"
if(PA_CONSTRUCTION_COMPLETE)
if(powered)
icon_state="[reference]p[strength]"
else
icon_state="[reference]c"
/obj/structure/particle_accelerator/proc/update_state()
if(master)
master.update_state()
/obj/structure/particle_accelerator/proc/connect_master(obj/O)
if(O.dir == dir)
master = O
return 1
return 0
///////////
// PARTS //
///////////
/obj/structure/particle_accelerator/end_cap
name = "Alpha Particle Generation Array"
desc = "This is where Alpha particles are generated from \[REDACTED\]."
icon_state = "end_cap"
reference = "end_cap"
/obj/structure/particle_accelerator/power_box
name = "Particle Focusing EM Lens"
desc = "This uses electromagnetic waves to focus the Alpha particles."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "power_box"
reference = "power_box"
/obj/structure/particle_accelerator/fuel_chamber
name = "EM Acceleration Chamber"
desc = "This is where the Alpha particles are accelerated to <b><i>radical speeds</i></b>."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "fuel_chamber"
reference = "fuel_chamber"
@@ -1,330 +1,330 @@
/obj/machinery/particle_accelerator/control_box
name = "Particle Accelerator Control Console"
desc = "This controls the density of the particles."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_box"
anchored = FALSE
density = TRUE
use_power = NO_POWER_USE
idle_power_usage = 500
active_power_usage = 10000
dir = NORTH
var/strength_upper_limit = 2
var/interface_control = 1
var/list/obj/structure/particle_accelerator/connected_parts
var/assembled = 0
var/construction_state = PA_CONSTRUCTION_UNSECURED
var/active = 0
var/strength = 0
var/powered = 0
mouse_opacity = MOUSE_OPACITY_OPAQUE
/obj/machinery/particle_accelerator/control_box/Initialize()
. = ..()
wires = new /datum/wires/particle_accelerator/control_box(src)
connected_parts = list()
/obj/machinery/particle_accelerator/control_box/Destroy()
if(active)
toggle_power()
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.master = null
connected_parts.Cut()
QDEL_NULL(wires)
return ..()
/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user)
. = ..()
if(.)
return
if(construction_state == PA_CONSTRUCTION_COMPLETE)
interact(user)
else if(construction_state == PA_CONSTRUCTION_PANEL_OPEN)
wires.interact(user)
/obj/machinery/particle_accelerator/control_box/proc/update_state()
if(construction_state < PA_CONSTRUCTION_COMPLETE)
use_power = NO_POWER_USE
assembled = 0
active = 0
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = null
part.powered = 0
part.update_icon()
connected_parts.Cut()
return
if(!part_scan())
use_power = IDLE_POWER_USE
active = 0
connected_parts.Cut()
/obj/machinery/particle_accelerator/control_box/update_icon()
if(active)
icon_state = "control_boxp1"
else
if(use_power)
if(assembled)
icon_state = "control_boxp"
else
icon_state = "ucontrol_boxp"
else
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED, PA_CONSTRUCTION_UNWIRED)
icon_state = "control_box"
if(PA_CONSTRUCTION_PANEL_OPEN)
icon_state = "control_boxw"
else
icon_state = "control_boxc"
/obj/machinery/particle_accelerator/control_box/Topic(href, href_list)
if(..())
return
if(!interface_control)
to_chat(usr, "<span class='error'>ERROR: Request timed out. Check wire contacts.</span>")
return
if(href_list["close"])
usr << browse(null, "window=pacontrol")
usr.unset_machine()
return
if(href_list["togglep"])
if(!wires.is_cut(WIRE_POWER))
toggle_power()
else if(href_list["scan"])
part_scan()
else if(href_list["strengthup"])
if(!wires.is_cut(WIRE_STRENGTH))
add_strength()
else if(href_list["strengthdown"])
if(!wires.is_cut(WIRE_STRENGTH))
remove_strength()
updateDialog()
update_icon()
/obj/machinery/particle_accelerator/control_box/proc/strength_change()
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = strength
part.update_icon()
/obj/machinery/particle_accelerator/control_box/proc/add_strength(s)
if(assembled && (strength < strength_upper_limit))
strength++
strength_change()
message_admins("PA Control Computer increased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_VERBOSEJMP(src)]")
log_game("PA Control Computer increased to [strength] by [key_name(usr)] in [AREACOORD(src)]")
investigate_log("increased to <font color='red'>[strength]</font> by [key_name(usr)] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
/obj/machinery/particle_accelerator/control_box/proc/remove_strength(s)
if(assembled && (strength > 0))
strength--
strength_change()
message_admins("PA Control Computer decreased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_VERBOSEJMP(src)]")
log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in [AREACOORD(src)]")
investigate_log("decreased to <font color='green'>[strength]</font> by [key_name(usr)] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
/obj/machinery/particle_accelerator/control_box/power_change()
..()
if(stat & NOPOWER)
active = 0
use_power = NO_POWER_USE
else if(!stat && construction_state == PA_CONSTRUCTION_COMPLETE)
use_power = IDLE_POWER_USE
/obj/machinery/particle_accelerator/control_box/process()
if(active)
//a part is missing!
if(connected_parts.len < 6)
investigate_log("lost a connected part; It <font color='red'>powered down</font>.", INVESTIGATE_SINGULO)
toggle_power()
update_icon()
return
//emit some particles
for(var/obj/structure/particle_accelerator/particle_emitter/PE in connected_parts)
PE.emit_particle(strength)
/obj/machinery/particle_accelerator/control_box/proc/part_scan()
var/ldir = turn(dir,-90)
var/rdir = turn(dir,90)
var/odir = turn(dir,180)
var/turf/T = loc
assembled = 0
critical_machine = FALSE
var/obj/structure/particle_accelerator/fuel_chamber/F = locate() in orange(1,src)
if(!F)
return 0
setDir(F.dir)
connected_parts.Cut()
T = get_step(T,rdir)
if(!check_part(T, /obj/structure/particle_accelerator/fuel_chamber))
return 0
T = get_step(T,odir)
if(!check_part(T, /obj/structure/particle_accelerator/end_cap))
return 0
T = get_step(T,dir)
T = get_step(T,dir)
if(!check_part(T, /obj/structure/particle_accelerator/power_box))
return 0
T = get_step(T,dir)
if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/center))
return 0
T = get_step(T,ldir)
if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/left))
return 0
T = get_step(T,rdir)
T = get_step(T,rdir)
if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/right))
return 0
assembled = 1
critical_machine = TRUE //Only counts if the PA is actually assembled.
return 1
/obj/machinery/particle_accelerator/control_box/proc/check_part(turf/T, type)
var/obj/structure/particle_accelerator/PA = locate(/obj/structure/particle_accelerator) in T
if(istype(PA, type) && (PA.construction_state == PA_CONSTRUCTION_COMPLETE))
if(PA.connect_master(src))
connected_parts.Add(PA)
return 1
return 0
/obj/machinery/particle_accelerator/control_box/proc/toggle_power()
active = !active
investigate_log("turned [active?"<font color='green'>ON</font>":"<font color='red'>OFF</font>"] by [usr ? key_name(usr) : "outside forces"] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
message_admins("PA Control Computer turned [active ?"ON":"OFF"] by [usr ? ADMIN_LOOKUPFLW(usr) : "outside forces"] in [ADMIN_VERBOSEJMP(src)]")
log_game("PA Control Computer turned [active ?"ON":"OFF"] by [usr ? "[key_name(usr)]" : "outside forces"] at [AREACOORD(src)]")
if(active)
use_power = ACTIVE_POWER_USE
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = strength
part.powered = 1
part.update_icon()
else
use_power = IDLE_POWER_USE
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = null
part.powered = 0
part.update_icon()
return 1
/obj/machinery/particle_accelerator/control_box/ui_interact(mob/user)
. = ..()
if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER)))
if(!issilicon(user))
user.unset_machine()
user << browse(null, "window=pacontrol")
return
var/dat = ""
dat += "<A href='?src=[REF(src)];close=1'>Close</A><BR><BR>"
dat += "<h3>Status</h3>"
if(!assembled)
dat += "Unable to detect all parts!<BR>"
dat += "<A href='?src=[REF(src)];scan=1'>Run Scan</A><BR><BR>"
else
dat += "All parts in place.<BR><BR>"
dat += "Power:"
if(active)
dat += "On<BR>"
else
dat += "Off <BR>"
dat += "<A href='?src=[REF(src)];togglep=1'>Toggle Power</A><BR><BR>"
dat += "Particle Strength: [strength] "
dat += "<A href='?src=[REF(src)];strengthdown=1'>--</A>|<A href='?src=[REF(src)];strengthup=1'>++</A><BR><BR>"
var/datum/browser/popup = new(user, "pacontrol", name, 420, 300)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/machinery/particle_accelerator/control_box/examine(mob/user)
. = ..()
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
. += "Looks like it's not attached to the flooring."
if(PA_CONSTRUCTION_UNWIRED)
. += "It is missing some cables."
if(PA_CONSTRUCTION_PANEL_OPEN)
. += "The panel is open."
/obj/machinery/particle_accelerator/control_box/attackby(obj/item/W, mob/user, params)
var/did_something = FALSE
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
if(istype(W, /obj/item/wrench) && !isinspace())
W.play_tool_sound(src, 75)
anchored = TRUE
user.visible_message("[user.name] secures the [name] to the floor.", \
"You secure the external bolts.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
if(PA_CONSTRUCTION_UNWIRED)
if(istype(W, /obj/item/wrench))
W.play_tool_sound(src, 75)
anchored = FALSE
user.visible_message("[user.name] detaches the [name] from the floor.", \
"You remove the external bolts.")
construction_state = PA_CONSTRUCTION_UNSECURED
did_something = TRUE
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if(CC.use(1))
user.visible_message("[user.name] adds wires to the [name].", \
"You add some wires.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(PA_CONSTRUCTION_PANEL_OPEN)
if(istype(W, /obj/item/wirecutters))//TODO:Shock user if its on?
user.visible_message("[user.name] removes some wires from the [name].", \
"You remove some wires.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
else if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] closes the [name]'s access panel.", \
"You close the access panel.")
construction_state = PA_CONSTRUCTION_COMPLETE
did_something = TRUE
if(PA_CONSTRUCTION_COMPLETE)
if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] opens the [name]'s access panel.", \
"You open the access panel.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(did_something)
user.changeNext_move(CLICK_CD_MELEE)
update_state()
update_icon()
return
..()
/obj/machinery/particle_accelerator/control_box/blob_act(obj/structure/blob/B)
if(prob(50))
qdel(src)
#undef PA_CONSTRUCTION_UNSECURED
#undef PA_CONSTRUCTION_UNWIRED
#undef PA_CONSTRUCTION_PANEL_OPEN
#undef PA_CONSTRUCTION_COMPLETE
/obj/machinery/particle_accelerator/control_box
name = "Particle Accelerator Control Console"
desc = "This controls the density of the particles."
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_box"
anchored = FALSE
density = TRUE
use_power = NO_POWER_USE
idle_power_usage = 500
active_power_usage = 10000
dir = NORTH
var/strength_upper_limit = 2
var/interface_control = 1
var/list/obj/structure/particle_accelerator/connected_parts
var/assembled = 0
var/construction_state = PA_CONSTRUCTION_UNSECURED
var/active = 0
var/strength = 0
var/powered = 0
mouse_opacity = MOUSE_OPACITY_OPAQUE
/obj/machinery/particle_accelerator/control_box/Initialize()
. = ..()
wires = new /datum/wires/particle_accelerator/control_box(src)
connected_parts = list()
/obj/machinery/particle_accelerator/control_box/Destroy()
if(active)
toggle_power()
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.master = null
connected_parts.Cut()
QDEL_NULL(wires)
return ..()
/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user)
. = ..()
if(.)
return
if(construction_state == PA_CONSTRUCTION_COMPLETE)
interact(user)
else if(construction_state == PA_CONSTRUCTION_PANEL_OPEN)
wires.interact(user)
/obj/machinery/particle_accelerator/control_box/proc/update_state()
if(construction_state < PA_CONSTRUCTION_COMPLETE)
use_power = NO_POWER_USE
assembled = 0
active = 0
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = null
part.powered = 0
part.update_icon()
connected_parts.Cut()
return
if(!part_scan())
use_power = IDLE_POWER_USE
active = 0
connected_parts.Cut()
/obj/machinery/particle_accelerator/control_box/update_icon()
if(active)
icon_state = "control_boxp1"
else
if(use_power)
if(assembled)
icon_state = "control_boxp"
else
icon_state = "ucontrol_boxp"
else
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED, PA_CONSTRUCTION_UNWIRED)
icon_state = "control_box"
if(PA_CONSTRUCTION_PANEL_OPEN)
icon_state = "control_boxw"
else
icon_state = "control_boxc"
/obj/machinery/particle_accelerator/control_box/Topic(href, href_list)
if(..())
return
if(!interface_control)
to_chat(usr, "<span class='error'>ERROR: Request timed out. Check wire contacts.</span>")
return
if(href_list["close"])
usr << browse(null, "window=pacontrol")
usr.unset_machine()
return
if(href_list["togglep"])
if(!wires.is_cut(WIRE_POWER))
toggle_power()
else if(href_list["scan"])
part_scan()
else if(href_list["strengthup"])
if(!wires.is_cut(WIRE_STRENGTH))
add_strength()
else if(href_list["strengthdown"])
if(!wires.is_cut(WIRE_STRENGTH))
remove_strength()
updateDialog()
update_icon()
/obj/machinery/particle_accelerator/control_box/proc/strength_change()
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = strength
part.update_icon()
/obj/machinery/particle_accelerator/control_box/proc/add_strength(s)
if(assembled && (strength < strength_upper_limit))
strength++
strength_change()
message_admins("PA Control Computer increased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_VERBOSEJMP(src)]")
log_game("PA Control Computer increased to [strength] by [key_name(usr)] in [AREACOORD(src)]")
investigate_log("increased to <font color='red'>[strength]</font> by [key_name(usr)] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
/obj/machinery/particle_accelerator/control_box/proc/remove_strength(s)
if(assembled && (strength > 0))
strength--
strength_change()
message_admins("PA Control Computer decreased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_VERBOSEJMP(src)]")
log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in [AREACOORD(src)]")
investigate_log("decreased to <font color='green'>[strength]</font> by [key_name(usr)] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
/obj/machinery/particle_accelerator/control_box/power_change()
..()
if(stat & NOPOWER)
active = 0
use_power = NO_POWER_USE
else if(!stat && construction_state == PA_CONSTRUCTION_COMPLETE)
use_power = IDLE_POWER_USE
/obj/machinery/particle_accelerator/control_box/process()
if(active)
//a part is missing!
if(connected_parts.len < 6)
investigate_log("lost a connected part; It <font color='red'>powered down</font>.", INVESTIGATE_SINGULO)
toggle_power()
update_icon()
return
//emit some particles
for(var/obj/structure/particle_accelerator/particle_emitter/PE in connected_parts)
PE.emit_particle(strength)
/obj/machinery/particle_accelerator/control_box/proc/part_scan()
var/ldir = turn(dir,-90)
var/rdir = turn(dir,90)
var/odir = turn(dir,180)
var/turf/T = loc
assembled = 0
critical_machine = FALSE
var/obj/structure/particle_accelerator/fuel_chamber/F = locate() in orange(1,src)
if(!F)
return 0
setDir(F.dir)
connected_parts.Cut()
T = get_step(T,rdir)
if(!check_part(T, /obj/structure/particle_accelerator/fuel_chamber))
return 0
T = get_step(T,odir)
if(!check_part(T, /obj/structure/particle_accelerator/end_cap))
return 0
T = get_step(T,dir)
T = get_step(T,dir)
if(!check_part(T, /obj/structure/particle_accelerator/power_box))
return 0
T = get_step(T,dir)
if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/center))
return 0
T = get_step(T,ldir)
if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/left))
return 0
T = get_step(T,rdir)
T = get_step(T,rdir)
if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/right))
return 0
assembled = 1
critical_machine = TRUE //Only counts if the PA is actually assembled.
return 1
/obj/machinery/particle_accelerator/control_box/proc/check_part(turf/T, type)
var/obj/structure/particle_accelerator/PA = locate(/obj/structure/particle_accelerator) in T
if(istype(PA, type) && (PA.construction_state == PA_CONSTRUCTION_COMPLETE))
if(PA.connect_master(src))
connected_parts.Add(PA)
return 1
return 0
/obj/machinery/particle_accelerator/control_box/proc/toggle_power()
active = !active
investigate_log("turned [active?"<font color='green'>ON</font>":"<font color='red'>OFF</font>"] by [usr ? key_name(usr) : "outside forces"] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
message_admins("PA Control Computer turned [active ?"ON":"OFF"] by [usr ? ADMIN_LOOKUPFLW(usr) : "outside forces"] in [ADMIN_VERBOSEJMP(src)]")
log_game("PA Control Computer turned [active ?"ON":"OFF"] by [usr ? "[key_name(usr)]" : "outside forces"] at [AREACOORD(src)]")
if(active)
use_power = ACTIVE_POWER_USE
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = strength
part.powered = 1
part.update_icon()
else
use_power = IDLE_POWER_USE
for(var/CP in connected_parts)
var/obj/structure/particle_accelerator/part = CP
part.strength = null
part.powered = 0
part.update_icon()
return 1
/obj/machinery/particle_accelerator/control_box/ui_interact(mob/user)
. = ..()
if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER)))
if(!issilicon(user))
user.unset_machine()
user << browse(null, "window=pacontrol")
return
var/dat = ""
dat += "<A href='?src=[REF(src)];close=1'>Close</A><BR><BR>"
dat += "<h3>Status</h3>"
if(!assembled)
dat += "Unable to detect all parts!<BR>"
dat += "<A href='?src=[REF(src)];scan=1'>Run Scan</A><BR><BR>"
else
dat += "All parts in place.<BR><BR>"
dat += "Power:"
if(active)
dat += "On<BR>"
else
dat += "Off <BR>"
dat += "<A href='?src=[REF(src)];togglep=1'>Toggle Power</A><BR><BR>"
dat += "Particle Strength: [strength] "
dat += "<A href='?src=[REF(src)];strengthdown=1'>--</A>|<A href='?src=[REF(src)];strengthup=1'>++</A><BR><BR>"
var/datum/browser/popup = new(user, "pacontrol", name, 420, 300)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/machinery/particle_accelerator/control_box/examine(mob/user)
. = ..()
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
. += "Looks like it's not attached to the flooring."
if(PA_CONSTRUCTION_UNWIRED)
. += "It is missing some cables."
if(PA_CONSTRUCTION_PANEL_OPEN)
. += "The panel is open."
/obj/machinery/particle_accelerator/control_box/attackby(obj/item/W, mob/user, params)
var/did_something = FALSE
switch(construction_state)
if(PA_CONSTRUCTION_UNSECURED)
if(istype(W, /obj/item/wrench) && !isinspace())
W.play_tool_sound(src, 75)
anchored = TRUE
user.visible_message("[user.name] secures the [name] to the floor.", \
"You secure the external bolts.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
if(PA_CONSTRUCTION_UNWIRED)
if(istype(W, /obj/item/wrench))
W.play_tool_sound(src, 75)
anchored = FALSE
user.visible_message("[user.name] detaches the [name] from the floor.", \
"You remove the external bolts.")
construction_state = PA_CONSTRUCTION_UNSECURED
did_something = TRUE
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if(CC.use(1))
user.visible_message("[user.name] adds wires to the [name].", \
"You add some wires.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(PA_CONSTRUCTION_PANEL_OPEN)
if(istype(W, /obj/item/wirecutters))//TODO:Shock user if its on?
user.visible_message("[user.name] removes some wires from the [name].", \
"You remove some wires.")
construction_state = PA_CONSTRUCTION_UNWIRED
did_something = TRUE
else if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] closes the [name]'s access panel.", \
"You close the access panel.")
construction_state = PA_CONSTRUCTION_COMPLETE
did_something = TRUE
if(PA_CONSTRUCTION_COMPLETE)
if(istype(W, /obj/item/screwdriver))
user.visible_message("[user.name] opens the [name]'s access panel.", \
"You open the access panel.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
did_something = TRUE
if(did_something)
user.changeNext_move(CLICK_CD_MELEE)
update_state()
update_icon()
return
..()
/obj/machinery/particle_accelerator/control_box/blob_act(obj/structure/blob/B)
if(prob(50))
qdel(src)
#undef PA_CONSTRUCTION_UNSECURED
#undef PA_CONSTRUCTION_UNWIRED
#undef PA_CONSTRUCTION_PANEL_OPEN
#undef PA_CONSTRUCTION_COMPLETE