diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index e0649723e01..85a1c2b0215 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -519,29 +519,30 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine access = access_eva /datum/supply_packs/engineering/inflatable - name = "Inflatable barriers" + name = "Inflatable barriers Crate" contains = list(/obj/item/weapon/storage/briefcase/inflatable, /obj/item/weapon/storage/briefcase/inflatable, /obj/item/weapon/storage/briefcase/inflatable) cost = 20 containername = "Inflatable Barrier Crate" -/datum/supply_packs/engineering/supermatter - name = "Supermatter Crystal Crate" - contains = list(/obj/machinery/power/supermatter) - cost = 50 //Yes that's a fucking lot. - containername = "Supermatter Shard Crate" - containertype = /obj/structure/closet/crate/secure/large/reinforced +/datum/supply_packs/engineering/engine/supermatter_shard + name = "Supermatter Shard Crate" + contains = list(/obj/machinery/power/supermatter_shard) + cost = 50 //So cargo thinks twice before killing themselves with it + containertype = /obj/structure/closet/crate/secure + containername = "supermatter shard crate" access = access_ce -/datum/supply_packs/engineering/teg - name = "Thermo-Electric Generator" +/datum/supply_packs/engineering/engine/teg + name = "Thermo-Electric Generator Crate" contains = list( /obj/machinery/power/generator, /obj/machinery/atmospherics/binary/circulator, /obj/machinery/atmospherics/binary/circulator ) cost = 25 + containertype = /obj/structure/closet/crate/secure containername = "Thermo-Electric Generator Components" access = access_ce @@ -592,7 +593,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /obj/item/weapon/storage/firstaid/adv) cost = 10 containername = "advaced first aid kits crate" - + /datum/supply_packs/medical/firstaibrute name = "Brute Trauma Treatment Kits Crate" contains = list(/obj/item/weapon/storage/firstaid/brute, diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm index 75cb92b774b..3c55255eb78 100644 --- a/code/game/smoothwall.dm +++ b/code/game/smoothwall.dm @@ -86,12 +86,12 @@ shroom.icon_state = "glowshroomf" shroom.pixel_x = 0 shroom.pixel_y = 0 - for(var/obj/effect/supermatter_crystal/crystal in get_step(src,direction)) +/* for(var/obj/effect/supermatter_crystal/crystal in get_step(src,direction)) if(!crystal.floor) //crystals drop to the floor crystal.floor = 1 crystal.icon_state = "supermatter_crystalf" crystal.pixel_x = 0 - crystal.pixel_y = 0 + crystal.pixel_y = 0 */ return ..() // DE-HACK diff --git a/code/modules/mob/living/carbon/human/species/apollo.dm b/code/modules/mob/living/carbon/human/species/apollo.dm index 3acc2e08a90..1528307d566 100644 --- a/code/modules/mob/living/carbon/human/species/apollo.dm +++ b/code/modules/mob/living/carbon/human/species/apollo.dm @@ -108,6 +108,6 @@ /datum/species/nucleation/handle_death(var/mob/living/carbon/human/H) var/turf/T = get_turf(H) H.visible_message("\red[H]'s body explodes, leaving behind a pile of microscopic crystals!") - supermatter_delamination(T, 2, 0, 0) // Create a small supermatter burst upon death - new /obj/item/weapon/shard/supermatter( T ) + explosion(T, 0, 0, 2, 2) // Create a small explosion burst upon death +// new /obj/item/weapon/shard/supermatter( T ) del(H) \ No newline at end of file diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index efc75eae0c6..a1d86e5f6dd 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -244,7 +244,7 @@ /obj/singularity/proc/consume(var/atom/A) var/gain = A.singularity_act(current_size) src.energy += gain - if(istype(A, /obj/machinery/power/supermatter) && !consumedSupermatter) + if(istype(A, /obj/machinery/power/supermatter_shard) && !consumedSupermatter) desc = "[initial(desc)] It glows fiercely with inner fire." name = "supermatter-charged [initial(name)]" consumedSupermatter = 1 diff --git a/code/game/objects/effects/sm_crystals.dm b/code/modules/power/supermatter/sm_crystals.dm similarity index 100% rename from code/game/objects/effects/sm_crystals.dm rename to code/modules/power/supermatter/sm_crystals.dm diff --git a/code/game/objects/items/weapons/sm_shard.dm b/code/modules/power/supermatter/sm_shard.dm similarity index 100% rename from code/game/objects/items/weapons/sm_shard.dm rename to code/modules/power/supermatter/sm_shard.dm diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm new file mode 100644 index 00000000000..482395a852d --- /dev/null +++ b/code/modules/power/supermatter/supermatter.dm @@ -0,0 +1,299 @@ +//Ported from /vg/station13, which was in turn forked from baystation12; +//Please do not bother them with bugs from this port, however, as it has been modified quite a bit. +//Modifications include removing the world-ending full supermatter variation, and leaving only the shard. + +#define NITROGEN_RETARDATION_FACTOR 2 //Higher == N2 slows reaction more +#define THERMAL_RELEASE_MODIFIER 5 //Higher == less heat released during reaction +#define PLASMA_RELEASE_MODIFIER 750 //Higher == less plasma released by reaction +#define OXYGEN_RELEASE_MODIFIER 325 //Higher == less oxygen released at high temperature/power +#define REACTION_POWER_MODIFIER 0.55 //Higher == more overall power + + +//These would be what you would get at point blank, decreases with distance +#define DETONATION_RADS 200 +#define DETONATION_HALLUCINATION 600 + + +#define WARNING_DELAY 30 //seconds between warnings. + +/obj/machinery/power/supermatter_shard + name = "supermatter shard" + desc = "A strangely translucent and iridescent crystal that looks like it used to be part of a larger structure. You get headaches just from looking at it." + icon = 'icons/obj/supermatter.dmi' + icon_state = "darkmatter_shard" + density = 1 + anchored = 0 + light_range = 4 + + + var/gasefficency = 0.125 + + var/base_icon_state = "darkmatter_shard" + + var/damage = 0 + var/damage_archived = 0 + var/safe_alert = "Crystalline hyperstructure returning to safe operating levels." + var/warning_point = 50 + var/warning_alert = "Danger! Crystal hyperstructure instability!" + var/emergency_point = 500 + var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT." + var/explosion_point = 900 + + var/emergency_issued = 0 + + var/explosion_power = 8 + + var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning + var/power = 0 + + var/oxygen = 0 // Moving this up here for easier debugging. + + //Temporary values so that we can optimize this + //How much the bullets damage should be multiplied by when it is added to the internal variables + var/config_bullet_energy = 2 + //How much of the power is left after processing is finished? +// var/config_power_reduction_per_tick = 0.5 + //How much hallucination should it produce per unit of power? + var/config_hallucination_power = 0.1 + + var/obj/item/device/radio/radio + + //for logging + var/has_been_powered = 0 + var/has_reached_emergency = 0 + +/obj/machinery/power/supermatter_shard/New() + . = ..() + radio = new(src) + radio.listening = 0 + investigate_log("has been created.", "supermatter") + + +/obj/machinery/power/supermatter_shard/Destroy() + investigate_log("has been destroyed.", "supermatter") + qdel(radio) + . = ..() + +/obj/machinery/power/supermatter_shard/proc/explode() + investigate_log("has exploded.", "supermatter") + explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1) + qdel(src) + return + +/obj/machinery/power/supermatter_shard/process() + var/turf/L = loc + + if(isnull(L)) // We have a null turf...something is wrong, stop processing this entity. + return PROCESS_KILL + + if(!istype(L)) //We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now. + return //Yeah just stop. + + if(istype(L, /turf/space)) // Stop processing this stuff if we've been ejected. + return + + if(damage > warning_point) // while the core is still damaged and it's still worth noting its status + if((world.timeofday - lastwarning) / 10 >= WARNING_DELAY) + var/stability = num2text(round((damage / explosion_point) * 100)) + + if(damage > emergency_point) + radio.autosay("[emergency_alert] Instability: [stability]%", src) + lastwarning = world.timeofday + if(!has_reached_emergency) + investigate_log("has reached the emergency point for the first time.", "supermatter") + message_admins("[src] has reached the emergency point (JMP).") + has_reached_emergency = 1 + + else if(damage >= damage_archived) // The damage is still going up + radio.autosay("[warning_alert] Instability: [stability]%", src) + lastwarning = world.timeofday - 150 + + else // Phew, we're safe + radio.autosay("[safe_alert]", src) + lastwarning = world.timeofday + + if(damage > explosion_point) + for(var/mob/living/mob in living_mob_list) + if(istype(mob, /mob/living/carbon/human)) + //Hilariously enough, running into a closet should make you get hit the hardest. + var/mob/living/carbon/human/H = mob + H.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) + var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(mob, src) + 1) ) + mob.apply_effect(rads, IRRADIATE) + + explode() + + //Ok, get the air from the turf + var/datum/gas_mixture/env = L.return_air() + + //Remove gas from surrounding area + var/datum/gas_mixture/removed = env.remove(gasefficency * env.total_moles()) + + if(!removed || !removed.total_moles()) + damage += max((power-1600)/10, 0) + power = min(power, 1600) + return 1 + + damage_archived = damage + damage = max( damage + ( (removed.temperature - 800) / 150 ) , 0 ) + //Ok, 100% oxygen atmosphere = best reaction + //Maxes out at 100% oxygen pressure + oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / MOLES_CELLSTANDARD, 1), 0) + + var/temp_factor = 50 + + if(oxygen > 0.8) + // with a perfect gas mix, make the power less based on heat + icon_state = "[base_icon_state]_glow" + else + // in normal mode, base the produced energy around the heat + temp_factor = 30 + icon_state = base_icon_state + + power = max( (removed.temperature * temp_factor / T0C) * oxygen + power, 0) //Total laser power plus an overload + + //We've generated power, now let's transfer it to the collectors for storing/usage + transfer_energy() + + var/device_energy = power * REACTION_POWER_MODIFIER + + //To figure out how much temperature to add each tick, consider that at one atmosphere's worth + //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature + //that the device energy is around 2140. At that stage, we don't want too much heat to be put out + //Since the core is effectively "cold" + + //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock + //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall. + removed.temperature += (device_energy / THERMAL_RELEASE_MODIFIER) + + removed.temperature = max(0, min(removed.temperature, 2500)) + + //Calculate how much gas to release + removed.toxins += max(device_energy / PLASMA_RELEASE_MODIFIER, 0) + + removed.oxygen += max((device_energy + removed.temperature - T0C) / OXYGEN_RELEASE_MODIFIER, 0) + + env.merge(removed) + + for(var/mob/living/carbon/human/l in view(src, min(7, round(power ** 0.25)))) // If they can see it without mesons on. Bad on them. + if(!istype(l.glasses, /obj/item/clothing/glasses/meson)) + l.hallucination = max(0, min(200, l.hallucination + power * config_hallucination_power * sqrt( 1 / max(1, get_dist(l, src)) ) ) ) + + for(var/mob/living/l in range(src, round((power / 100) ** 0.25))) + var/rads = (power / 10) * sqrt( 1 / max(get_dist(l, src),1) ) + l.apply_effect(rads, IRRADIATE) + + power -= (power/500)**3 + + return 1 + +/obj/machinery/power/supermatter_shard + +/obj/machinery/power/supermatter_shard/bullet_act(var/obj/item/projectile/Proj) + var/turf/L = loc + if(!istype(L)) // We don't run process() when we are in space + return 0 // This stops people from being able to really power up the supermatter + // Then bring it inside to explode instantly upon landing on a valid turf. + + + if(Proj.flag != "bullet") + power += Proj.damage * config_bullet_energy + if(!has_been_powered) + investigate_log("has been powered for the first time.", "supermatter") + message_admins("[src] has been powered for the first time (JMP).") + has_been_powered = 1 + else + damage += Proj.damage * config_bullet_energy + return 0 + +/obj/machinery/power/supermatter_shard/singularity_act() + var/gain = 100 + investigate_log("Supermatter shard consumed by singularity.","singulo") + message_admins("Singularity has consumed a supermatter shard and can now become stage six.") + visible_message("[src] is consumed by the singularity!") + for(var/mob/M in mob_list) + M << 'sound/effects/supermatter.ogg' //everyone goan know bout this + M << "A horrible screeching fills your ears, and a wave of dread washes over you..." + qdel(src) + return(gain) + +/obj/machinery/power/supermatter_shard/attack_robot(mob/user as mob) + if(Adjacent(user)) + return attack_hand(user) + else + user << "You attempt to interface with the control circuits but find they are not connected to your network. Maybe in a future firmware update." + return + +/obj/machinery/power/supermatter_shard/attack_ai(mob/user as mob) + user << "You attempt to interface with the control circuits but find they are not connected to your network. Maybe in a future firmware update." + +/obj/machinery/power/supermatter_shard/attack_hand(mob/living/user as mob) + if(!istype(user)) + return + user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... \his body starts to glow and bursts into flames before flashing into ash.",\ + "You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\ + "You hear an unearthly noise as a wave of heat washes over you.") + + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + + Consume(user) + +/obj/machinery/power/supermatter_shard/proc/transfer_energy() + for(var/obj/machinery/power/rad_collector/R in rad_collectors) + if(get_dist(R, src) <= 15) // Better than using orange() every process + R.receive_pulse(power/10) + return + +/obj/machinery/power/supermatter_shard/attackby(obj/item/W as obj, mob/living/user as mob, params) + if(!istype(W) || (W.flags & ABSTRACT) || !istype(user)) + return + if(user.drop_item(W)) + Consume(W) + user.visible_message("As [user] touches \the [src] with \a [W], silence fills the room...",\ + "You touch \the [src] with \the [W], and everything suddenly goes silent.\"\n\The [W] flashes into dust as you flinch away from \the [src].",\ + "Everything suddenly goes silent.") + + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + + user.apply_effect(150, IRRADIATE) + + +/obj/machinery/power/supermatter_shard/Bumped(atom/AM as mob|obj) + if(istype(AM, /mob/living)) + AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.",\ + "You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\ + "You hear an unearthly noise as a wave of heat washes over you.") + else if(isobj(AM) && !istype(AM, /obj/effect)) + AM.visible_message("\The [AM] smacks into \the [src] and rapidly flashes to ash.",\ + "You hear a loud crack as you are washed with a wave of heat.") + else + return + + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + + Consume(AM) + + +/obj/machinery/power/supermatter_shard/proc/Consume(atom/movable/AM) + if(istype(AM, /mob/living)) + var/mob/living/user = AM + user.dust() + power += 200 + message_admins("[src] has consumed [key_name_admin(user)]? (FLW) (JMP).") + investigate_log("has consumed [key_name(user)].", "supermatter") + else if(isobj(AM) && !istype(AM, /obj/effect)) + investigate_log("has consumed [AM].", "supermatter") + qdel(AM) + + power += 200 + + //Some poor sod got eaten, go ahead and irradiate people nearby. + for(var/mob/living/L in range(10)) + var/rads = 500 * sqrt( 1 / (get_dist(L, src) + 1) ) + L.apply_effect(rads, IRRADIATE) + investigate_log("has irradiated [L] after consuming [AM].", "supermatter") + if(L in view()) + L.show_message("As \the [src] slowly stops resonating, you find your skin covered in new radiation burns.", 1,\ + "The unearthly ringing subsides and you notice you have new radiation burns.", 2) + else + L.show_message("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns.", 2) diff --git a/code/modules/supermatter/wall.dm b/code/modules/power/supermatter/wall.dm similarity index 100% rename from code/modules/supermatter/wall.dm rename to code/modules/power/supermatter/wall.dm diff --git a/code/modules/research/xenoarchaeology/artifact/artifact.dm b/code/modules/research/xenoarchaeology/artifact/artifact.dm index 2c3946b0428..8730b04e063 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact.dm @@ -13,10 +13,9 @@ artifact_id = "[pick("kappa","sigma","antaeres","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]-[rand(100,999)]" artifact_find_type = pick(\ - 5;/obj/machinery/power/supermatter,\ 5;/obj/structure/constructshell,\ 5;/obj/machinery/wish_granter,\ - 25;/obj/machinery/power/supermatter/shard,\ + 25;/obj/machinery/power/supermatter_shard,\ 50;/obj/structure/cult/pylon,\ 100;/obj/machinery/auto_cloner,\ 100;/obj/machinery/giga_drill,\ diff --git a/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm b/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm index 3d2ec6c32c1..cbc755e2c22 100644 --- a/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm +++ b/code/modules/research/xenoarchaeology/machinery/artifact_analyser.dm @@ -135,10 +135,7 @@ ecosystem involving self cannibalism and a symbiotic relationship with the contained liquid.

