From f5eb6b48b8d54811d8fae0b1970b22f9538ec8d8 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Mon, 25 Sep 2023 08:24:04 +0200 Subject: [PATCH] [MIRROR] [NO GBP]Zap strength is now measured in joules. NT CIMs will now display the power transmission from the zaps, accounting for every factor. [MDB IGNORE] (#23887) * [NO GBP]Zap strength is now measured in joules. NT CIMs will now display the power transmission from the zaps, accounting for every factor. (#78310) ## About The Pull Request Zap strength is now measured in joules. Scales everything to account for this. NT CIMS will now display the zap power transmission in watts, instead of a modifier. This will allow you to actually see how much power the supermatter is generating accurately, without knowledge of hidden multipliers. NT CIMs will also show the internal energy gain from heat in eV/K/s, so you can easily figure out how internal energy gain works, and how much energy gain it actually gives. The internal energy measurement will also adjust its prefix. Internal energy is now a measure of internal energy, rather than internal energy density, removing the "/cm^3". Here is what it looked like: ![Screenshot (25)](https://github.com/tgstation/tgstation/assets/58013024/781323d4-db91-4a78-9a46-8152022993ed) This image was created on an earlier commit where the numbers were wrong due to a hidden multiplier that got removed later, so keep that in mind. Also fixes inactive supermatters unnecessarily scaling delta time. The high energy (>5GeV) additional zaps now also scale with delta time. The code in this PR is absolute garbage trash and there are some major issues, so I'm drafting this for now. ## Why It's Good For The Game Makes it more clear what the factors add, and also how much power the SM is releasing. Zap strength being measured in joules will simplify a lot of things, making power balance more clear rather than guessimating. Adjusting the prefix for internal energy is just the natural thing to do. The per cubic centimeter part of internal energy would imply it is energy density, however it is functionally not. It would probably confuse people thinking the volume of the turf or the size of the supermatter actually matters for what the internal energy does, when it does not (except for gas absorption I guess, which changes heating/mol requirements, but nothing else), so I am removing that part. ## Changelog :cl: qol: NT CIMs shows how much power the supermatter is releasing. qol: NT CIMs internal energy will adjust its prefix. qol: Energy displays (such as multitooling grid) will use the full range of SI prefixes available, up to the peta prefix if you somehow managed to reach that. del: Removes the per cubic centimeter part of internal energy. fix: Fix unnecessary delta time scaling on inactive supermatters. fix: Fix high energy zaps not scaling with delta time. fix: Fixes grounding rods lying about potential power you can generate. code: Convert supermatter_zap() and tesla_zap() zap_str argument unit to be in joules, and scales everything that uses that argument. /:cl: * [NO GBP]Zap strength is now measured in joules. NT CIMs will now display the power transmission from the zaps, accounting for every factor. --------- Co-authored-by: Pickle-Coding <58013024+Pickle-Coding@users.noreply.github.com> --- code/__DEFINES/maths.dm | 3 + code/__DEFINES/supermatter.dm | 10 +- code/__HELPERS/maths.dm | 57 +++++++--- code/__HELPERS/text.dm | 23 +--- code/datums/mutations/touch.dm | 2 +- code/game/machinery/_machinery.dm | 4 +- .../effects/anomalies/anomalies_flux.dm | 2 +- code/game/objects/obj_defense.dm | 2 +- code/game/objects/structures.dm | 4 +- .../abductor/equipment/glands/electric.dm | 2 +- .../antagonists/blob/structures/_blob.dm | 6 +- .../components/fusion/hfr_main_processes.dm | 6 +- .../modules/clothing/suits/reactive_armour.dm | 2 +- code/modules/power/rtg.dm | 2 +- code/modules/power/supermatter/supermatter.dm | 106 ++++++++++++------ .../supermatter/supermatter_extra_effects.dm | 8 +- .../power/supermatter/supermatter_gas.dm | 24 ++-- code/modules/power/tesla/coil.dm | 9 +- code/modules/power/tesla/energy_ball.dm | 8 +- .../projectiles/projectile/energy/tesla.dm | 4 +- code/modules/projectiles/projectile/magic.dm | 4 +- .../chemistry/recipes/pyrotechnics.dm | 6 +- .../internal/stomach/stomach_ethereal.dm | 2 +- tgui/packages/tgui/interfaces/Supermatter.tsx | 52 +++++---- 24 files changed, 205 insertions(+), 143 deletions(-) diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index eb1b2ecce51..1260e3daf03 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -254,3 +254,6 @@ /// Returns a random decimal between x and y. #define RANDOM_DECIMAL(x, y) LERP((x), (y), rand()) + +#define SI_COEFFICIENT "coefficient" +#define SI_UNIT "unit" diff --git a/code/__DEFINES/supermatter.dm b/code/__DEFINES/supermatter.dm index bac35207fb5..5eab41fcdf9 100644 --- a/code/__DEFINES/supermatter.dm +++ b/code/__DEFINES/supermatter.dm @@ -28,6 +28,12 @@ #define MATTER_POWER_CONVERSION 10 //Crystal converts 1/this value of stored matter into energy. +/// The internal energy gain coefficient. +#define GAS_HEAT_POWER_SCALING_COEFFICIENT (1/6) + +/// The base zap power transmission of the supermatter crystal in W/MeV. +#define BASE_POWER_TRANSMISSION_RATE 1040 + //These would be what you would get at point blank, decreases with distance #define DETONATION_HALLUCINATION (20 MINUTES) @@ -165,9 +171,9 @@ #define SM_TEMP_LIMIT_LOW_MOLES "Low Moles Heat Resistance" /// How much we are multiplying our zap energy. -#define SM_ZAP_BASE "Base Zap Multiplier" +#define SM_ZAP_BASE "Base Zap Transmission" /// How much we are multiplying our zap energy because of gas factors. -#define SM_ZAP_GAS "Gas Zap Multiplier" +#define SM_ZAP_GAS "Gas Zap Transmission Modifier" /// Delamination types. #define CASCADE_DELAMINATION "cascade" #define SINGULARITY_DELAMINATION "singularity" diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index 6cda3466949..116fb34fad5 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -119,25 +119,48 @@ dx -= 1 return perimeter -///Format a power value in W, kW, MW, or GW. -/proc/display_power(powerused) - if(powerused < 1000) //Less than a kW - return "[powerused] W" - else if(powerused < 1000000) //Less than a MW - return "[round((powerused * 0.001),0.01)] kW" - else if(powerused < 1000000000) //Less than a GW - return "[round((powerused * 0.000001),0.001)] MW" - return "[round((powerused * 0.000000001),0.0001)] GW" +/** + * Formats a number into a list representing the si unit. + * Access the coefficient with [SI_COEFFICIENT], and access the unit with [SI_UNIT]. + * + * Supports SI exponents between 1e-15 to 1e15, but properly handles numbers outside that range as well. + * Arguments: + * * value - The number to convert to text. Can be positive or negative. + * * unit - The base unit of the number, such as "Pa" or "W". + * * maxdecimals - Maximum amount of decimals to display for the final number. Defaults to 1. + * Returns: [SI_COEFFICIENT = si unit coefficient, SI_UNIT = prefixed si unit.] + */ +/proc/siunit_isolated(value, unit, maxdecimals=1) + var/static/list/prefixes = list("f","p","n","μ","m","","k","M","G","T","P") -///Format an energy value in J, kJ, MJ, or GJ. 1W = 1J/s. + // We don't have prefixes beyond this point + // and this also captures value = 0 which you can't compute the logarithm for + // and also byond numbers are floats and doesn't have much precision beyond this point anyway + if(abs(value) <= 1e-18) + . = list(SI_COEFFICIENT = 0, SI_UNIT = " [unit]") + return + + var/exponent = clamp(log(10, abs(value)), -15, 15) // Calculate the exponent and clamp it so we don't go outside the prefix list bounds + var/divider = 10 ** (round(exponent / 3) * 3) // Rounds the exponent to nearest SI unit and power it back to the full form + var/coefficient = round(value / divider, 10 ** -maxdecimals) // Calculate the coefficient and round it to desired decimals + var/prefix_index = round(exponent / 3) + 6 // Calculate the index in the prefixes list for this exponent + + // An edge case which happens if we round 999.9 to 0 decimals for example, which gets rounded to 1000 + // In that case, we manually swap up to the next prefix if there is one available + if(coefficient >= 1000 && prefix_index < 11) + coefficient /= 1e3 + prefix_index++ + + var/prefix = prefixes[prefix_index] + . = list(SI_COEFFICIENT = coefficient, SI_UNIT = " [prefix][unit]") + +///Format a power value in prefixed watts. +/proc/display_power(powerused) + return siunit(powerused, "W", 3) + +///Format an energy value in prefixed joules. /proc/display_joules(units) - if (units < 1000) // Less than a kJ - return "[round(units, 0.1)] J" - else if (units < 1000000) // Less than a MJ - return "[round(units * 0.001, 0.01)] kJ" - else if (units < 1000000000) // Less than a GJ - return "[round(units * 0.000001, 0.001)] MJ" - return "[round(units * 0.000000001, 0.0001)] GJ" + return siunit(units, "J", 3) /proc/joules_to_energy(joules) return joules * (1 SECONDS) / SSmachines.wait diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index f75e6770207..00317d8cf1c 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -1048,27 +1048,8 @@ GLOBAL_LIST_INIT(binary, list("0","1")) * * For pressure conversion, use proc/siunit_pressure() below */ /proc/siunit(value, unit, maxdecimals=1) - var/static/list/prefixes = list("f","p","n","μ","m","","k","M","G","T","P") - - // We don't have prefixes beyond this point - // and this also captures value = 0 which you can't compute the logarithm for - // and also byond numbers are floats and doesn't have much precision beyond this point anyway - if(abs(value) <= 1e-18) - return "0 [unit]" - - var/exponent = clamp(log(10, abs(value)), -15, 15) // Calculate the exponent and clamp it so we don't go outside the prefix list bounds - var/divider = 10 ** (round(exponent / 3) * 3) // Rounds the exponent to nearest SI unit and power it back to the full form - var/coefficient = round(value / divider, 10 ** -maxdecimals) // Calculate the coefficient and round it to desired decimals - var/prefix_index = round(exponent / 3) + 6 // Calculate the index in the prefixes list for this exponent - - // An edge case which happens if we round 999.9 to 0 decimals for example, which gets rounded to 1000 - // In that case, we manually swap up to the next prefix if there is one available - if(coefficient >= 1000 && prefix_index < 11) - coefficient /= 1e3 - prefix_index++ - - var/prefix = prefixes[prefix_index] - return "[coefficient] [prefix][unit]" + var/si_isolated = siunit_isolated(value, unit, maxdecimals) + return "[si_isolated[SI_COEFFICIENT]][si_isolated[SI_UNIT]]" /** The game code never uses Pa, but kPa, since 1 Pa is too small to reasonably handle diff --git a/code/datums/mutations/touch.dm b/code/datums/mutations/touch.dm index 1f1cefe1cbe..3f798ba52b2 100644 --- a/code/datums/mutations/touch.dm +++ b/code/datums/mutations/touch.dm @@ -38,7 +38,7 @@ ///This var decides if the spell should chain, dictated by presence of power chromosome var/chain = FALSE ///Affects damage, should do about 1 per limb - var/zap_power = 7500 + var/zap_power = 3e6 ///Range of tesla shock bounces var/zap_range = 7 ///flags that dictate what the tesla shock can interact with, Can only damage mobs, Cannot damage machines or generate energy diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index b6327480399..349a895238d 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -1122,10 +1122,10 @@ if(prob(85) && (zap_flags & ZAP_MACHINE_EXPLOSIVE) && !(resistance_flags & INDESTRUCTIBLE)) explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 4, flame_range = 2, adminlog = FALSE, smoke = FALSE) else if(zap_flags & ZAP_OBJ_DAMAGE) - take_damage(power * 0.0005, BURN, ENERGY) + take_damage(power * 6.25e-7, BURN, ENERGY) if(prob(40)) emp_act(EMP_LIGHT) - power -= power * 0.0005 + power -= power * 5e-4 return ..() /obj/machinery/proc/adjust_item_drop_location(atom/movable/dropped_atom) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8 diff --git a/code/game/objects/effects/anomalies/anomalies_flux.dm b/code/game/objects/effects/anomalies/anomalies_flux.dm index eee4319b352..2bb3ab28a1a 100644 --- a/code/game/objects/effects/anomalies/anomalies_flux.dm +++ b/code/game/objects/effects/anomalies/anomalies_flux.dm @@ -66,7 +66,7 @@ ///range in whuich we zap var/zap_range = 1 ///strength of the zappy - var/zap_power = 2500 + var/zap_power = 1e6 ///the zappy flags var/zap_flags = ZAP_GENERATES_POWER | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 524c189acc6..a06b7fdaea7 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -145,7 +145,7 @@ if(has_buckled_mobs()) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - buckled_mob.electrocute_act((clamp(round(strength/400), 10, 90) + rand(-5, 5)), src, flags = SHOCK_TESLA) + buckled_mob.electrocute_act((clamp(round(strength * 3.125e-6), 10, 90) + rand(-5, 5)), src, flags = SHOCK_TESLA) ///the obj is deconstructed into pieces, whether through careful disassembly or when destroyed. /obj/proc/deconstruct(disassembled = TRUE) diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 71d15fb3f58..ba8623ec4aa 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -63,6 +63,6 @@ /obj/structure/zap_act(power, zap_flags) if(zap_flags & ZAP_OBJ_DAMAGE) - take_damage(power/8000, BURN, "energy") - power -= power/2000 //walls take a lot out of ya + take_damage(power * 1.5625e-7, BURN, "energy") + power -= power * 5e-4 //walls take a lot out of ya . = ..() diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm index acb1505a71c..9c4d47dc337 100644 --- a/code/modules/antagonists/abductor/equipment/glands/electric.dm +++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm @@ -22,5 +22,5 @@ addtimer(CALLBACK(src, PROC_REF(zap)), rand(30, 100)) /obj/item/organ/internal/heart/gland/electric/proc/zap() - tesla_zap(owner, 4, 8000, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN) + tesla_zap(owner, 4, 3.2e6, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN) playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE) diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index 3580e3f3bf8..543da00d2f5 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -227,10 +227,10 @@ /obj/structure/blob/zap_act(power, zap_flags) if(overmind) if(overmind.blobstrain.tesla_reaction(src, power)) - take_damage(power * 0.0025, BURN, ENERGY) + take_damage(power * 3.125e-6, BURN, ENERGY) else - take_damage(power * 0.0025, BURN, ENERGY) - power -= power * 0.0025 //You don't get to do it for free + take_damage(power * 3.125e-6, BURN, ENERGY) + power -= power * 2.5e-3 //You don't get to do it for free return ..() //You don't get to do it for free /obj/structure/blob/extinguish() diff --git a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm index 5062ec7731f..c6e1d6183ef 100644 --- a/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm +++ b/code/modules/atmospherics/machinery/components/fusion/hfr_main_processes.dm @@ -480,8 +480,8 @@ if(critical_threshold_proximity > 650 && prob(20)) zap_number += 1 - var/cutoff = 1500 - cutoff = clamp(3000 - (power_level * (internal_fusion.total_moles() * 0.45)), 450, 3000) + var/cutoff = 1.2e6 + cutoff = clamp(2.4e6 - (power_level * (internal_fusion.total_moles() * 360)), 3.6e5, 2.4e6) var/zaps_aspect = DEFAULT_ZAP_ICON_STATE var/flags = ZAP_SUPERMATTER_FLAGS @@ -495,7 +495,7 @@ playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10) for(var/i in 1 to zap_number) - supermatter_zap(src, 5, power_level * 300, flags, zap_cutoff = cutoff, power_level = src.power_level * 1000, zap_icon = zaps_aspect) + supermatter_zap(src, 5, power_level * 2.4e5, flags, zap_cutoff = cutoff, power_level = src.power_level * 1000, zap_icon = zaps_aspect) /obj/machinery/atmospherics/components/unary/hypertorus/core/proc/check_gravity_pulse(seconds_per_tick) if(SPT_PROB(100 - critical_threshold_proximity / 15, seconds_per_tick)) diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index 9537fa7b6ef..6c33e287f03 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -226,7 +226,7 @@ emp_message = span_warning("The tesla capacitors beep ominously for a moment.") clothing_traits = list(TRAIT_TESLA_SHOCKIMMUNE) /// How strong are the zaps we give off? - var/zap_power = 25000 + var/zap_power = 1e7 /// How far to the zaps we give off go? var/zap_range = 20 /// What flags do we pass to the zaps we give off? diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm index c49bc455165..974c2e66737 100644 --- a/code/modules/power/rtg.dm +++ b/code/modules/power/rtg.dm @@ -71,7 +71,7 @@ visible_message(span_danger("\The [src] lets out a shower of sparks as it starts to lose stability!"),\ span_hear("You hear a loud electrical crack!")) playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) - tesla_zap(src, 5, power_gen * 0.05) + tesla_zap(src, 5, power_gen * 20) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(explosion), src, 2, 3, 4, null, 8), 10 SECONDS) // Not a normal explosion. /obj/machinery/power/rtg/abductor/bullet_act(obj/projectile/Proj) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 654ea805440..8598b3cccf2 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -53,8 +53,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/damage_archived = 0 var/list/damage_factors - /// How much extra power does the main zap generate. - var/zap_multiplier = 1 + /// The zap power transmission over internal energy. W/MeV. + var/zap_transmission_rate = BASE_POWER_TRANSMISSION_RATE var/list/zap_factors /// The temperature at which we start taking damage @@ -95,7 +95,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /// How much power decay is negated. Complete power decay negation at 1. var/gas_powerloss_inhibition = 0 /// Affects the amount of power the main SM zap makes. - var/gas_power_transmission = 0 + var/gas_power_transmission_rate = 0 /// Affects the power gain the SM experiances from heat. var/gas_heat_power_generation = 0 @@ -109,7 +109,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/external_damage_immediate = 0 ///The cutoff for a bolt jumping, grows with heat, lowers with higher mol count, - var/zap_cutoff = 1500 + var/zap_cutoff = 1.2e6 ///How much the bullets damage should be multiplied by when it is added to the internal variables var/bullet_energy = SUPERMATTER_DEFAULT_BULLET_ENERGY ///How much hallucination should we produce per unit of power? @@ -153,6 +153,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) ///Stores the time of when the last zap occurred var/last_power_zap = 0 + var/last_high_energy_zap = 0 ///Do we show this crystal in the CIMS modular program var/include_in_cims = TRUE @@ -275,7 +276,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) // PART 3: POWER PROCESSING internal_energy_factors = calculate_internal_energy() - zap_factors = calculate_zap_multiplier() + zap_factors = calculate_zap_transmission_rate() if(internal_energy && (last_power_zap + (4 - internal_energy * 0.001) SECONDS) < world.time) playsound(src, 'sound/weapons/emitter2.ogg', 70, TRUE) hue_angle_shift = clamp(903 * log(10, (internal_energy + 8000)) - 3590, -50, 240) @@ -286,9 +287,9 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) supermatter_zap( zapstart = src, range = 3, - zap_str = 1.25 * internal_energy * zap_multiplier * delta_time, + zap_str = internal_energy * zap_transmission_rate * delta_time, zap_flags = ZAP_SUPERMATTER_FLAGS, - zap_cutoff = 300 * delta_time, + zap_cutoff = 2.4e5 * delta_time, power_level = internal_energy, color = zap_color, ) @@ -374,15 +375,20 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) "name" = factor, "amount" = amount * -1 )) + var/list/internal_energy_si_derived_data = siunit_isolated(internal_energy * 1e6, "eV", 3) data["internal_energy"] = internal_energy + data["internal_energy_coefficient"] = internal_energy_si_derived_data[SI_COEFFICIENT] + data["internal_energy_unit"] = internal_energy_si_derived_data[SI_UNIT] data["internal_energy_factors"] = list() for (var/factor in internal_energy_factors) + var/list/internal_energy_factor_si_derived_data = siunit_isolated(internal_energy_factors[factor] * 1e6, "eV", 3) var/amount = round(internal_energy_factors[factor], 0.01) if(!amount) continue data["internal_energy_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = internal_energy_factor_si_derived_data[SI_COEFFICIENT], + "unit" = internal_energy_factor_si_derived_data[SI_UNIT], )) data["temp_limit"] = temp_limit data["temp_limit_factors"] = list() @@ -392,7 +398,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) continue data["temp_limit_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = amount, )) data["waste_multiplier"] = waste_multiplier data["waste_multiplier_factors"] = list() @@ -402,18 +408,42 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) continue data["waste_multiplier_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = amount, )) - data["zap_multiplier"] = zap_multiplier - data["zap_multiplier_factors"] = list() + + data["zap_transmission_factors"] = list() for (var/factor in zap_factors) - var/amount = round(zap_factors[factor], 0.01) - if(!amount) + var/list/zap_factor_si_derived_data = siunit_isolated(zap_factors[factor] * internal_energy, "W", 2) + if(!zap_factor_si_derived_data[SI_COEFFICIENT]) continue - data["zap_multiplier_factors"] += list(list( + data["zap_transmission_factors"] += list(list( "name" = factor, - "amount" = amount + "amount" = zap_factor_si_derived_data[SI_COEFFICIENT], + "unit" = zap_factor_si_derived_data[SI_UNIT], )) + + ///Add high energy bonus to the zap transmission data so we can accurately measure our power generation from zaps. + var/high_energy_bonus = 0 + var/zap_transmission = zap_transmission_rate * internal_energy + var/zap_power_multiplier = 1 + if(internal_energy > POWER_PENALTY_THRESHOLD) //Supermatter zaps multiply power internally under some conditions for some reason, so we'll snowflake this for now. + ///Power multiplier bonus applied to all zaps. Zap power generation doubles when it reaches 7GeV and 9GeV. + zap_power_multiplier *= 2 ** clamp(round((internal_energy - POWER_PENALTY_THRESHOLD) / 2000), 0, 2) + ///The supermatter releases additional zaps after 5GeV, with more at 7GeV and 9GeV. + var/additional_zap_bonus = clamp(internal_energy * 3200, 6.4e6, 3.2e7) * clamp(round(INVERSE_LERP(1000, 3000, internal_energy)), 1, 4) + high_energy_bonus = (zap_transmission + additional_zap_bonus) * zap_power_multiplier - zap_transmission + var/list/zap_factor_si_derived_data = siunit_isolated(high_energy_bonus, "W", 2) + data["zap_transmission_factors"] += list(list( + "name" = "High Energy Bonus", + "amount" = zap_factor_si_derived_data[SI_COEFFICIENT], + "unit" = zap_factor_si_derived_data[SI_UNIT], + )) + + var/list/zap_transmission_si_derived_data = siunit_isolated(zap_transmission + high_energy_bonus, "W", 2) + data["zap_transmission"] = zap_transmission + high_energy_bonus + data["zap_transmission_coefficient"] = zap_transmission_si_derived_data[SI_COEFFICIENT] + data["zap_transmission_unit"] = zap_transmission_si_derived_data[SI_UNIT] + data["absorbed_ratio"] = absorption_ratio var/list/formatted_gas_percentage = list() for (var/datum/gas/gas_path as anything in subtypesof(/datum/gas)) @@ -577,7 +607,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) * * Updates: * [/obj/machinery/power/supermatter_crystal/var/list/gas_percentage] - * [/obj/machinery/power/supermatter_crystal/var/gas_power_transmission] + * [/obj/machinery/power/supermatter_crystal/var/gas_power_transmission_rate] * [/obj/machinery/power/supermatter_crystal/var/gas_heat_modifier] * [/obj/machinery/power/supermatter_crystal/var/gas_heat_resistance] * [/obj/machinery/power/supermatter_crystal/var/gas_heat_power_generation] @@ -590,7 +620,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) return gas_percentage = list() - gas_power_transmission = 0 + gas_power_transmission_rate = 0 gas_heat_modifier = 0 gas_heat_resistance = 0 gas_heat_power_generation = 0 @@ -607,7 +637,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/datum/sm_gas/sm_gas = current_gas_behavior[gas_path] if(!sm_gas) continue - gas_power_transmission += sm_gas.power_transmission * gas_percentage[gas_path] + gas_power_transmission_rate += sm_gas.power_transmission * gas_percentage[gas_path] gas_heat_modifier += sm_gas.heat_modifier * gas_percentage[gas_path] gas_heat_resistance += sm_gas.heat_resistance * gas_percentage[gas_path] gas_heat_power_generation += sm_gas.heat_power_generation * gas_percentage[gas_path] @@ -637,7 +667,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) external_power_trickle -= min(additive_power[SM_POWER_EXTERNAL_TRICKLE], external_power_trickle) additive_power[SM_POWER_EXTERNAL_IMMEDIATE] = external_power_immediate external_power_immediate = 0 - additive_power[SM_POWER_HEAT] = gas_heat_power_generation * absorbed_gasmix.temperature / 6 + additive_power[SM_POWER_HEAT] = gas_heat_power_generation * absorbed_gasmix.temperature * GAS_HEAT_POWER_SCALING_COEFFICIENT additive_power[SM_POWER_HEAT] && log_activation(who = "environmental factors") // I'm sorry for this, but we need to calculate power lost immediately after power gain. @@ -660,6 +690,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(internal_energy && !activation_logged) stack_trace("Supermatter powered for the first time without being logged. Internal energy factors: [json_encode(internal_energy_factors)]") activation_logged = TRUE // so we dont spam the log. + else if(!internal_energy) + last_power_zap = world.time return additive_power /** Log when the supermatter is activated for the first time. @@ -685,24 +717,24 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) activation_logged = TRUE /** - * Perform calculation for the main zap power multiplier. + * Perform calculation for the main zap power transmission rate in W/MeV. * Description of each factors can be found in the defines. * * Updates: - * [/obj/machinery/power/supermatter_crystal/var/zap_multiplier] + * [/obj/machinery/power/supermatter_crystal/var/zap_transmission_rate] * * Returns: The factors that have influenced the calculation. list[FACTOR_DEFINE] = number */ -/obj/machinery/power/supermatter_crystal/proc/calculate_zap_multiplier() - var/list/additive_transmission = list() - additive_transmission[SM_ZAP_BASE] = 1 - additive_transmission[SM_ZAP_GAS] = gas_power_transmission +/obj/machinery/power/supermatter_crystal/proc/calculate_zap_transmission_rate() + var/list/additive_transmission_rate = list() + additive_transmission_rate[SM_ZAP_BASE] = BASE_POWER_TRANSMISSION_RATE + additive_transmission_rate[SM_ZAP_GAS] = BASE_POWER_TRANSMISSION_RATE * gas_power_transmission_rate - zap_multiplier = 0 - for (var/transmission_types in additive_transmission) - zap_multiplier += additive_transmission[transmission_types] - zap_multiplier = max(zap_multiplier, 0) - return additive_transmission + zap_transmission_rate = 0 + for (var/transmission_types in additive_transmission_rate) + zap_transmission_rate += additive_transmission_rate[transmission_types] + zap_transmission_rate = max(zap_transmission_rate, 0) + return additive_transmission_rate /** * Perform calculation for the waste multiplier. @@ -836,7 +868,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) delamination_strategy.on_select(src) return TRUE -/obj/machinery/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list(), zap_cutoff = 1500, power_level = 0, zap_icon = DEFAULT_ZAP_ICON_STATE, color = null) +/obj/machinery/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 3.2e6, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list(), zap_cutoff = 1.2e6, power_level = 0, zap_icon = DEFAULT_ZAP_ICON_STATE, color = null) if(QDELETED(zapstart)) return . = zapstart.dir @@ -931,13 +963,13 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) //Going boom should be rareish if(prob(80)) zap_flags &= ~ZAP_MACHINE_EXPLOSIVE - if(target_type == COIL) - var/multi = 2 - switch(power_level)//Between 7k and 9k it's 4, above that it's 8 + if(target_type == COIL || target_type == ROD) + var/multi = 1 + switch(power_level)//Between 7k and 9k it's 2, above that it's 4 if(SEVERE_POWER_PENALTY_THRESHOLD to CRITICAL_POWER_PENALTY_THRESHOLD) - multi = 4 + multi = 2 if(CRITICAL_POWER_PENALTY_THRESHOLD to INFINITY) - multi = 8 + multi = 4 if(zap_flags & ZAP_SUPERMATTER_FLAGS) var/remaining_power = target.zap_act(zap_str * multi, zap_flags) zap_str = remaining_power / multi //Coils should take a lot out of the power of the zap diff --git a/code/modules/power/supermatter/supermatter_extra_effects.dm b/code/modules/power/supermatter/supermatter_extra_effects.dm index 7fe56d9c2d4..efd84c677fa 100644 --- a/code/modules/power/supermatter/supermatter_extra_effects.dm +++ b/code/modules/power/supermatter/supermatter_extra_effects.dm @@ -91,6 +91,7 @@ /obj/machinery/power/supermatter_crystal/proc/handle_high_power() if(internal_energy <= POWER_PENALTY_THRESHOLD && damage <= danger_point) //If the power is above 5000 or if the damage is above 550 + last_high_energy_zap = world.time //Prevent oddly high initial zap due to high energy zaps not getting triggered via too low energy. return var/range = 4 zap_cutoff = 1500 @@ -99,7 +100,7 @@ var/temp = absorbed_gasmix.temperature if(pressure > 0 && temp > 0) //You may be able to freeze the zapstate of the engine with good planning, we'll see - zap_cutoff = clamp(3000 - (internal_energy * total_moles / 10) / temp, 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols + zap_cutoff = clamp(1.2e6 - (internal_energy * total_moles * 40) / temp, 1.4e5, 1.2e6)//If the core is cold, it's easier to jump, ditto if there are a lot of mols //We should always be able to zap our way out of the default enclosure //See supermatter_zap() for more details range = clamp(internal_energy / pressure * 10, 2, 7) @@ -128,9 +129,10 @@ if(zap_count >= 1) playsound(loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10) + var/delta_time = min((world.time - last_high_energy_zap) * 0.1, 16) for(var/i in 1 to zap_count) - supermatter_zap(src, range, clamp(internal_energy*2, 4000, 20000), flags, zap_cutoff = src.zap_cutoff, power_level = internal_energy, zap_icon = src.zap_icon) - + supermatter_zap(src, range, clamp(internal_energy * 3200, 6.4e6, 3.2e7) * delta_time, flags, zap_cutoff = src.zap_cutoff * delta_time, power_level = internal_energy, zap_icon = src.zap_icon) + last_high_energy_zap = world.time if(prob(5)) supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10)) if(prob(5)) diff --git a/code/modules/power/supermatter/supermatter_gas.dm b/code/modules/power/supermatter/supermatter_gas.dm index 141f78a38b8..df8ef8e5b4f 100644 --- a/code/modules/power/supermatter/supermatter_gas.dm +++ b/code/modules/power/supermatter/supermatter_gas.dm @@ -17,33 +17,40 @@ // Positive is true if more of the amount is a good thing. var/list/numeric_data = list() if(sm_gas.power_transmission) + var/list/si_derived_data = siunit_isolated(sm_gas.power_transmission * BASE_POWER_TRANSMISSION_RATE, "W/MeV", 2) numeric_data += list(list( - "name" = "Power Transmission", - "amount" = sm_gas.power_transmission, + "name" = "Power Transmission Bonus", + "amount" = si_derived_data["coefficient"], + "unit" = si_derived_data["unit"], "positive" = TRUE, )) if(sm_gas.heat_modifier) numeric_data += list(list( "name" = "Waste Multiplier", - "amount" = sm_gas.heat_modifier, + "amount" = 100 * sm_gas.heat_modifier, + "unit" = "%", "positive" = FALSE, )) if(sm_gas.heat_resistance) numeric_data += list(list( "name" = "Heat Resistance", - "amount" = sm_gas.heat_resistance, + "amount" = 100 * sm_gas.heat_resistance, + "unit" = "%", "positive" = TRUE, )) if(sm_gas.heat_power_generation) + var/list/si_derived_data = siunit_isolated(sm_gas.heat_power_generation * GAS_HEAT_POWER_SCALING_COEFFICIENT * 1e7 / SSair.wait, "eV/K/s", 2) numeric_data += list(list( "name" = "Heat Power Gain", - "amount" = sm_gas.heat_power_generation, + "amount" = si_derived_data["coefficient"], + "unit" = si_derived_data["unit"], "positive" = TRUE, )) if(sm_gas.powerloss_inhibition) numeric_data += list(list( "name" = "Power Decay Negation", - "amount" = sm_gas.powerloss_inhibition, + "amount" = 100 * sm_gas.powerloss_inhibition, + "unit" = "%", "positive" = TRUE, )) singular_gas_data["numeric_data"] = numeric_data @@ -59,8 +66,7 @@ GLOBAL_LIST_INIT(sm_gas_behavior, init_sm_gas()) /datum/sm_gas /// Path of the [/datum/gas] involved with this interaction. var/gas_path - - /// Influences zap power without interfering with the crystal's own energy. + /// Influences zap power without interfering with the crystal's own energy. Gets scaled by [BASE_POWER_TRANSMISSION_RATE]. var/power_transmission = 0 /// How much more waste heat and gas the SM generates. var/heat_modifier = 0 @@ -216,7 +222,7 @@ GLOBAL_LIST_INIT(sm_gas_behavior, init_sm_gas()) sm.supermatter_zap( sm, range = 6, - zap_str = clamp(sm.internal_energy * 2, 4000, 20000), + zap_str = clamp(sm.internal_energy * 1600, 3.2e6, 1.6e7), zap_flags = ZAP_MOB_STUN, zap_cutoff = sm.zap_cutoff, power_level = sm.internal_energy, diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 098ff7ceaee..3cf040b76ef 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -1,7 +1,5 @@ // zap needs to be over this amount to get power -#define TESLA_COIL_THRESHOLD 80 -// each zap power unit produces 400 joules -#define ZAP_TO_ENERGY(p) (joules_to_energy((p) * 400)) +#define TESLA_COIL_THRESHOLD 32000 /obj/machinery/power/energy_accumulator/tesla_coil name = "tesla coil" @@ -107,7 +105,7 @@ power /= 10 zap_buckle_check(power) var/power_removed = powernet ? power * input_power_multiplier : power - stored_energy += max(ZAP_TO_ENERGY(power_removed - TESLA_COIL_THRESHOLD), 0) + stored_energy += max(joules_to_energy(power_removed - TESLA_COIL_THRESHOLD), 0) return max(power - power_removed, 0) //You get back the amount we didn't use /obj/machinery/power/energy_accumulator/tesla_coil/proc/zap() @@ -170,10 +168,9 @@ if(anchored && !panel_open) flick("grounding_rodhit", src) zap_buckle_check(power) - stored_energy += ZAP_TO_ENERGY(power) + stored_energy += joules_to_energy(power) return 0 else . = ..() #undef TESLA_COIL_THRESHOLD -#undef ZAP_TO_ENERGY diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index b21938e2608..7ee8c0085c9 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -1,5 +1,5 @@ -#define TESLA_DEFAULT_POWER 1738260 -#define TESLA_MINI_POWER 869130 +#define TESLA_DEFAULT_POWER 6.95304e8 +#define TESLA_MINI_POWER 3.47652e8 //Zap constants, speeds up targeting #define BIKE (COIL + 1) #define COIL (ROD + 1) @@ -205,7 +205,7 @@ if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) LAZYSET(shocked_targets, source, TRUE) //I don't want no null refs in my list yeah? . = source.dir - if(power < 1000) + if(power < 4e5) return /* @@ -334,7 +334,7 @@ var/mob/living/closest_mob = closest_atom ADD_TRAIT(closest_mob, TRAIT_BEING_SHOCKED, WAS_SHOCKED) addtimer(TRAIT_CALLBACK_REMOVE(closest_mob, TRAIT_BEING_SHOCKED, WAS_SHOCKED), 1 SECONDS) - var/shock_damage = (zap_flags & ZAP_MOB_DAMAGE) ? (min(round(power/600), 90) + rand(-5, 5)) : 0 + var/shock_damage = (zap_flags & ZAP_MOB_DAMAGE) ? (min(round(power/2.4e5), 90) + rand(-5, 5)) : 0 closest_mob.electrocute_act(shock_damage, source, 1, SHOCK_TESLA | ((zap_flags & ZAP_MOB_STUN) ? NONE : SHOCK_NOSTUN)) if(issilicon(closest_mob)) var/mob/living/silicon/S = closest_mob diff --git a/code/modules/projectiles/projectile/energy/tesla.dm b/code/modules/projectiles/projectile/energy/tesla.dm index 9afb816088f..687bd1b8e73 100644 --- a/code/modules/projectiles/projectile/energy/tesla.dm +++ b/code/modules/projectiles/projectile/energy/tesla.dm @@ -5,7 +5,7 @@ damage = 10 //A worse lasergun var/zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN var/zap_range = 3 - var/power = 10000 + var/power = 4e6 /obj/projectile/energy/tesla/on_hit(atom/target) . = ..() @@ -22,7 +22,7 @@ /obj/projectile/energy/tesla/cannon name = "tesla orb" - power = 20000 + power = 8e6 damage = 15 //Mech man big /obj/projectile/energy/tesla_cannon diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index afe59235478..c8da91b9dde 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -481,7 +481,7 @@ speed = 0.3 /// The power of the zap itself when it electrocutes someone - var/zap_power = 20000 + var/zap_power = 8e6 /// The range of the zap itself when it electrocutes someone var/zap_range = 15 /// The flags of the zap itself when it electrocutes someone @@ -503,7 +503,7 @@ return ..() /obj/projectile/magic/aoe/lightning/no_zap - zap_power = 10000 + zap_power = 4e6 zap_range = 4 zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 707a1dca350..9083de70902 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -542,9 +542,9 @@ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_EXPLOSIVE | REACTION_TAG_DANGEROUS /datum/chemical_reaction/reagent_explosion/teslium_lightning/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) - var/T1 = created_volume * 20 //100 units : Zap 3 times, with powers 2000/5000/12000. Tesla revolvers have a power of 10000 for comparison. - var/T2 = created_volume * 50 - var/T3 = created_volume * 120 + var/T1 = created_volume * 8e3 //100 units : Zap 3 times, with powers 8e5/2e6/4.8e6. Tesla revolvers have a power of 10000 for comparison. + var/T2 = created_volume * 2e4 + var/T3 = created_volume * 4.8e4 var/added_delay = 0.5 SECONDS if(created_volume >= 75) addtimer(CALLBACK(src, PROC_REF(zappy_zappy), holder, T1), added_delay) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm index 4d43b6a3a0a..4cc8ee404c1 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm @@ -92,7 +92,7 @@ playsound(carbon, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) carbon.cut_overlay(overcharge) - tesla_zap(carbon, 2, crystal_charge*2.5, ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN | ZAP_ALLOW_DUPLICATES) + tesla_zap(carbon, 2, crystal_charge * 1e3, ZAP_OBJ_DAMAGE | ZAP_LOW_POWER_GEN | ZAP_ALLOW_DUPLICATES) adjust_charge(ETHEREAL_CHARGE_FULL - crystal_charge) carbon.visible_message(span_danger("[carbon] violently discharges energy!"), span_warning("You violently discharge energy!")) diff --git a/tgui/packages/tgui/interfaces/Supermatter.tsx b/tgui/packages/tgui/interfaces/Supermatter.tsx index 5dd1bf8c399..57820fd038c 100644 --- a/tgui/packages/tgui/interfaces/Supermatter.tsx +++ b/tgui/packages/tgui/interfaces/Supermatter.tsx @@ -16,6 +16,7 @@ type SMGasMetadata = { numeric_data: { name: string; amount: number; + unit: string; positive: BooleanLike; }[]; }; @@ -28,9 +29,13 @@ type SupermatterProps = { integrity: number; integrity_factors: { name: string; amount: number }[]; internal_energy: number; - internal_energy_factors: { name: string; amount: number }[]; - zap_multiplier: number; - zap_multiplier_factors: { name: string; amount: number }[]; + internal_energy_coefficient: number; + internal_energy_unit: string; + internal_energy_factors: { name: string; amount: number; unit: string }[]; + zap_transmission: number; + zap_transmission_coefficient: number; + zap_transmission_unit: string; + zap_transmission_factors: { name: string; amount: number; unit: string }[]; temp_limit: number; temp_limit_factors: { name: string; amount: number }[]; waste_multiplier: number; @@ -92,9 +97,13 @@ export const SupermatterContent = (props: SupermatterProps, context) => { integrity, integrity_factors, internal_energy, + internal_energy_coefficient, + internal_energy_unit, internal_energy_factors, - zap_multiplier, - zap_multiplier_factors, + zap_transmission, + zap_transmission_coefficient, + zap_transmission_unit, + zap_transmission_factors, temp_limit, temp_limit_factors, waste_multiplier, @@ -166,19 +175,20 @@ export const SupermatterContent = (props: SupermatterProps, context) => { average: [5000, 7000], bad: [7000, Infinity], }}> - {toFixed(internal_energy) + ' MeV/cm3'} + {toFixed(internal_energy_coefficient, 3) + + internal_energy_unit} } detail={ !!internal_energy_factors.length && ( - {internal_energy_factors.map(({ name, amount }) => ( + {internal_energy_factors.map(({ name, amount, unit }) => ( 0 ? 'green' : 'red'}> - {toFixed(amount, 2) + ' MeV/cm3'} + {toFixed(amount, 3) + unit} ))} @@ -187,28 +197,30 @@ export const SupermatterContent = (props: SupermatterProps, context) => { } /> - {toFixed(zap_multiplier, 2) + ' x'} + {toFixed(zap_transmission_coefficient, 2) + + zap_transmission_unit} } detail={ - !!zap_multiplier_factors.length && ( + !!zap_transmission_factors.length && ( - {zap_multiplier_factors.map(({ name, amount }) => ( + {zap_transmission_factors.map(({ name, amount, unit }) => ( 0 ? 'green' : 'red'}> - {toFixed(amount, 2) + ' x'} + {toFixed(amount, 2) + unit} ))} @@ -356,8 +368,8 @@ export const SupermatterContent = (props: SupermatterProps, context) => { : 'red' }> {effect.amount > 0 - ? '+' + effect.amount * 100 + '%' - : effect.amount * 100 + '%'} + ? '+' + effect.amount + effect.unit + : effect.amount + effect.unit} ) )}