From 73561bc24ac5235a80103226d1d9932e58379983 Mon Sep 17 00:00:00 2001 From: shizcalev Date: Mon, 7 Aug 2017 16:00:14 -0400 Subject: [PATCH] Revert: Minor supermatter code refactor(#28848) Moves repeated code into procs, as well as adding processing handicaps/damage hardcaps to things that really need them. (reverted from commit 59ce8fa83286ca8ea703188fd9834b8a624b2e8e) --- code/modules/power/supermatter/supermatter.dm | 265 ++++++++---------- 1 file changed, 120 insertions(+), 145 deletions(-) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 6e8b964460f..816cd978743 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -25,7 +25,6 @@ #define HEAT_PENALTY_THRESHOLD 40 //Higher == Crystal safe operational temperature is higher. #define DAMAGE_HARDCAP 0.0025 #define DAMAGE_INCREASE_MULTIPLIER 0.25 -#define PROCESSING_HANDICAP 0.25 #define THERMAL_RELEASE_MODIFIER 5 //Higher == less heat released during reaction, not to be confused with the above values @@ -85,6 +84,7 @@ var/emergency_issued = FALSE var/explosion_power = 12 + var/temp_factor = 30 var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning var/power = 0 @@ -107,17 +107,8 @@ var/mole_heat_penalty = 0 var/freon_transmit_modifier = 1 - var/device_energy = 0 - - var/has_gas = TRUE //Whether we have gas to process. - var/matter_power = 0 - var/temp_factor = 30 - var/temp_factor_normal = 30 - var/temp_factor_optimal = 50 - - //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 @@ -256,7 +247,9 @@ //Ok, get the air from the turf var/datum/gas_mixture/env = T.return_air() + var/datum/gas_mixture/removed + if(produces_gas) //Remove gas from surrounding area removed = env.remove(gasefficency * env.total_moles()) @@ -264,130 +257,141 @@ // Pass all the gas related code an empty gas container removed = new() - //Check if we have gas. - if(!removed || !removed.total_moles() || isspaceturf(T)) - has_gas = FALSE - else - has_gas = TRUE + if(!removed || !removed.total_moles() || isspaceturf(T)) //we're in space or there is no gas to process + if(takes_damage) + damage += max((power-1600)/10, 0) + return 1 - //Process negative effects. - if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point) - SM_autoprocess_lightning() - SM_autoprocess_anomaly() - - //Process powerloss - SM_autoprocess_powerloss() - - //Process radiation - SM_autoprocess_proximity() - - - //Process damage. + damage_archived = damage if(takes_damage) - SM_autoprocess_damage(removed, T) + //causing damage + damage = max(damage + (max(removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0) + damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0) + damage = max(damage + (max(combined_gas - MOLE_PENALTY_THRESHOLD, 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0) - //Process matter - SM_autoprocess_matter() + //healing damage + if(combined_gas < MOLE_PENALTY_THRESHOLD) + damage = max(damage + (min(removed.temperature - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ), 0) - //Process alerts - SM_autoprocess_alert() + //capping damage + damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage) + if(damage > damage_archived && prob(10)) + playsound(get_turf(src), 'sound/effects/empulse.ogg', 50, 1) - //Process explosion check - SM_autoprocess_explosioncheck() - - //Process temperature factor - SM_autoprocess_tempfactor() - - //Process gasses - SM_autoprocess_gas(removed, env) - - return TRUE - -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_gas(datum/gas_mixture/removed, datum/gas_mixture/env) removed.assert_gases("o2", "plasma", "co2", "n2o", "n2", "freon") //calculating gas related values combined_gas = max(removed.total_moles(), 0) - if(combined_gas) - plasmacomp = max(removed.gases["plasma"][MOLES]/combined_gas, 0) - o2comp = max(removed.gases["o2"][MOLES]/combined_gas, 0) - co2comp = max(removed.gases["co2"][MOLES]/combined_gas, 0) - n2ocomp = max(removed.gases["n2o"][MOLES]/combined_gas, 0) - n2comp = max(removed.gases["n2"][MOLES]/combined_gas, 0) - freoncomp = max(removed.gases["freon"][MOLES]/combined_gas, 0) - else - plasmacomp = 0 - o2comp = 0 - co2comp = 0 - n2ocomp = 0 - n2comp = 0 - freoncomp = 0 + + plasmacomp = max(removed.gases["plasma"][MOLES]/combined_gas, 0) + o2comp = max(removed.gases["o2"][MOLES]/combined_gas, 0) + co2comp = max(removed.gases["co2"][MOLES]/combined_gas, 0) + + n2ocomp = max(removed.gases["n2o"][MOLES]/combined_gas, 0) + n2comp = max(removed.gases["n2"][MOLES]/combined_gas, 0) + freoncomp = max(removed.gases["freon"][MOLES]/combined_gas, 0) + gasmix_power_ratio = min(max(plasmacomp + o2comp + co2comp - n2comp - freoncomp, 0), 1) + dynamic_heat_modifier = max((plasmacomp * PLASMA_HEAT_PENALTY)+(o2comp * OXYGEN_HEAT_PENALTY)+(co2comp * CO2_HEAT_PENALTY)+(n2comp * NITROGEN_HEAT_MODIFIER), 0.5) dynamic_heat_resistance = max(n2ocomp * N2O_HEAT_RESISTANCE, 1) + power_transmission_bonus = max((plasmacomp * PLASMA_TRANSMIT_MODIFIER) + (o2comp * OXYGEN_TRANSMIT_MODIFIER), 0) + freon_transmit_modifier = max(1-(freoncomp * FREON_TRANSMIT_PENALTY), 0) + //more moles of gases are harder to heat than fewer, so let's scale heat damage around them mole_heat_penalty = max(combined_gas / MOLE_HEAT_PENALTY, 0.25) + if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && co2comp > POWERLOSS_INHIBITION_GAS_THRESHOLD) powerloss_dynamic_scaling = Clamp(powerloss_dynamic_scaling + Clamp(co2comp - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1) else powerloss_dynamic_scaling = Clamp(powerloss_dynamic_scaling - 0.05,0, 1) powerloss_inhibitor = Clamp(1-(powerloss_dynamic_scaling * Clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD,1 ,1.5)),0 ,1) - power = max(((removed.temperature * temp_factor / T0C) * gasmix_power_ratio + power) * PROCESSING_HANDICAP, 0) //Total laser power plus an overload + + if(matter_power) + var/removed_matter = max(matter_power/MATTER_POWER_CONVERSION, 40) + power = max(power + removed_matter, 0) + matter_power = max(matter_power - removed_matter, 0) + + var/temp_factor = 50 + + if(gasmix_power_ratio > 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) * gasmix_power_ratio + 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 * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER) - removed.temperature = max(0, min(removed.temperature, 2500 * dynamic_heat_modifier) * PROCESSING_HANDICAP) + + removed.temperature = max(0, min(removed.temperature, 2500 * dynamic_heat_modifier)) + //Calculate how much gas to release - removed.gases["plasma"][MOLES] += max(((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER) * PROCESSING_HANDICAP, 0) - removed.gases["o2"][MOLES] += max((((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER) * PROCESSING_HANDICAP, 0) + removed.gases["plasma"][MOLES] += max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0) + + removed.gases["o2"][MOLES] += max(((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0) + if(combined_gas < 50) - removed.gases["freon"][MOLES] = max(((removed.gases["freon"][MOLES] + device_energy) * freoncomp / FREON_BREEDING_MODIFIER) * PROCESSING_HANDICAP, 0) + removed.gases["freon"][MOLES] = max((removed.gases["freon"][MOLES] + device_energy) * freoncomp / FREON_BREEDING_MODIFIER, 0) + if(produces_gas) env.merge(removed) air_update_turf() -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_tempfactor() - if(gasmix_power_ratio > 0.8) - // with a perfect gas mix, make the power less based on heat - temp_factor = temp_factor_optimal - icon_state = "[base_icon_state]_glow" - else - // in normal mode, base the produced energy around the heat - temp_factor = temp_factor_normal - icon_state = base_icon_state + for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them. + if(!istype(l.glasses, /obj/item/clothing/glasses/meson)) + var/D = sqrt(1 / max(1, get_dist(l, src))) + l.hallucination += power * config_hallucination_power * D + l.hallucination = Clamp(0, 200, l.hallucination) -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_powerloss() - power -= ((power/500)**3) * powerloss_inhibitor - device_energy = power * REACTION_POWER_MODIFIER * PROCESSING_HANDICAP + 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.rad_act(rads) + + if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point) + + if(power > POWER_PENALTY_THRESHOLD) + playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10) + supermatter_zap(src, 5, min(power*2, 20000)) + supermatter_zap(src, 5, min(power*2, 20000)) + if(power > SEVERE_POWER_PENALTY_THRESHOLD) + supermatter_zap(src, 5, min(power*2, 20000)) + if(power > CRITICAL_POWER_PENALTY_THRESHOLD) + supermatter_zap(src, 5, min(power*2, 20000)) + else if (damage > damage_penalty_point && prob(20)) + playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10) + supermatter_zap(src, 5, Clamp(power*2, 4000, 20000)) + + if(prob(15) && power > POWER_PENALTY_THRESHOLD) + supermatter_pull(src, power/750) + if(prob(5)) + supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10)) + if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(5) || prob(1)) + supermatter_anomaly_gen(src, GRAVITATIONAL_ANOMALY, rand(5, 10)) + if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2) || prob(0.3) && power > POWER_PENALTY_THRESHOLD) + supermatter_anomaly_gen(src, PYRO_ANOMALY, rand(5, 10)) -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_explosioncheck() - if(damage > explosion_point) - for(var/mob in GLOB.living_mob_list) - var/mob/living/L = mob - if(istype(L) && L.z == 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(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) - var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(L, src) + 1) ) - L.rad_act(rads) - explode() -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_matter() - if(matter_power) - var/removed_matter = max((matter_power/MATTER_POWER_CONVERSION) * PROCESSING_HANDICAP, 40) - power = max((power + removed_matter) * PROCESSING_HANDICAP, 0) - matter_power = max(matter_power - removed_matter, 0) -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_alert() if(damage > warning_point) // while the core is still damaged and it's still worth noting its status if((REALTIMEOFDAY - lastwarning) / 10 >= WARNING_DELAY) alarm() + if(damage > emergency_point) radio.talk_into(src, "[emergency_alert] Integrity: [get_integrity()]%", common_channel, get_spans(), get_default_language()) lastwarning = REALTIMEOFDAY @@ -398,70 +402,36 @@ else if(damage >= damage_archived) // The damage is still going up radio.talk_into(src, "[warning_alert] Integrity: [get_integrity()]%", engineering_channel, get_spans(), get_default_language()) lastwarning = REALTIMEOFDAY - (WARNING_DELAY * 5) + else // Phew, we're safe radio.talk_into(src, "[safe_alert] Integrity: [get_integrity()]%", engineering_channel, get_spans(), get_default_language()) lastwarning = REALTIMEOFDAY + if(power > POWER_PENALTY_THRESHOLD) radio.talk_into(src, "Warning: Hyperstructure has reached dangerous power level.", engineering_channel, get_spans(), get_default_language()) if(powerloss_inhibitor < 0.5) radio.talk_into(src, "DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.", engineering_channel, get_spans(), get_default_language()) + if(combined_gas > MOLE_PENALTY_THRESHOLD) radio.talk_into(src, "Warning: Critical coolant mass reached.", engineering_channel, get_spans(), get_default_language()) -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_proximity() - for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them. - if(!istype(l.glasses, /obj/item/clothing/glasses/meson)) - var/D = sqrt(1 / max(1, get_dist(l, src))) - l.hallucination += (power * config_hallucination_power * D) * PROCESSING_HANDICAP - l.hallucination = Clamp(0, 200, l.hallucination) - 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))) * PROCESSING_HANDICAP - l.rad_act(rads) - if(has_gas) //no gas no power for you! - for(var/obj/machinery/power/rad_collector/R in GLOB.rad_collectors) - if(R.z == z && get_dist(R, src) <= 15) //Better than using orange() every process - R.receive_pulse(power * (1 + power_transmission_bonus)/10 * freon_transmit_modifier) + if(damage > explosion_point) + for(var/mob in GLOB.living_mob_list) + var/mob/living/L = mob + if(istype(L) && L.z == 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(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) + var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(L, src) + 1) ) + L.rad_act(rads) -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_damage(datum/gas_mixture/removed, turf/T) - damage_archived = damage - if(!removed || !removed.total_moles() || isspaceturf(T)) //we're in space or there is no gas to process - damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),max((power-1600)/10, 0) + damage) - else - //causing damage - damage = max(damage + ((max(removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER) * PROCESSING_HANDICAP, 0) - damage = max(damage + ((max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER) * PROCESSING_HANDICAP, 0) - damage = max(damage + ((max(combined_gas - MOLE_PENALTY_THRESHOLD, 0)/80) * DAMAGE_INCREASE_MULTIPLIER) * PROCESSING_HANDICAP, 0) - //healing damage - if(has_gas) //No gas you go kaboom. - if(combined_gas < MOLE_PENALTY_THRESHOLD) - damage = max(damage + ((min(removed.temperature - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ) * PROCESSING_HANDICAP), 0) - //capping damage - damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage) - if(damage > damage_archived && prob(10)) - playsound(get_turf(src), 'sound/effects/empulse.ogg', 50, 1) + explode() -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_lightning() - if(power > POWER_PENALTY_THRESHOLD) - playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10) - supermatter_zap(src, 5, min(power*2, 20000)) - supermatter_zap(src, 5, min(power*2, 20000)) - if(power > SEVERE_POWER_PENALTY_THRESHOLD) - supermatter_zap(src, 5, min(power*2, 20000)) - if(power > CRITICAL_POWER_PENALTY_THRESHOLD) - supermatter_zap(src, 5, min(power*2, 20000)) - else if (damage > damage_penalty_point && prob(20)) - playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10) - supermatter_zap(src, 5, Clamp(power*2, 4000, 20000)) -/obj/machinery/power/supermatter_shard/proc/SM_autoprocess_anomaly() - if(prob(15) && power > POWER_PENALTY_THRESHOLD) - supermatter_pull(src, power/750) - if(prob(5)) - supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10)) - if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(5) || prob(1)) - supermatter_anomaly_gen(src, GRAVITATIONAL_ANOMALY, rand(5, 10)) - if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2) || prob(0.3) && power > POWER_PENALTY_THRESHOLD) - supermatter_anomaly_gen(src, PYRO_ANOMALY, rand(5, 10)) + power -= ((power/500)**3) * powerloss_inhibitor + + return 1 /obj/machinery/power/supermatter_shard/bullet_act(obj/item/projectile/Proj) var/turf/L = loc @@ -548,6 +518,11 @@ playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) Consume(nom) +/obj/machinery/power/supermatter_shard/proc/transfer_energy() + for(var/obj/machinery/power/rad_collector/R in GLOB.rad_collectors) + if(R.z == z && get_dist(R, src) <= 15) //Better than using orange() every process + R.receive_pulse(power * (1 + power_transmission_bonus)/10 * freon_transmit_modifier) + /obj/machinery/power/supermatter_shard/attackby(obj/item/W, mob/living/user, params) if(!istype(W) || (W.flags & ABSTRACT) || !istype(user)) return