\ Structure is composed of a carbo-titanium alloy with interlaced reinforcing energy fields, and the contained liquid \ resembles proto-plasmic residue supportive of single cellular developmental conditions." - if(/obj/machinery/power/supermatter) - return "Super dense plasma clump - Appears to have been shaped or hewn, structure is composed of matter 2000% denser than ordinary carbon matter residue.\ - Potential application as unrefined plasma source." - if(/obj/machinery/power/supermatter) + if(/obj/machinery/power/supermatter_shard) return "Super dense plasma clump - Appears to have been shaped or hewn, structure is composed of matter 2000% denser than ordinary carbon matter residue.\ Potential application as unrefined plasma source." if(/obj/structure/constructshell) diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm deleted file mode 100644 index 92264de763a..00000000000 --- a/code/modules/supermatter/supermatter.dm +++ /dev/null @@ -1,473 +0,0 @@ - -#define NITROGEN_RETARDATION_FACTOR 0.15 //Higher == N2 slows reaction more -#define THERMAL_RELEASE_MODIFIER 750 //Higher == more heat released during reaction -#define PLASMA_RELEASE_MODIFIER 1500 //Higher == less plasma released by reaction -#define OXYGEN_RELEASE_MODIFIER 1500 //Higher == less oxygen released at high temperature/power -#define REACTION_POWER_MODIFIER 1.1 //Higher == more overall power - -/* - How to tweak the SM - - POWER_FACTOR directly controls how much power the SM puts out at a given level of excitation (power var). Making this lower means you have to work the SM harder to get the same amount of power. - CRITICAL_TEMPERATURE The temperature at which the SM starts taking damage. - - CHARGING_FACTOR Controls how much emitter shots excite the SM. - DAMAGE_RATE_LIMIT Controls the maximum rate at which the SM will take damage due to high temperatures. -*/ - -//Controls how much power is produced by each collector in range - this is the main parameter for tweaking SM balance, as it basically controls how the power variable relates to the rest of the game. -#define POWER_FACTOR 1.0 -#define DECAY_FACTOR 700 //Affects how fast the supermatter power decays -#define CRITICAL_TEMPERATURE 5000 //K -#define CHARGING_FACTOR 0.05 -#define DAMAGE_RATE_LIMIT 3 //damage rate cap at power = 300, scales linearly with power - - -//These would be what you would get at point blank, decreases with distance -#define DETONATION_RADS 200 -#define DETONATION_HALLUCINATION 600 - -#define TRANSFORM_DISTANCE_MOD 2 // Size/this is maximum distance from SM during burst for transformation to Nucleation - -#define WARNING_DELAY 30 //seconds between warnings. - -/obj/machinery/power/supermatter - name = "Supermatter" - desc = "A strangely translucent and iridescent crystal. \red You get headaches just from looking at it." - icon = 'icons/obj/engine.dmi' - icon_state = "darkmatter" - density = 1 - anchored = 0 - light_range = 4 - - var/gasefficency = 0.25 - - var/base_icon_state = "darkmatter" - - var/damage = 0 - var/damage_archived = 0 - var/safe_alert = "Crystaline hyperstructure returning to safe operating levels." - var/safe_warned = 0 - var/warning_point = 100 - var/warning_alert = "Danger! Crystal hyperstructure instability!" - var/emergency_point = 700 - var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT." - var/explosion_point = 1000 - - light_color = "#8A8A00" - var/warning_color = "#B8B800" - var/emergency_color = "#D9D900" - - var/grav_pulling = 0 - var/pull_radius = 14 - // Time in ticks between delamination ('exploding') and exploding (as in the actual boom) - var/pull_time = 100 - var/explosion_power = 8 - - var/emergency_issued = 0 - - // Time in 1/10th of seconds since the last sent warning - var/lastwarning = 0 - - // This stops spawning redundand explosions. Also incidentally makes supermatter unexplodable if set to 1. - var/exploded = 0 - - var/power = 0 - var/oxygen = 0 - - //Temporary values so that we can optimize this - //How much the bullets damage should be multiplied by when it is added to the internal variables - var/config_bullet_energy = 2 - //How much of the power is left after processing is finished? -// var/config_power_reduction_per_tick = 0.5 - //How much hallucination should it produce per unit of power? - var/config_hallucination_power = 0.1 - - var/obj/item/device/radio/radio - - var/debug = 0 - var/uneatable = list(/turf/space, /obj/effect/overlay, /atom/movable/lighting_overlay, /mob/dead, /mob/camera, /mob/new_player) - -/obj/machinery/power/supermatter/New() - . = ..() - radio = new (src) - - -/obj/machinery/power/supermatter/Del() - del radio - . = ..() - -/obj/machinery/power/supermatter/proc/explode() - message_admins("Supermatter exploded at ([x],[y],[z] - JMP)",0,1) - log_game("Supermatter exploded at ([x],[y],[z])") - anchored = 1 - grav_pulling = 1 - exploded = 1 - spawn(pull_time) - var/turf/epicenter = get_turf(src) - explosion(epicenter, explosion_power, explosion_power*2, explosion_power*3, explosion_power*4, 1) - supermatter_delamination( epicenter, explosion_power*4, 1 ) - del src - return - -//Changes color and light_range of the light to these values if they were not already set -/obj/machinery/power/supermatter/proc/shift_light(var/lum, var/clr) - if(light_color != clr) - light_color = clr - if(light_range != lum) - set_light(lum) - -/obj/machinery/power/supermatter/proc/announce_warning() - var/integrity = damage / explosion_point - integrity = round(100 - integrity * 100) - integrity = integrity < 0 ? 0 : integrity - var/alert_msg = " Integrity at [integrity]%" - - if(damage > emergency_point) - alert_msg = emergency_alert + alert_msg - lastwarning = world.timeofday - WARNING_DELAY * 4 - else if(damage >= damage_archived) // The damage is still going up - safe_warned = 0 - alert_msg = warning_alert + alert_msg - lastwarning = world.timeofday - else if(!safe_warned) - safe_warned = 1 // We are safe, warn only once - alert_msg = safe_alert - lastwarning = world.timeofday - else - alert_msg = null - if(alert_msg) - radio.autosay(alert_msg, "Supermatter Monitor") - -/obj/machinery/power/supermatter/process() - - var/turf/L = loc - - if(isnull(L)) // We have a null turf...something is wrong, stop processing this entity. - return PROCESS_KILL - - if(!istype(L)) //We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now. - return //Yeah just stop. - - if(damage > explosion_point) - if(!exploded) - if(!istype(L, /turf/space)) - announce_warning() - explode() - else if(damage > warning_point) // while the core is still damaged and it's still worth noting its status - shift_light(5, warning_color) - if(damage > emergency_point) - shift_light(7, emergency_color) - if(!istype(L, /turf/space) && (world.timeofday - lastwarning) >= WARNING_DELAY * 10) - announce_warning() - else - shift_light(4,initial(light_color)) - if(grav_pulling) - supermatter_pull() - - //Ok, get the air from the turf - var/datum/gas_mixture/removed = null - var/datum/gas_mixture/env = null - - //ensure that damage doesn't increase too quickly due to super high temperatures resulting from no coolant, for example. We dont want the SM exploding before anyone can react. - //We want the cap to scale linearly with power (and explosion_point). Let's aim for a cap of 5 at power = 300 (based on testing, equals roughly 5% per SM alert announcement). - var/damage_inc_limit = (power/300)*(explosion_point/1000)*DAMAGE_RATE_LIMIT - - if(!istype(L, /turf/space)) - env = L.return_air() - removed = env.remove(gasefficency * env.total_moles()) //Remove gas from surrounding area - - if(!env || !removed || !removed.total_moles()) - damage += max((power - 15*POWER_FACTOR)/10, 0) - else if (grav_pulling) //If supermatter is detonating, remove all air from the zone - env.remove(env.total_moles()) - else - damage_archived = damage - - damage = max( damage + min( ( (removed.temperature - CRITICAL_TEMPERATURE) / 150 ), damage_inc_limit ) , 0 ) - //Ok, 100% oxygen atmosphere = best reaction - //Maxes out at 100% oxygen pressure - oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / removed.total_moles(), 1), 0) - - //calculate power gain for oxygen reaction - var/temp_factor - var/equilibrium_power - if (oxygen > 0.8) - //If chain reacting at oxygen == 1, we want the power at 800 K to stabilize at a power level of 400 - equilibrium_power = 400 - icon_state = "[base_icon_state]_glow" - else - //If chain reacting at oxygen == 1, we want the power at 800 K to stabilize at a power level of 250 - equilibrium_power = 250 - icon_state = base_icon_state - - temp_factor = ( (equilibrium_power/DECAY_FACTOR)**3 )/800 - power = max( (removed.temperature * temp_factor) * oxygen + power, 0) - - //We've generated power, now let's transfer it to the collectors for storing/usage - transfer_energy() - - var/device_energy = power * REACTION_POWER_MODIFIER - - - //Calculate how much gas to release - removed.toxins += max(device_energy / PLASMA_RELEASE_MODIFIER, 0) - - removed.oxygen += max((device_energy + removed.temperature - T0C) / OXYGEN_RELEASE_MODIFIER, 0) - - env.merge(removed) - - - for(var/mob/living/carbon/human/l in view(src, min(7, round(sqrt(power/6))))) // If they can see it without mesons on. Bad on them. - if(!istype(l.glasses, /obj/item/clothing/glasses/meson)) - l.hallucination = max(0, min(200, l.hallucination + power * config_hallucination_power * sqrt( 1 / max(1,get_dist(l, src)) ) ) ) - - //adjusted range so that a power of 300 (pretty high) results in 8 tiles, roughly the distance from the core to the engine monitoring room. - for(var/mob/living/l in range(src, round(sqrt(power / 5)))) - var/rads = (power / 10) * sqrt( 1 / get_dist(l, src) ) - l.apply_effect(rads, IRRADIATE) - - power -= (power/DECAY_FACTOR)**3 //energy losses due to radiation - - return 1 - - -/obj/machinery/power/supermatter/bullet_act(var/obj/item/projectile/Proj) - var/turf/L = loc - if(!istype(L)) // We don't run process() when we are in space - return 0 // This stops people from being able to really power up the supermatter - // Then bring it inside to explode instantly upon landing on a valid turf. - - - if(istype(Proj, /obj/item/projectile/beam)) - power += Proj.damage * config_bullet_energy * CHARGING_FACTOR / POWER_FACTOR - else - damage += Proj.damage * config_bullet_energy - return 0 - -/obj/machinery/power/supermatter/singularity_act() - var/gain = 100 - investigate_log("Supermatter shard consumed by singularity.","singulo") - message_admins("Singularity has consumed a supermatter shard and can now become stage six.") - visible_message("[src] is consumed by the singularity!") - for(var/mob/M in mob_list) - M << 'sound/effects/supermatter.ogg' //everyone goan know bout this - M << "A horrible screeching fills your ears, and a wave of dread washes over you..." - qdel(src) - return(gain) - -/obj/machinery/power/supermatter/attack_robot(mob/user as mob) - if(Adjacent(user)) - return attack_hand(user) - else - user << "You attempt to interface with the control circuits but find they are not connected to your network. Maybe in a future firmware update." - return - -/obj/machinery/power/supermatter/attack_ai(mob/user as mob) - user << "You attempt to interface with the control circuits but find they are not connected to your network. Maybe in a future firmware update." - -/obj/machinery/power/supermatter/attack_hand(mob/user as mob) - if(istype(user,/mob/living/carbon/human/nucleation)) // Nucleation's biology doesn't react to this - return - - user.visible_message("\The [user] reaches out and touches \the [src], inducing a resonance... \his body starts to glow and bursts into flames before flashing into ash.",\ - "You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\ - "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.") - - Consume(user) - -/obj/machinery/power/supermatter/proc/transfer_energy() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) - var/distance = get_dist(R, src) - if(distance <= 15) - //for collectors using standard plasma tanks at 1013 kPa, the actual power generated will be this power*POWER_FACTOR*20*29 = power*POWER_FACTOR*580 - R.receive_pulse(power * POWER_FACTOR * (min(3/distance, 1))**2) - return - -/obj/machinery/power/supermatter/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob) - user.visible_message("\The [user] touches \a [W] to \the [src] as a silence fills the room...",\ - "You touch \the [W] to \the [src] when everything suddenly goes silent.\"\n\The [W] flashes into dust as you flinch away from \the [src].",\ - "Everything suddenly goes silent.") - - user.unEquip(W) - Consume(W) - - user.apply_effect(150, IRRADIATE) - - -/obj/machinery/power/supermatter/Bumped(atom/AM as mob|obj) - if(istype(AM, /mob/living)) - if(istype(AM,/mob/living/carbon/human/nucleation)) // Nucleation's biology doesn't react to this - return - AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.",\ - "You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\ - "You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.") - else if(!grav_pulling) //To prevent spam, detonating supermatter does not indicate non-mobs being destroyed - AM.visible_message("\The [AM] smacks into \the [src] and rapidly flashes to ash.",\ - "You hear a loud crack as you are washed with a wave of heat.") - - Consume(AM) - - -/obj/machinery/power/supermatter/proc/Consume(var/mob/living/user) - if(istype(user,/mob/living/carbon/human/nucleation)) // Nucleation's biology doesn't react to this - return - - if(istype(user)) - user.dust() - power += 200 - else - del user - - power += 200 - - //Some poor sod got eaten, go ahead and irradiate people nearby. - for(var/mob/living/l in range(10)) - if(l in view()) - l.show_message("As \the [src] slowly stops resonating, you find your skin covered in new radiation burns.", 1,\ - "The unearthly ringing subsides and you notice you have new radiation burns.", 2) - else - l.show_message("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns.", 2) - var/rads = 500 * sqrt( 1 / (get_dist(l, src) + 1) ) - l.apply_effect(rads, IRRADIATE) - - -/obj/machinery/power/supermatter/proc/supermatter_pull() - //following is adapted from singulo code - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 1 - // Let's just make this one loop. - for(var/atom/X in orange(pull_radius,src)) - // Movable atoms only - if(istype(X, /atom/movable)) - if(is_type_in_list(X, uneatable)) continue - if(((X) && (!istype(X,/mob/living/carbon/human)))) - step_towards(X,src) - if(istype(X, /obj)) //unanchored objects pulled twice as fast - var/obj/O = X - if(!O.anchored) - step_towards(X,src) - else - step_towards(X,src) - if(istype(X, /obj/structure/window)) //shatter windows - var/obj/structure/window/W = X - W.ex_act(2.0) - else if(istype(X,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = X - if(istype(H.shoes,/obj/item/clothing/shoes/magboots)) - var/obj/item/clothing/shoes/magboots/M = H.shoes - if(M.magpulse) - step_towards(H,src) //step just once with magboots - continue - step_towards(H,src) //step twice - step_towards(H,src) - - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 0 - return - - -proc/supermatter_delamination(var/turf/epicenter, var/size, var/transform_mobs = 0, var/adminlog = 1) - spawn(0) - var/start = world.timeofday - epicenter = get_turf(epicenter) - if(!epicenter) return - - if(adminlog) - message_admins("Supermatter delamination with size ([size]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z] - JMP)") - log_game("Supermatter delamination with size ([size]) in area [epicenter.loc.name] ") - - playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(size*2,1) ) - playsound(epicenter, "explosion", 100, 1, round(size,1) ) - - if(defer_powernet_rebuild != 2) - defer_powernet_rebuild = 1 - - var/x = epicenter.x - var/y = epicenter.y - var/z = epicenter.z - - epicenter.ChangeTurf( /turf/simulated/floor/plating/smatter ) - - for(var/mob/living/mob in orange( epicenter, size*2 )) // Irradiate area twice the size of the main blast - if(epicenter.z == mob.loc.z) - if( ishuman(mob) ) - //Hilariously enough, running into a closet should make you get hit the hardest. - var/mob/living/carbon/human/H = mob - H.hallucination += max(50, min(size*10, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, epicenter) + 1)) ) ) - var/rads = size*10 * sqrt( 1 / (get_dist(mob, epicenter) + 1) ) - mob.apply_effect(rads, IRRADIATE) - - for(var/i=0, i