Dynamic EMP Severity (#20855)

* holy hell

-fixed ed-209 only being EMP'd on light EMPs and only 30% of the time
-singulo EMP range and strength dependent on size
-bodyparts handle EMP damage
-HoS gun and ion carbine use the same projectile
-fixed leg implant EMP effects not happening
-fixed cybernetic ears causing less knockdown on stronger EMPs
-fixed nanite heart causing instant death on every EMP

* stuff

* absolutely not

* preternis moment

* fix

* physiology

* subtractive once more

* use define

* missed a spot

* Update implant_misc.dm
This commit is contained in:
SapphicOverload
2023-12-02 23:03:19 -05:00
committed by GitHub
parent b6afdfed9b
commit 510bf4a26e
105 changed files with 323 additions and 382 deletions

View File

@@ -236,8 +236,8 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
#define EXPLODE_LIGHT 3
#define EXPLODE_GIB_THRESHOLD 50 //ex_act() with EXPLODE_DEVASTATE severity will gib mobs with less than this much bomb armor
#define EMP_HEAVY 1
#define EMP_LIGHT 2
#define EMP_LIGHT 5 // maximum severity level without severe effects like organ failure and paralysis
#define EMP_HEAVY 10 // max severity from most sources so you can't use a 5 billion tile EMP to instakill people
#define GRENADE_CLUMSY_FUMBLE 1
#define GRENADE_NONCLUMSY_FUMBLE 2

View File

@@ -291,8 +291,6 @@
#define TRAIT_NOVEHICLE "no_vehicle"
/// BALD!!!
#define TRAIT_BALD "bald"
/// Reduces severity of EMPs by one level, heavy becomes light and light is ignored
#define TRAIT_FARADAYCAGE "faraday_cage"
/// You can't see color!
#define TRAIT_COLORBLIND "color_blind"

View File

@@ -184,12 +184,14 @@
/datum/component/nanites/proc/on_emp(datum/source, severity)
if(HAS_TRAIT(host_mob, TRAIT_EMPPROOF_SELF))
return // don't do EMP effects if they're protected from EMPs
if(HAS_TRAIT(host_mob, TRAIT_FARADAYCAGE))
severity++
if(severity > EMP_LIGHT)
return
nanite_volume *= 1 - (rand(0.1, 0.25) / severity) //Lose 10-25% of nanites
adjust_nanites(null, -(rand(5, 30) / severity)) //Lose 5-30 flat nanite volume
if(iscarbon(host_mob))
var/mob/living/carbon/host_carbon = host_mob
if(host_carbon.dna?.species)
severity *= host_carbon.dna.species.emp_mod
if(severity < 1)
return // don't bother if it's less than 1 severity
nanite_volume *= 1 - (rand(0.01, 0.025) * severity) //Lose 1-2.5% of nanites for each severity level
adjust_nanites(null, -(rand(0.5, 3) * severity)) //Lose 0.5-3 flat nanite volume for each severity level
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_emp(severity)

View File

@@ -191,7 +191,7 @@ Class Procs:
/obj/machinery/emp_act(severity)
. = ..()
if(use_power && !stat && !(. & EMP_PROTECT_SELF))
use_power(7500/severity)
use_power(750 * severity)
new /obj/effect/temp_visual/emp(loc)
/obj/machinery/proc/open_machine(drop = TRUE)

View File

@@ -144,7 +144,7 @@
if(!status)
return
if(!(. & EMP_PROTECT_SELF))
if(prob(150/severity))
if(prob(15 * severity))
update_appearance(UPDATE_ICON)
var/list/previous_network = network
network = list()
@@ -164,7 +164,7 @@
if(can_use())
GLOB.cameranet.addCamera(src)
emped = 0 //Resets the consecutive EMP count
addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), 100)
addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), severity SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
for(var/i in GLOB.player_list)
var/mob/M = i
if (M.client.eye == src)

View File

@@ -532,7 +532,7 @@ GLOBAL_VAR_INIT(clones, 0)
. = ..()
if (!(. & EMP_PROTECT_SELF))
var/mob/living/mob_occupant = occupant
if(mob_occupant && prob(100/(severity*efficiency)))
if(mob_occupant && prob(10 * severity / efficiency))
log_cloning("[key_name(mob_occupant)] ejected from [src] at [AREACOORD(src)] due to EMP pulse.")
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))

View File

@@ -137,14 +137,10 @@
/obj/machinery/computer/emp_act(severity)
. = ..()
if (!(. & EMP_PROTECT_SELF))
switch(severity)
if(1)
if(prob(50))
obj_break(ENERGY)
if(2)
if(prob(10))
obj_break(ENERGY)
if(. & EMP_PROTECT_SELF)
return
if(prob(5 * severity))
obj_break(ENERGY)
/obj/machinery/computer/deconstruct(disassembled = TRUE, mob/user)
on_deconstruction()

View File

@@ -120,12 +120,7 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
return
var/empprize = null
var/num_of_prizes = 0
switch(severity)
if(1)
num_of_prizes = rand(1,4)
if(2)
num_of_prizes = rand(0,2)
var/num_of_prizes = rand(0, severity / 2.5)
for(var/i = num_of_prizes; i > 0; i--)
if(override)
empprize = pickweight(prize_override)

View File

@@ -534,7 +534,7 @@
. = ..()
if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
for(var/datum/data/record/R in GLOB.data_core.medical)
if(prob(10/severity))
if(prob(severity))
switch(rand(1,6))
if(1)
if(prob(10))

View File

@@ -875,7 +875,7 @@
return
for(var/datum/data/record/R in GLOB.data_core.security)
if(prob(10/severity))
if(prob(severity))
switch(rand(1,8))
if(1)
if(prob(10))

View File

@@ -586,7 +586,7 @@
. += gear_text
/obj/machinery/door/airlock/clockwork/emp_act(severity)
if(prob(80/severity))
if(prob(8 * severity))
open()
/obj/machinery/door/airlock/clockwork/canAIControl(mob/user)

View File

@@ -315,9 +315,9 @@
. = ..()
if (. & EMP_PROTECT_SELF)
return
if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) )
if(prob(2 * severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) )
INVOKE_ASYNC(src, PROC_REF(open))
if(prob(severity*10 - 20))
if(prob(severity*2 - 20))
if(secondsElectrified == MACHINE_NOT_ELECTRIFIED)
secondsElectrified = MACHINE_ELECTRIFIED_PERMANENT
LAZYADD(shockedby, "\[[time_stamp()]\]EM Pulse")

View File

@@ -423,7 +423,7 @@
return ..()
/obj/machinery/door/window/clockwork/emp_act(severity)
if(prob(80/severity))
if(prob(8 * severity))
open()
/obj/machinery/door/window/clockwork/ratvar_act()

View File

@@ -119,7 +119,7 @@
if (. & EMP_PROTECT_SELF)
return
if(prob(50 / severity))
if(prob(5 * severity))
alarm()
/obj/machinery/firealarm/emag_act(mob/user, obj/item/card/emag/emag_card)

View File

@@ -141,7 +141,7 @@
/obj/machinery/flasher/emp_act(severity)
. = ..()
if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
if(bulb && prob(75/severity))
if(bulb && prob(8 * severity))
flash()
bulb.burn_out()
power_change()

View File

@@ -25,11 +25,10 @@
. = ..()
if (. & EMP_PROTECT_SELF)
return
switch(severity)
if(1)
qdel(src)
if(2)
take_damage(50, BRUTE, ENERGY, 0)
if(severity > EMP_LIGHT)
qdel(src)
return
take_damage(5 * severity, BRUTE, ENERGY, 0)
/obj/structure/emergency_shield/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)

View File

@@ -228,7 +228,7 @@
/obj/machinery/power/engine_capacitor_bank/emp_act(severity)
. = ..()
stored_power = rand(0, stored_power)
stored_power = stored_power * (0.9**(severity)) // exponential decay based on EMP severity, heavy EMPs (10 severity) reduce to 35% power
/obj/machinery/power/engine_capacitor_bank/escape_pod
name = "emergency thruster capacitor bank"

View File

@@ -182,7 +182,7 @@
return
if(prob(1)) // :^)
obj_flags |= EMAGGED
var/severity_ascending = 4 - severity
var/severity_ascending = 2 + (severity / 5)
money = max(rand(money - (200 * severity_ascending), money + (200 * severity_ascending)), 0)
balance = max(rand(balance - (50 * severity_ascending), balance + (50 * severity_ascending)), 0)
money -= max(0, give_payout(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo

View File

@@ -502,16 +502,15 @@
/obj/item/bombcore/emp
name = "EMP payload"
desc = "A set of superconducting electromagnetic coils designed to release a powerful pulse to destroy electronics and scramble circuits"
range_heavy = 15
range_medium = 25
range_heavy = 25 // 25 severity, can do some serious damage
/obj/item/bombcore/emp/detonate()
if(adminlog)
message_admins(adminlog)
log_game(adminlog)
empulse(src, range_heavy, range_medium)
empulse(src, range_heavy)
qdel(src)
///Syndicate Detonator (aka the big red button)///

View File

@@ -190,9 +190,9 @@ GLOBAL_LIST_EMPTY(telecomms_list)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(prob(100/severity) && !(stat & EMPED))
if(prob(10 * severity) && !(stat & EMPED))
stat |= EMPED
var/duration = (300 * 10)/severity
var/duration = (30 SECONDS) * severity // 30 seconds per level of severity, 5 minutes at 10 severity (EMP_HEAVY)
addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 20, duration + 20))
/obj/machinery/telecomms/proc/de_emp()

View File

@@ -161,8 +161,8 @@
if (. & EMP_PROTECT_SELF)
return
if(get_charge())
use_power((cell.charge/3)/(severity*2))
take_damage(40 / severity, BURN, ENERGY, 1)
use_power((cell.charge * severity / 15))
take_damage(4 * severity, BURN, ENERGY, 1)
log_message("EMP detected", LOG_MECHA, color="red")
if(istype(src, /obj/mecha/combat))

View File

@@ -1,32 +1,30 @@
/proc/empulse(turf/epicenter, heavy_range, light_range, log=0)
/proc/empulse(turf/epicenter, severity, range=null, log=TRUE)
if(!epicenter)
CRASH("Warning: empulse() called without an epicenter!")
if(severity < 1)
return
if(!isturf(epicenter))
epicenter = get_turf(epicenter.loc)
if(isnull(range)) // range is equal to severity by default
range = severity
if(log)
message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
message_admins("EMP with size ([range]) and severity ([severity]) in area [epicenter.loc.name] ")
log_game("EMP with size ([range]) and severity ([severity]) in area [epicenter.loc.name] ")
if(heavy_range > 1)
new /obj/effect/temp_visual/emp/pulse(epicenter)
if(range <= 0)
for(var/atom/A in epicenter)
A.emp_act(severity)
return
if(heavy_range > light_range)
light_range = heavy_range
for(var/A in spiral_range(light_range, epicenter))
var/tile_falloff = severity / range
for(var/A in spiral_range(range, epicenter))
var/atom/T = A
var/distance = get_dist(epicenter, T)
if(distance < 0)
distance = 0
if(distance < heavy_range)
T.emp_act(EMP_HEAVY)
else if(heavy_range && distance == heavy_range) //0 radius heavy EMPs will have no effect
if(prob(50))
T.emp_act(EMP_HEAVY)
else
T.emp_act(EMP_LIGHT)
else if(distance <= light_range)
T.emp_act(EMP_LIGHT)
return 1
var/decayed_severity = severity - round(get_dist(epicenter, T) * tile_falloff)
if(decayed_severity < 1)
continue
T.emp_act(decayed_severity)
return TRUE

View File

@@ -105,7 +105,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
var/wipe_chance = 60 / severity
var/wipe_chance = 6 * severity
if(prob(wipe_chance))
visible_message(span_warning("[src] fizzles and disappears!"))
qdel(src) //rip cash

View File

@@ -153,7 +153,7 @@
. = ..()
if(cell && !(. & EMP_PROTECT_CONTENTS))
deductcharge(5000 / severity)
deductcharge(500 * severity)
if (. & EMP_PROTECT_SELF)
return

View File

@@ -1226,7 +1226,7 @@ GLOBAL_LIST_EMPTY(PDAs)
A.emp_act(severity)
if (!(. & EMP_PROTECT_SELF))
emped += 1
spawn(200 * severity)
spawn(20 * severity)
emped -= 1
/proc/get_viewable_pdas()

View File

@@ -429,7 +429,6 @@ GLOBAL_LIST_INIT(channel_tokens, list(
if (. & EMP_PROTECT_SELF)
return
emped++ //There's been an EMP; better count it
var/curremp = emped //Remember which EMP this was
if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice
to_chat(loc, span_warning("\The [src] overloads."))
broadcasting = FALSE
@@ -437,11 +436,9 @@ GLOBAL_LIST_INIT(channel_tokens, list(
for (var/ch_name in channels)
channels[ch_name] = 0
on = FALSE
addtimer(CALLBACK(src, PROC_REF(end_emp_effect), curremp), 200)
addtimer(CALLBACK(src, PROC_REF(end_emp_effect)), 20 * severity, TIMER_UNIQUE | TIMER_OVERRIDE)
/obj/item/radio/proc/end_emp_effect(curremp)
if(emped != curremp) //Don't fix it if it's been EMP'd again
return FALSE
/obj/item/radio/proc/end_emp_effect()
emped = FALSE
on = TRUE
return TRUE

View File

@@ -17,4 +17,4 @@
/obj/item/book/granter/action/spell/charge/recoil(mob/living/user)
. = ..()
to_chat(user,span_warning("[src] suddenly feels very warm!"))
empulse(src, 1, 1)
empulse(src, EMP_HEAVY, 0)

View File

@@ -151,7 +151,7 @@
/obj/item/grenade/chem_grenade/emp_act(severity)
..()
if(prob(40/severity))
if(prob(4 * severity))
prime()
/obj/item/grenade/chem_grenade/on_found(mob/finder)

View File

@@ -6,5 +6,5 @@
/obj/item/grenade/empgrenade/prime()
update_mob()
empulse(src, 4, 10)
empulse(src, EMP_HEAVY)
qdel(src)

View File

@@ -64,7 +64,7 @@
/obj/item/implant/emp/activate()
. = ..()
uses--
empulse(imp_in, 3, 5)
empulse(imp_in, EMP_HEAVY, 5) // 10 severity, extends to 5 tiles
if(!uses)
qdel(src)
@@ -174,13 +174,13 @@
UnregisterSignal(target, COMSIG_ATOM_EMP_ACT)
return TRUE
/obj/item/implant/empshield/proc/overloaded(mob/living/target)
/obj/item/implant/empshield/proc/overloaded(mob/living/target, severity)
if(world.time - lastemp > overloadtimer)
numrecent = 0
numrecent ++
numrecent += severity
lastemp = world.time
if(numrecent >= 5 && ishuman(target))
if(numrecent >= (5 * EMP_HEAVY) && ishuman(target))
if(warning)
to_chat(target, span_userdanger("You feel a twinge inside from your [src], you get the feeling it won't protect you anymore."))
warning = FALSE

View File

@@ -78,19 +78,18 @@
togglelock(user)
/obj/item/storage/lockbox/emp_act(severity)
switch(severity)
if(EMP_HEAVY)
emag_act()
if(EMP_LIGHT)
if(prob(60))
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !locked)
locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if(locked)
icon_state = icon_locked
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_HIDE_ALL)
else
icon_state = icon_closed
if(severity > EMP_LIGHT)
emag_act()
return
if(prob(6 * severity))
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !locked)
locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if(locked)
icon_state = icon_locked
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_HIDE_ALL)
else
icon_state = icon_closed
/obj/item/storage/lockbox/loyalty
name = "lockbox of mindshield implants"

View File

@@ -257,7 +257,7 @@
/obj/item/melee/baton/emp_act(severity)
. = ..()
if (!(. & EMP_PROTECT_SELF))
deductcharge(1000 / severity)
deductcharge(100 * severity)
//Makeshift stun baton. Replacement for stun gloves.
/obj/item/melee/baton/cattleprod

View File

@@ -201,7 +201,7 @@
investigate_log("has consumed [key_name(user)].", "supermatter")
user.dust()
radiation_pulse(src, 500, 2)
empulse(src, 5, 10)
empulse(src, EMP_HEAVY)
playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
QDEL_NULL(shard)
update_appearance(UPDATE_ICON)

View File

@@ -550,10 +550,10 @@ GLOBAL_LIST_EMPTY(lockers)
for(var/obj/O in src)
O.emp_act(severity)
if(secure && !broken && !(. & EMP_PROTECT_SELF))
if(prob(50 / severity))
if(prob(5 * severity))
locked = !locked
update_appearance(UPDATE_ICON)
if(prob(20 / severity) && !opened)
if(prob(2 * severity) && !opened)
if(!locked)
open()
else

View File

@@ -703,18 +703,17 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_ADMIN))
return
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null)
return
var/light = input("Range of light pulse.", text("Input")) as num|null
if(light == null)
var/severity = input("Severity of pulse.", text("Input")) as num|null
if(!isnum(severity))
return
var/range = input("Range of pulse.", text("Input")) as num|null
if(!isnum(range))
range = severity
if (heavy || light)
empulse(O, heavy, light)
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
if (severity)
empulse(O, severity, range)
log_admin("[key_name(usr)] created an EM Pulse ([range] range, [severity] severity) at [AREACOORD(O)]")
message_admins("[key_name_admin(usr)] created an EM Pulse ([range] range, [severity] severity) at [AREACOORD(O)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return

View File

@@ -22,7 +22,7 @@
/datum/blobstrain/reagent/electromagnetic_web/death_reaction(obj/structure/blob/B, damage_flag)
if(damage_flag == MELEE || damage_flag == BULLET || damage_flag == LASER)
empulse(B.loc, 1, 3) //less than screen range, so you can stand out of range to avoid it
empulse(B.loc, EMP_HEAVY, 3) //less than screen range, so you can stand out of range to avoid it
/datum/reagent/blob/electromagnetic_web
name = "Electromagnetic Web"
@@ -32,6 +32,6 @@
/datum/reagent/blob/electromagnetic_web/reaction_mob(mob/living/M, methods = TOUCH, reac_volume, show_message, permeability, mob/camera/blob/O)
reac_volume = ..()
if(prob(reac_volume*2))
M.emp_act(EMP_LIGHT)
M.emp_act(min(reac_volume / 10, EMP_HEAVY))
if(M)
M.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND)

View File

@@ -206,7 +206,7 @@
if(severity > 0)
if(overmind)
overmind.blobstrain.emp_reaction(src, severity)
if(prob(100 - severity * 30))
if(prob(40 + (severity * 6)))
new /obj/effect/temp_visual/emp(get_turf(src))
/obj/structure/blob/tesla_act(power, tesla_flags, shocked_targets, zap_gib = FALSE)

View File

@@ -53,5 +53,5 @@
for(var/obj/machinery/light/L in range(5, usr))
L.on = 1
L.break_light_tube()
empulse(get_turf(user), 2, 5, 1)
empulse(get_turf(user), EMP_HEAVY, 5, 1)
return TRUE

View File

@@ -8,13 +8,14 @@
block_chance = 35
attack_verb = list("attacked", "slashed", "cut", "torn", "gored")
clockwork_desc = "A powerful sword of Ratvarian making. Enemies hit with it will be struck with a powerful electromagnetic pulse."
var/emp_severity = EMP_LIGHT
var/emp_cooldown = 0
var/cooldown_duration = 10 SECONDS
/obj/item/clockwork/weapon/brass_sword/attack(mob/living/target, mob/living/carbon/human/user)
. = ..()
if(world.time > emp_cooldown && !is_servant_of_ratvar(target))
target.emp_act(EMP_LIGHT)
target.emp_act(emp_severity)
emp_cooldown = world.time + cooldown_duration
addtimer(CALLBACK(src, PROC_REF(send_message)), cooldown_duration)
to_chat(user, "<span class='brass'>You strike [target] with an electromagnetic pulse!</span>")
@@ -24,7 +25,7 @@
/obj/item/clockwork/weapon/brass_sword/attack_obj(obj/O, mob/living/user)
. = ..()
if(world.time > emp_cooldown && ismecha(O))
O.emp_act(EMP_HEAVY)
O.emp_act(emp_severity * 2)
emp_cooldown = world.time + cooldown_duration
addtimer(CALLBACK(src, PROC_REF(send_message)), cooldown_duration)
to_chat(user, "<span class='brass'>You strike [O] with an electromagnetic pulse!</span>")

View File

@@ -1046,7 +1046,7 @@ structure_check() searches for nearby cultist structures required for the invoca
visible_message(span_warning("A colossal shockwave of energy bursts from the rune, disintegrating it in the process!"))
for(var/mob/living/L in range(src, 3))
L.Paralyze(30)
empulse(T, 0.42*(intensity), 1)
empulse(T, 0.42*(intensity))
var/list/images = list()
var/zmatch = T.z
var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]

View File

@@ -156,8 +156,7 @@ THIS FILE IS FOR ALL HERETIC SPELLS THAT DO NOT CONFER TO A PATH'S THEME OR YOU
invocation_type = INVOCATION_WHISPER
spell_requirements = SPELL_CASTABLE_WITHOUT_INVOCATION | SPELL_REQUIRES_NO_ANTIMAGIC
emp_heavy = 6
emp_light = 10
radius = 10
/datum/action/cooldown/spell/list_target/telepathy/eldritch
name = "Eldritch Telepathy"

View File

@@ -439,8 +439,7 @@
var/devastating_explosion = 0
var/em_pulse = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_EMP
var/rad_pulse = selected_fuel.meltdown_flags & HYPERTORUS_FLAG_RADIATION_PULSE
var/emp_light_size = 0
var/emp_heavy_size = 0
var/emp_severity = 0
var/rad_pulse_size = 0
var/rad_pulse_strength = 0
var/gas_spread = 0
@@ -464,8 +463,7 @@
if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MINIMUM_SPREAD)
if(em_pulse)
emp_light_size = power_level * 3
emp_heavy_size = power_level * 1
emp_severity = power_level * 3
if(rad_pulse)
rad_pulse_size = (1 / (power_level + 1))
rad_pulse_strength = power_level * 3000
@@ -474,8 +472,7 @@
if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MEDIUM_SPREAD)
if(em_pulse)
emp_light_size = power_level * 5
emp_heavy_size = power_level * 3
emp_severity = power_level * 5
if(rad_pulse)
rad_pulse_size = (1 / (power_level + 3))
rad_pulse_strength = power_level * 5000
@@ -484,8 +481,7 @@
if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_BIG_SPREAD)
if(em_pulse)
emp_light_size = power_level * 7
emp_heavy_size = power_level * 5
emp_severity = power_level * 7
if(rad_pulse)
rad_pulse_size = (1 / (power_level + 5))
rad_pulse_strength = power_level * 7000
@@ -494,8 +490,7 @@
if(selected_fuel.meltdown_flags & HYPERTORUS_FLAG_MASSIVE_SPREAD)
if(em_pulse)
emp_light_size = power_level * 9
emp_heavy_size = power_level * 7
emp_severity = power_level * 9
if(rad_pulse)
rad_pulse_size = (1 / (power_level + 7))
rad_pulse_strength = power_level * 9000
@@ -550,8 +545,7 @@
if(em_pulse)
empulse(
epicenter = loc,
heavy_range = critical ? emp_heavy_size * 2 : emp_heavy_size,
light_range = critical ? emp_light_size * 2 : emp_heavy_size,
severity = critical ? emp_severity * 2 : emp_severity,
log = TRUE
)

View File

@@ -62,9 +62,9 @@
if(. & EMP_PROTECT_SELF)
return
if(is_operational())
if(prob(50 / severity))
if(prob(5 * severity))
on = !on
if(prob(100 / severity))
if(prob(10 * severity))
direction = PUMP_OUT
pump.target_pressure = rand(0, 100 * ONE_ATMOSPHERE)
update_appearance(UPDATE_ICON)

View File

@@ -64,7 +64,7 @@
if(. & EMP_PROTECT_SELF)
return
if(is_operational())
if(prob(50 / severity))
if(prob(5 * severity))
on = !on
update_appearance(UPDATE_ICON)

View File

@@ -515,17 +515,15 @@
cloak_charge_rate = 20
cloak_dodge_loss = 40
var/cloak_emp_disable_duration = 10 SECONDS
var/cloak_emp_loss = 25
var/cloak_emp_loss = 5
/obj/item/clothing/neck/cloak/ranger/syndie/emp_act(severity)
. = ..()
if(CHECK_BITFIELD(., EMP_PROTECT_SELF))
return
if(severity == EMP_HEAVY)
set_cloak(0)
if(severity > EMP_LIGHT)
TIMER_COOLDOWN_START(src, "cloak_emp_disable", cloak_emp_disable_duration)
else
set_cloak(cloak - cloak_emp_loss)
set_cloak(max(cloak - (cloak_emp_loss * severity), 0))
/obj/item/clothing/neck/cloak/ranger/syndie/process(delta_time)
if(TIMER_COOLDOWN_CHECK(src, "cloak_emp_disable"))

View File

@@ -88,7 +88,7 @@
/obj/item/clothing/neck/bodycam/emp_act(severity)
. = ..()
if(prob(150/severity))
if(prob(15 * severity))
Disconnect()
bodcam.c_tag = null
bodcam.network[1] = null //requires a reset

View File

@@ -73,13 +73,11 @@
if(. & EMP_PROTECT_SELF)
return
var/mob/living/carbon/human/user = src.loc
switch(severity)
if(1)
if(activated && user && ishuman(user) && (user.wear_suit == src))
to_chat(user, span_danger("E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD"))
to_chat(user, span_userdanger("An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!"))
user.emote("scream")
deactivate(1, 1)
if(severity > EMP_LIGHT && activated && user && ishuman(user) && (user.wear_suit == src))
to_chat(user, span_danger("E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD"))
to_chat(user, span_userdanger("An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!"))
user.emote("scream")
deactivate(1, 1)
/obj/item/clothing/suit/space/chronos/proc/finish_chronowalk(mob/living/carbon/human/user, turf/to_turf)
if(!user)

View File

@@ -144,7 +144,7 @@
/obj/item/clothing/head/helmet/space/hardsuit/emp_act(severity)
. = ..()
display_visor_message("[severity > 1 ? "Light" : "Strong"] electromagnetic pulse detected!")
display_visor_message("Electromagnetic pulse detected! Severity: [severity]")
/obj/item/clothing/suit/space/hardsuit

View File

@@ -117,7 +117,7 @@
if(ismob(loc))
to_chat(loc, emp_message)
bad_effect = TRUE
addtimer(VARSET_CALLBACK(src, bad_effect, FALSE), 30 SECONDS)
addtimer(VARSET_CALLBACK(src, bad_effect, FALSE), (3 SECONDS) * severity)
//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
/obj/item/clothing/suit/armor/reactive/teleport

View File

@@ -52,7 +52,7 @@
playsound(src,'sound/effects/sparks4.ogg',50,1)
qdel(src)
/obj/item/wormhole_jaunter/emp_act(power)
/obj/item/wormhole_jaunter/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
@@ -60,11 +60,8 @@
var/mob/M = loc
if(istype(M))
var/triggered = FALSE
if(M.get_item_by_slot(ITEM_SLOT_BELT) == src)
if(power == 1)
triggered = TRUE
else if(power == 2 && prob(50))
triggered = TRUE
if(M.get_item_by_slot(ITEM_SLOT_BELT) == src && prob(10 * severity))
triggered = TRUE
if(triggered)
M.visible_message(span_warning("[src] overloads and activates!"))

View File

@@ -287,15 +287,10 @@
var/obj/item/clothing/head/hat = owner.get_item_by_slot(ITEM_SLOT_HEAD)
if(hat && istype(hat, /obj/item/clothing/head/foilhat))
return
owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, (50/severity) * (maxHealth - damage) / maxHealth)
owner.adjust_drugginess(40/severity)
switch(severity)
if(1)
to_chat(owner, span_warning("Alert: Posibrain heavily damaged."))
if(2)
to_chat(owner, span_warning("Alert: Posibrain damaged."))
to_chat(owner, span_warning("Alert: Posibrain [severity > EMP_LIGHT ? "severely " : ""]damaged."))
owner.adjust_drugginess(5 * severity)
if(severity > EMP_LIGHT)
owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, (2 * (severity - EMP_LIGHT)) * (maxHealth - damage) / maxHealth) // don't give traumas from weak EMPs
////////////////////////////////////TRAUMAS////////////////////////////////////////

View File

@@ -372,13 +372,16 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(HAS_TRAIT(src, TRAIT_FARADAYCAGE))
severity++
if(severity > EMP_LIGHT)
return
for(var/X in internal_organs)
var/obj/item/organ/O = X
O.emp_act(severity)
if(dna?.species)
severity *= dna.species.emp_mod
if(severity < 1)
return
var/emp_message = TRUE
for(var/obj/item/bodypart/BP as anything in get_damageable_bodyparts(BODYPART_ROBOTIC))
if(!(BP.emp_act(severity, emp_message) & EMP_PROTECT_SELF))
emp_message = FALSE // if the EMP was successful, don't spam the chat with more messages
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE, gib = FALSE)
if(tesla_shock && (flags_1 & TESLA_IGNORE_1))

View File

@@ -547,32 +547,8 @@
return dna.species.spec_emag_act(src, user, emag_card)
/mob/living/carbon/human/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(HAS_TRAIT(src, TRAIT_FARADAYCAGE))
severity++
if(severity > EMP_LIGHT)
return
dna?.species.spec_emp_act(src, severity)
var/list/affected_parts = list()
for(var/obj/item/bodypart/BP in bodyparts)
if(istype(BP) && BP.status == BODYPART_ROBOTIC)
if(prob(5) && severity == EMP_HEAVY && (TRAIT_EASYDISMEMBER in dna?.species.inherent_traits) && BP.body_zone != BODY_ZONE_CHEST)
BP.dismember()
else
affected_parts += BP
if(affected_parts.len)
emote("scream")
adjustFireLoss(min(5 * affected_parts.len / severity, 20 / severity), FALSE, FALSE, BODYPART_ROBOTIC)
var/obj/item/bodypart/chest/C = get_bodypart(BODY_ZONE_CHEST)
var/obj/item/bodypart/head/H = get_bodypart(BODY_ZONE_HEAD)
if(((C && C.status == BODYPART_ROBOTIC) || (H && H.status == BODYPART_ROBOTIC)) && severity == EMP_HEAVY) // if your head and/or chest are robotic (aka you're a robotic race or augmented) you get cooler flavor text and rapid-onset paralysis
to_chat(src, span_userdanger("A surge of searing pain erupts throughout your very being! As the pain subsides, a terrible sensation of emptiness is left in its wake."))
Paralyze(5 SECONDS) //heavy EMPs will fully stun you
else
adjustStaminaLoss(min(15 * affected_parts.len / severity, 60 / severity), FALSE, FALSE, BODYPART_ROBOTIC)
to_chat(src, span_userdanger("You feel a sharp pain as your robotic limbs overload."))
severity *= physiology.emp_mod
return ..(severity)
/mob/living/carbon/human/rad_act(amount, collectable_radiation)
. = ..()

View File

@@ -17,6 +17,7 @@
var/damage_resistance = 0 // %damage reduction from all sources
var/siemens_coeff = 1 // resistance to shocks
var/emp_mod = 1 // resistance to EMPs
var/stun_mod = 1 // % stun modifier
var/bleed_mod = 1 // % bleeding modifier

View File

@@ -97,6 +97,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/staminamod = 1
/// multiplier for pressure damage
var/pressuremod = 1
/// multiplier for EMP severity
var/emp_mod = 1
/// multiplier for money paid at payday, species dependent
var/payday_modifier = 1
///Type of damage attack does
@@ -2577,6 +2579,22 @@ GLOBAL_LIST_EMPTY(features_by_species)
SPECIES_PERK_DESC = "[plural_form] are resilient to being shocked.",
))
if(emp_mod > 1)
to_add += list(list(
SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK,
SPECIES_PERK_ICON = "thunderstorm",
SPECIES_PERK_NAME = "EM Weakness",
SPECIES_PERK_DESC = "[plural_form] are weak to electromagnetic interference.",
))
if(emp_mod < 1)
to_add += list(list(
SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK,
SPECIES_PERK_ICON = "thunderstorm", //if we update font awesome, please swap to bolt-slash
SPECIES_PERK_NAME = "EM Resistance",
SPECIES_PERK_DESC = "[plural_form] are resistant to electromagnetic interference.",
))
return to_add
/**
@@ -2675,15 +2693,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
SPECIES_PERK_NAME = "Radiation Immunity",
SPECIES_PERK_DESC = "[plural_form] are completely unaffected by radiation. However, this doesn't mean they can't be irradiated.",
))
if(TRAIT_FARADAYCAGE in inherent_traits)
to_add += list(list(
SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK,
SPECIES_PERK_ICON = "thunderstorm", //if we update font awesome, please swap to bolt-slash
SPECIES_PERK_NAME = "Faraday \"Skin\"",
SPECIES_PERK_DESC = "[plural_form] have a unique physiology that shields them from weak EMPs.",
))
if(TRAIT_LIMBATTACHMENT in inherent_traits)
to_add += list(list(
SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK,

View File

@@ -133,7 +133,7 @@
to_chat(H, span_notice("You feel the light of your body leave you."))
EMPeffect = TRUE
spec_updatehealth(H)
addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 200 / severity, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 10 to 20 seconds depending on severity
addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 20 * severity, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 2 to 20 seconds depending on severity
/datum/species/ethereal/proc/stop_emp(mob/living/carbon/human/H)
EMPeffect = FALSE

View File

@@ -6,16 +6,16 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
take_holo_damage(50/severity)
Paralyze(400/severity)
silent = max(30/severity, silent)
take_holo_damage(5 * severity)
Paralyze(40 * severity)
silent = max(3 * severity, silent)
if(holoform)
fold_in(force = TRUE)
//Need more effects that aren't instadeath or permanent law corruption.
//Ask and you shall receive
switch(rand(1, 3))
if(1)
adjust_stutter(1 MINUTES / severity)
adjust_stutter((6 * severity) SECONDS)
to_chat(src, span_danger("Warning: Feedback loop detected in speech module."))
if(2)
adjust_slurring(INFINITY)

View File

@@ -80,11 +80,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
switch(severity)
if(1)
Stun(160)
if(2)
Stun(60)
Stun(min((1.6 SECONDS) * severity, 16 SECONDS)) // up to 16 seconds
/mob/living/silicon/robot/emag_act(mob/user, obj/item/card/emag/emag_card)

View File

@@ -109,14 +109,10 @@
to_chat(src, span_danger("Warning: Electromagnetic pulse detected."))
if(. & EMP_PROTECT_SELF)
return
switch(severity)
if(1)
src.take_bodypart_damage(20)
if(2)
src.take_bodypart_damage(10)
take_bodypart_damage(2 * severity)
to_chat(src, span_userdanger("*BZZZT*"))
for(var/mob/living/M in buckled_mobs)
if(prob(severity*50))
if(prob(5 * severity))
unbuckle_mob(M)
M.Paralyze(40)
M.visible_message(span_boldwarning("[M] is thrown off of [src]!"))

View File

@@ -364,7 +364,7 @@
ejectpai(0)
if(on)
turn_off()
spawn(severity*300)
spawn(30 * severity)
stat &= ~EMPED
if(was_on)
turn_on()

View File

@@ -459,12 +459,10 @@ Auto Patrol[]"},
/mob/living/simple_animal/bot/ed209/emp_act(severity)
if(severity == 2 && prob(70))
severity = 1
. = ..()
if(. & EMP_PROTECT_SELF)
return
if (severity >= 2)
if (severity > EMP_LIGHT || prob(70))
new /obj/effect/temp_visual/emp(loc)
var/list/mob/living/carbon/targets = new
for(var/mob/living/carbon/C in view(12,src))

View File

@@ -229,9 +229,9 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
Stun(100)
Stun(10 * severity)
to_chat(src, span_danger("<b>ER@%R: MME^RY CO#RU9T!</b> R&$b@0tin)..."))
if(severity == 1)
if(severity > EMP_LIGHT)
adjustBruteLoss(heavy_emp_damage)
to_chat(src, span_userdanger("HeAV% DA%^MMA+G TO I/O CIR!%UUT!"))

View File

@@ -6,5 +6,5 @@
if(!ninjacost(250,N_STEALTH_CANCEL))
var/mob/living/carbon/human/H = affecting
playsound(H.loc, 'sound/effects/empulse.ogg', 60, 2)
empulse(H, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch.
empulse(H, EMP_HEAVY, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch.
s_coold = 4

View File

@@ -154,7 +154,7 @@
if(on) // EMP will only work on cameras that are on as it has power going through it
icon_state = state_off
on = FALSE
addtimer(CALLBACK(src, PROC_REF(emp_after)), (600/severity))
addtimer(CALLBACK(src, PROC_REF(emp_after)), (6*severity) SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
/obj/item/camera/proc/emp_after()
on = TRUE

View File

@@ -1466,7 +1466,7 @@
environ = 0
update_appearance(UPDATE_ICON)
update()
addtimer(CALLBACK(src, PROC_REF(reset), APC_RESET_EMP), 600)
addtimer(CALLBACK(src, PROC_REF(reset), APC_RESET_EMP), (6 * severity) SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
/obj/machinery/power/apc/blob_act(obj/structure/blob/B)
set_broken()

View File

@@ -179,7 +179,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
charge -= max((charge * 0.1), 500) / severity
charge -= max((charge * severity / 100), 50 * severity)
if (charge < 0)
charge = 0
@@ -392,7 +392,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
charge = clamp((charge-(10000/severity)),0,maxcharge)
charge = clamp((charge-(1000 * severity)),0,maxcharge)
/obj/item/stock_parts/cell/emergency_light
name = "miniature power cell"

View File

@@ -583,7 +583,7 @@
/obj/singularity/proc/emp_area()
empulse(src, 8, 10)
empulse(src, EMP_HEAVY)
return
/obj/singularity/singularity_act()

View File

@@ -417,7 +417,7 @@
outputting = output_attempt
output_level = rand(0, output_level_max)
input_level = rand(0, input_level_max)
charge = max(charge - 1e6/severity, 0)
charge = max(charge - (1e5 * severity), 0)
update_appearance(UPDATE_ICON)
log_smes()

View File

@@ -758,7 +758,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
radiation_pulse(src, (100-support_integrity)*2, 4)
if(support_integrity<3)
var/emp_power = round(explosion_power * (1+(1-(support_integrity/3))),1)
empulse(src, emp_power, emp_power*2)
empulse(src, emp_power)
if(support_integrity<100)
power += round((100-support_integrity)/2,1)
if(support_integrity<70)
@@ -779,7 +779,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(istype(T, /turf/open/space) || T.return_air().total_moles() < MOLE_SPACE_THRESHOLD)
damage += DAMAGE_HARDCAP * explosion_point //Can't cheat by spacing the crystal to buy time, it will just delaminate faster
if(prob(2))
empulse(src, 10-support_integrity, (10-support_integrity)*2) //EMPs must always be spewing every so often to ensure that containment is guaranteed to fail.
empulse(src, 10-support_integrity) //EMPs must always be spewing every so often to ensure that containment is guaranteed to fail.
return 1
/obj/machinery/power/supermatter_crystal/bullet_act(obj/projectile/Proj)
@@ -1004,7 +1004,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
to_chat(user, "<span class='danger'>You attach the antinoblium shard to the [src], moving your hand away before a sudden gravitational wave pulls the [W] into the crystal as it flashes to ash!")
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1)
radiation_pulse(src, 150, 4)
empulse(src, 3,6)
empulse(src, EMP_HEAVY, 6)
qdel(W)
return
else if(user.dropItemToGround(W))

View File

@@ -231,10 +231,10 @@
/obj/item/ammo_casing/shotgun/hardlight/emp_act(severity)
if (. & EMP_PROTECT_SELF)
return
variance = 60 // yikes
if(severity == EMP_HEAVY)
pellets = 3 // also yikes
addtimer(CALLBACK(src, PROC_REF(remove_emp)), 10 SECONDS / severity, TIMER_OVERRIDE|TIMER_UNIQUE)
variance = initial(variance) + severity*4 // yikes
if(severity > EMP_LIGHT)
pellets = initial(pellets) * (0.5**(severity / EMP_HEAVY)) // also yikes
addtimer(CALLBACK(src, PROC_REF(remove_emp)), severity SECONDS, TIMER_OVERRIDE|TIMER_UNIQUE)
/obj/item/ammo_casing/shotgun/hardlight/proc/remove_emp()
variance = initial(variance)

View File

@@ -4,7 +4,7 @@
fire_sound = 'sound/weapons/ionrifle.ogg'
/obj/item/ammo_casing/energy/ion/hos
projectile_type = /obj/projectile/ion/light
projectile_type = /obj/projectile/ion/weak
e_cost = 200
/obj/item/ammo_casing/energy/ion/weak

View File

@@ -464,23 +464,23 @@
if(/obj/item/singularity_shard/stage2)
break_chance = 0.5
rads_released = 200
empulse(src, 0, 1)
empulse(src, 1)
if(/obj/item/singularity_shard/stage3)
break_chance = 1.5
rads_released = 500
empulse(src, 0, 3)
empulse(src, 3)
if(/obj/item/singularity_shard/stage4)
break_chance = 5
rads_released = 1000
empulse(src, 1, 5)
empulse(src, 5)
if(/obj/item/singularity_shard/stage5)
break_chance = 10
rads_released = 2000
empulse(src, 2, 7)
empulse(src, 7)
if(/obj/item/singularity_shard/stage6)
break_chance = 100
rads_released = 3000
empulse(src, 5, 15) // Its going to break open into a singulo anyways, may as well add some fireworks
empulse(src, 15) // Its going to break open into a singulo anyways, may as well add some fireworks
// Handles releasing rads
if(rads_released)

View File

@@ -102,7 +102,7 @@
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
var/bullet_count = ammo_count()
var/bullets_to_remove = round(bullet_count / (severity*2))
var/bullets_to_remove = round(bullet_count * (0.5**(severity/EMP_HEAVY)))
for(var/i = 0; i < bullets_to_remove, i++)
qdel(get_round())
update_appearance(UPDATE_ICON)
@@ -111,8 +111,8 @@
if(!G.magazine == src)
return
G.semicd = TRUE
// 5-10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears
var/unjam_time = ((10/severity) + (rand(-20,20)*0.01)) SECONDS
// up to 10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears
var/unjam_time = (min(severity, EMP_HEAVY) + (rand(-20,20)*0.01)) SECONDS
addtimer(CALLBACK(G, TYPE_PROC_REF(/obj/item/gun, reset_semicd)), unjam_time)
/obj/item/ammo_casing/caseless/c22hl

View File

@@ -36,11 +36,11 @@
/obj/item/gun/energy/emp_act(severity)
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
cell.use(round(cell.charge / (severity*2)))
cell.use(round(cell.charge * (0.5**(severity/EMP_HEAVY))))
emp_jammed = TRUE
deltimer(emp_jam_timer)
// 5-10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears
var/unjam_time = ((10/severity) + (rand(-20,20)*0.01)) SECONDS
// up to 10 seconds depending on severity, then give or take 0.2 seconds to prevent piercing ears
var/unjam_time = (min(severity, EMP_HEAVY) + (rand(-20,20)*0.01)) SECONDS
emp_jam_timer = addtimer(CALLBACK(src, PROC_REF(emp_unjam)), unjam_time, TIMER_STOPPABLE)
chambered = null //we empty the chamber
recharge_newshot() //and try to charge a new shot

View File

@@ -64,7 +64,7 @@
/obj/projectile/bullet/c10mm/emp/on_hit(atom/target, blocked = FALSE)
..()
empulse(target, 0.5, 1) //Heavy EMP on target, light EMP in tiles around
empulse(target, EMP_HEAVY, 1) //Heavy EMP on target, light EMP in tiles around
/obj/projectile/bullet/boltpistol
name = "Bolt round"

View File

@@ -1102,10 +1102,10 @@
nodamage = TRUE
armor_flag = ENERGY
impact_effect_type = /obj/effect/temp_visual/impact_effect/ion
var/light_emp_radius = 3
var/heavy_emp_radius = 0.5 //Effectively 1 but doesnt spread to adjacent tiles
var/ion_severity = EMP_HEAVY //Heavy EMP effect that doesn't spread to adjacent tiles
var/ion_range = 3
/obj/projectile/magic/ion/on_hit(atom/target, blocked = FALSE)
..()
empulse(target, heavy_emp_radius, light_emp_radius)
empulse(target, ion_severity, ion_range)
return BULLET_ACT_HIT

View File

@@ -6,22 +6,18 @@
nodamage = TRUE
armor_flag = ENERGY
impact_effect_type = /obj/effect/temp_visual/impact_effect/ion
var/light_emp_radius = 1
var/heavy_emp_radius = 0.5 //Effectively 1 but doesnt spread to adjacent tiles
var/ion_severity = EMP_HEAVY // Heavy EMP effects that don't spread to adjacent tiles
var/ion_range = 1
/obj/projectile/ion/on_hit(atom/target, blocked = FALSE)
..()
empulse(target, heavy_emp_radius, light_emp_radius)
empulse(target, ion_severity, ion_range)
return BULLET_ACT_HIT
/obj/projectile/ion/weak
light_emp_radius = 0
heavy_emp_radius = 0
/obj/projectile/ion/light
light_emp_radius = 1
heavy_emp_radius = 0
ion_severity = EMP_LIGHT // weak ions
ion_range = 0
/obj/projectile/ion/heavy
light_emp_radius = 2
heavy_emp_radius = 2
ion_severity = 15 // STRONG ions
ion_range = 2

View File

@@ -119,10 +119,10 @@
/datum/chemical_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
// 100 created volume = 8 heavy range & 14 light range. 4 tiles larger than traitor EMP grenades.
// 200 created volume = 16 heavy range & 28 light range. 12 tiles larger than traitor EMP grenades. This is the maximum
// 100 created volume = 8 severity & 14 range. 4 tiles larger than traitor EMP grenades.
// 200 created volume = 16 (capped to 10) severity & 28 range. 12 tiles larger than traitor EMP grenades. This is the maximum
created_volume = min(created_volume, 200)
empulse(location, round(created_volume / 12), round(created_volume / 7), 1)
empulse(location, min(round(created_volume / 12), EMP_HEAVY), round(created_volume / 7), 1)
holder.clear_reagents()

View File

@@ -354,7 +354,7 @@
required_other = TRUE
/datum/chemical_reaction/slime/slimeoverload/on_reaction(datum/reagents/holder, created_volume)
empulse(get_turf(holder.my_atom), 3, 7)
empulse(get_turf(holder.my_atom), 7)
..()
/datum/chemical_reaction/slime/slimecell

View File

@@ -369,7 +369,7 @@
else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
autoexperiment = 0
visible_message(span_warning("[src] melts [exp_on], ionizing the air around it!"))
empulse(loc, 4, 6)
empulse(loc, 6)
investigate_log("Experimentor has generated an Electromagnetic Pulse.", INVESTIGATE_EXPERIMENTOR)
ejectItem(TRUE)
////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -194,7 +194,7 @@
/datum/nanite_program/proc/on_emp(severity)
if(program_flags & NANITE_EMP_IMMUNE)
return
if(prob(80 / severity))
if(prob(8 * severity))
software_error()
/datum/nanite_program/proc/on_shock(shock_damage)

View File

@@ -134,7 +134,7 @@
/datum/nanite_program/triggered/emp/trigger()
if(!..())
return
empulse(host_mob, 1, 2)
empulse(host_mob, EMP_HEAVY, 2)
/datum/nanite_program/pyro/active_effect()
host_mob.adjust_fire_stacks(1)

View File

@@ -96,12 +96,12 @@
working = TRUE
update_appearance(UPDATE_ICON)
/obj/machinery/rnd/server/emp_act()
/obj/machinery/rnd/server/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
stat |= EMPED
addtimer(CALLBACK(src, PROC_REF(unemp)), 600)
addtimer(CALLBACK(src, PROC_REF(unemp)), (6 * severity) SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
refresh_working()
/obj/machinery/rnd/server/proc/unemp()

View File

@@ -279,7 +279,7 @@
if(SLIME_ACTIVATE_MAJOR)
user.visible_message(span_warning("[user]'s skin starts flashing intermittently..."), span_warning("Your skin starts flashing intermittently..."))
if(do_after(user, 2.5 SECONDS, user))
empulse(user, 1, 2)
empulse(user, EMP_HEAVY, 2)
user.visible_message(span_warning("[user]'s skin flashes!"), span_warning("Your skin flashes as you emit an electromagnetic pulse!"))
return 600

View File

@@ -6,14 +6,14 @@
school = SCHOOL_EVOCATION
/// The heavy radius of the EMP
var/emp_heavy = 2
/// The light radius of the EMP
var/emp_light = 3
/// The severity of the EMP
var/severity = EMP_HEAVY
/// The radius of the EMP
var/radius = 3
/datum/action/cooldown/spell/emp/cast(atom/cast_on)
. = ..()
empulse(get_turf(cast_on), emp_heavy, emp_light)
empulse(get_turf(cast_on), severity, radius)
/datum/action/cooldown/spell/emp/disable_tech
name = "Disable Tech"
@@ -26,5 +26,4 @@
invocation = "NEC CANTIO"
invocation_type = INVOCATION_SHOUT
emp_heavy = 6
emp_light = 10
radius = 10

View File

@@ -45,6 +45,7 @@
var/brute_reduction = 0 //Subtracted to brute damage taken
var/burn_reduction = 0 //Subtracted to burn damage taken
var/emp_reduction = 0 //Subtracted to EMP severity
//Coloring and proper item icon update
var/skin_tone = ""
@@ -127,6 +128,32 @@
/obj/item/bodypart/blob_act()
take_damage(max_damage)
/obj/item/bodypart/emp_act(severity, emp_message=TRUE)
. = ..()
if(. & EMP_PROTECT_SELF)
return
var/blocked = owner.getarmor(body_zone, ENERGY) // energy armor protects against EMPs
severity *= (100 - blocked) / 100
severity -= emp_reduction
if(severity < 1)
return
if(receive_damage(0, severity / 2, severity, FALSE, TRUE, BODYPART_ROBOTIC, CANT_WOUND)) // returns false for non-robotic limbs
if(severity > EMP_LIGHT)
ADD_TRAIT(src, TRAIT_PARALYSIS, "EMP")
addtimer(CALLBACK(src, PROC_REF(after_emp)), min((severity / 2) SECONDS, 5 SECONDS), TIMER_UNIQUE | TIMER_OVERRIDE)
if(owner && emp_message)
owner.emote("scream")
to_chat(src, span_userdanger("You feel a sharp pain as your robotic limbs overload."))
if(!(. & EMP_PROTECT_CONTENTS))
for(var/obj/item/organ/O as anything in get_organs())
O.emp_act(severity)
/obj/item/bodypart/proc/after_emp()
REMOVE_TRAIT(src, TRAIT_PARALYSIS, "EMP")
/obj/item/bodypart/Destroy()
if(owner)
owner.bodyparts -= src

View File

@@ -83,4 +83,5 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
damage += 100/severity
if(severity > EMP_LIGHT)
damage += 20 * (severity - EMP_HEAVY)

View File

@@ -23,7 +23,7 @@
if(!L) //how did you get an implant in a limb you don't have?
return
L.receive_damage(5,0,10) //always take a least a little bit of damage to the leg
L.receive_damage(severity / 2, 0, severity) //always take a least a little bit of damage to the leg
if(prob(50)) //you're forced to use two of these for them to work so let's give em a chance to not get completely fucked
if(COOLDOWN_FINISHED(src, emp_notice))
@@ -32,15 +32,15 @@
return
L.set_disabled(TRUE) //disable the bodypart
addtimer(CALLBACK(src, PROC_REF(reenableleg)), 5 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
addtimer(CALLBACK(src, PROC_REF(reenableleg)), (severity / 2) SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
if(severity & EMP_HEAVY && prob(5) && !syndicate_implant) //put probabilities into a calculator before you try fucking with this
to_chat(owner, span_warning("The EMP causes your [src] to thrash your [L] around wildly, breaking it!"))
if(severity > EMP_LIGHT && prob(5) && !syndicate_implant) //put probabilities into a calculator before you try fucking with this
to_chat(owner, span_warning("[src] malfunctions and thrashes your [L] around wildly, breaking it!"))
var/datum/wound/blunt/severe/breakdown = new
breakdown.apply_wound(L)
L.receive_damage(20)
else if(COOLDOWN_FINISHED(src, emp_notice))
to_chat(owner, span_warning("The EMP causes your [src] to seize up, preventing your [L] from moving!"))
to_chat(owner, span_warning("[src] malfunctions and causes your muscles to seize up, preventing your [L] from moving!"))
COOLDOWN_START(src, emp_notice, 30 SECONDS)
/obj/item/organ/cyberimp/leg/proc/reenableleg()
@@ -84,14 +84,6 @@
to_chat(user, span_notice("You modify [src] to be installed on the [zone == BODY_ZONE_R_LEG ? "right" : "left"] leg."))
update_appearance(UPDATE_ICON)
/obj/item/organ/cyberimp/leg/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(prob(15/severity) && owner)
to_chat(owner, span_warning("[src] is hit by EMP!"))
// give the owner an idea about why his implant is glitching
/obj/item/organ/cyberimp/leg/Insert(mob/living/carbon/M, special, drop_if_replaced, special_zone)
. = ..()
if(HasBoth())

View File

@@ -67,7 +67,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(prob(15/severity) && owner)
if(prob(1.5 * severity) && owner)
to_chat(owner, span_warning("[src] is hit by EMP!"))
// give the owner an idea about why his implant is glitching
Retract()
@@ -162,7 +162,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(prob(30/severity) && owner && (organ_flags & ORGAN_FAILING))
if(prob(3 * severity) && owner && (organ_flags & ORGAN_FAILING))
Retract()
owner.visible_message(span_danger("A loud bang comes from [owner]\'s [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm!"))
playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1)

View File

@@ -32,7 +32,8 @@
. = ..()
if(!owner || . & EMP_PROTECT_SELF)
return
owner.reagents.add_reagent(/datum/reagent/toxin/bad_food, poison_amount / severity)
var/existing = owner.reagents.get_reagent_amount(/datum/reagent/toxin/bad_food)
owner.reagents.add_reagent(/datum/reagent/toxin/bad_food, (poison_amount * (severity / EMP_HEAVY)) - existing)
to_chat(owner, span_warning("You feel like your insides are burning."))
@@ -102,10 +103,10 @@
if(ishuman(owner) && !syndicate_implant)
var/mob/living/carbon/human/H = owner
if(H.stat != DEAD && prob(50 / severity) && H.can_heartattack())
if(H.stat != DEAD && prob(5 * severity) && H.can_heartattack())
H.set_heartattack(TRUE)
to_chat(H, span_userdanger("You feel a horrible agony in your chest!"))
addtimer(CALLBACK(src, PROC_REF(undo_heart_attack)), 10 SECONDS / severity)
addtimer(CALLBACK(src, PROC_REF(undo_heart_attack)), severity SECONDS)
/obj/item/organ/cyberimp/chest/reviver/proc/undo_heart_attack()
var/mob/living/carbon/human/H = owner
@@ -212,13 +213,8 @@
/obj/item/organ/cyberimp/chest/thrusters/emp_act(severity)
. = ..()
switch(severity)
if(EMP_HEAVY)
owner.adjustFireLoss(35)
to_chat(owner, span_warning("Your thruster implant malfunctions and severely burns you!"))
if(EMP_LIGHT)
owner.adjustFireLoss(10)
to_chat(owner, span_danger("Your thruster implant malfunctions and mildly burns you!"))
owner.adjustFireLoss(3 * severity)
to_chat(owner, span_warning("Your thruster implant malfunctions and severely burns you!"))
/obj/item/organ/cyberimp/chest/spinalspeed
name = "neural overclocker implant"
@@ -335,27 +331,17 @@
/obj/item/organ/cyberimp/chest/spinalspeed/emp_act(severity)
. = ..()
if(!syndicate_implant)//the toy has a different emp act
owner.adjust_dizzy(10 SECONDS / severity)
owner.adjust_dizzy(severity SECONDS)
to_chat(owner, span_warning("Your spinal implant makes you feel queasy!"))
return
switch(severity)//i don't want emps to just be damage again, that's boring
if(EMP_HEAVY)
owner.set_drugginess(40)
owner.adjust_hallucinations(500 SECONDS)
owner.blur_eyes(20)
owner.adjust_dizzy(10 SECONDS)
time_on += 10
owner.adjustFireLoss(10)
to_chat(owner, span_warning("Your spinal implant malfunctions and you feel it scramble your brain!"))
if(EMP_LIGHT)
owner.set_drugginess(20)
owner.adjust_hallucinations(200 SECONDS)
owner.blur_eyes(10)
owner.adjust_dizzy(5 SECONDS)
time_on += 5
owner.adjustFireLoss(5)
to_chat(owner, span_danger("Your spinal implant malfunctions and you suddenly feel... wrong."))
owner.set_drugginess(4 * severity)
owner.adjust_hallucinations((50 * severity) SECONDS)
owner.blur_eyes(2 * severity)
owner.adjust_dizzy(severity SECONDS)
time_on += severity
owner.adjustFireLoss(severity)
to_chat(owner, span_warning("Your spinal implant malfunctions and you feel it scramble your brain!"))
/obj/item/organ/cyberimp/chest/spinalspeed/toy
name = "glowy after-image trail implant"

View File

@@ -36,7 +36,7 @@
. = ..()
if(!owner || . & EMP_PROTECT_SELF)
return
owner.Stun(stun_amount / severity)
owner.Stun(stun_amount * (severity / EMP_HEAVY))
to_chat(owner, span_warning("Your body seizes up!"))
@@ -74,13 +74,12 @@
. = ..()
if(!owner || . & EMP_PROTECT_SELF)
return
var/range = severity ? 10 : 5
var/atom/A
if(active)
release_items()
for(var/obj/item/I in stored_items)
A = pick(oview(range))
I.throw_at(A, range, 2)
A = pick(oview(severity))
I.throw_at(A, severity, 2)
to_chat(owner, span_warning("Your [owner.get_held_index_name(owner.get_held_index_of_item(I))] spasms and throws the [I.name]!"))
stored_items = list()
@@ -138,7 +137,7 @@
if((organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF)
return
organ_flags |= ORGAN_FAILING
addtimer(CALLBACK(src, PROC_REF(reboot)), stun_cap_amount * 2 / severity)
addtimer(CALLBACK(src, PROC_REF(reboot)), stun_cap_amount * (severity / 5))
/obj/item/organ/cyberimp/brain/anti_stun/proc/reboot()
clear_stuns()
@@ -183,7 +182,7 @@
. = ..()
if(!owner || . & EMP_PROTECT_SELF)
return
if(prob(60/severity))
if(prob(6 * severity))
to_chat(owner, span_warning("Your breathing tube suddenly closes!"))
owner.losebreath += 2

View File

@@ -157,15 +157,11 @@
compatible_biotypes = MOB_ROBOTIC // for IPCs
/obj/item/organ/ears/robot/emp_act(severity)
switch(severity)
if(1)
owner.adjust_jitter(30 SECONDS)
owner.adjust_dizzy(30)
owner.Knockdown(5 SECONDS)
deaf = 30
to_chat(owner, span_warning("Your robotic ears are uselessly ringing."))
if(2)
owner.adjust_jitter(15 SECONDS)
owner.adjust_dizzy(15)
owner.Knockdown(10 SECONDS)
to_chat(owner, span_warning("Your robotic ears buzz."))
owner.adjust_jitter(3 * severity)
owner.adjust_dizzy(3 * severity)
owner.Knockdown(severity SECONDS)
if(severity > EMP_LIGHT)
deaf = 3 * severity
to_chat(owner, span_warning("Your robotic ears are uselessly ringing."))
return
to_chat(owner, span_warning("Your robotic ears buzz."))

View File

@@ -171,12 +171,11 @@
. = ..()
if(!owner || . & EMP_PROTECT_SELF)
return
var/obj/item/organ/eyes/eyes = owner.getorganslot(ORGAN_SLOT_EYES)
to_chat(owner, span_danger("your eyes overload and blind you!"))
owner.flash_act(override_blindness_check = 1)
owner.blind_eyes(5)
owner.blind_eyes(severity / 2)
owner.blur_eyes(8)
eyes.applyOrganDamage(20 / severity)
applyOrganDamage(2 * severity)
/obj/item/organ/eyes/robotic/xray
name = "\improper meson eyes"

View File

@@ -239,8 +239,9 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
Stop()
addtimer(CALLBACK(src, PROC_REF(Restart)), restartTimer/severity) //Can restart itself after an EMP so it isnt an insta death
if(severity > EMP_LIGHT)
Stop()
addtimer(CALLBACK(src, PROC_REF(Restart)), restartTimer * min(severity / EMP_HEAVY, 1)) //Can restart itself after an EMP so it isnt an insta death
/obj/item/organ/heart/cybernetic/upgraded
name = "upgraded cybernetic heart"
@@ -266,12 +267,12 @@
/obj/item/organ/heart/cybernetic/ipc
desc = "An electronic device that appears to mimic the functions of an organic heart."
/obj/item/organ/heart/cybernetic/ipc/emp_act()
/obj/item/organ/heart/cybernetic/ipc/emp_act(severity)
if(prob(30))
return
. = ..()
to_chat(owner, "<span class='warning'>Alert: Cybernetic heart failed one heartbeat</span>")
addtimer(CALLBACK(src, PROC_REF(Restart)), 10 SECONDS)
addtimer(CALLBACK(src, PROC_REF(Restart)), severity SECONDS)
/obj/item/organ/heart/freedom
name = "heart of freedom"

View File

@@ -117,8 +117,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
damage += 50/severity
applyOrganDamage(5 * severity)
/obj/item/organ/liver/cybernetic/upgraded/ipc
name = "substance processor"
@@ -135,4 +134,4 @@
if(prob(10))
return
to_chat(owner, "<span class='warning'>Alert: Your Substance Processor has been damaged. An internal chemical leak is affecting performance.</span>")
owner.adjustToxLoss(10/severity)
owner.adjustToxLoss(severity)

View File

@@ -581,11 +581,11 @@
safe_breath_min = 13
safe_breath_max = 100
/obj/item/organ/lungs/cybernetic/emp_act()
/obj/item/organ/lungs/cybernetic/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
owner.losebreath = 20
owner.losebreath = 2 * severity
/obj/item/organ/lungs/cybernetic/upgraded
name = "upgraded cybernetic lungs"

View File

@@ -145,7 +145,7 @@
/obj/item/organ/stomach/cell/emp_act(severity)
to_chat(owner, emp_message)
charge(amount = owner.nutrition * -0.2 / severity)
charge(amount = owner.nutrition * -0.02 * severity)
/obj/item/organ/stomach/cell/Insert(mob/living/carbon/M, special, drop_if_replaced)
. = ..()

View File

@@ -266,9 +266,9 @@
/obj/item/organ/tongue/robot/emp_act(severity)
if(prob(5))
return
owner.apply_effect(EFFECT_STUTTER, rand(5 SECONDS, 2 MINUTES))
owner.apply_effect(EFFECT_STUTTER, rand(1, severity) * 6 SECONDS)
owner.emote("scream")
to_chat(owner, "<span class='warning'>Alert: Vocal cords are malfunctioning.</span>")
to_chat(owner, "<span class='warning'>Alert: Voice synthesizer is malfunctioning.</span>")
/obj/item/organ/tongue/robot/can_speak_language(language)
return TRUE // THE MAGIC OF ELECTRONICS

View File

@@ -96,12 +96,13 @@
. = ..()
. += "Resources: [resources]"
/mob/living/simple_animal/hostile/swarmer/emp_act()
/mob/living/simple_animal/hostile/swarmer/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(health > 1)
adjustHealth(health-1)
var/emp_damage = severity/EMP_HEAVY
if(health > emp_damage)
adjustHealth(health - emp_damage)
else
death()

View File

@@ -45,7 +45,7 @@
return ..()
/obj/machinery/dominator/emp_act(severity)
gang.domination_time += 30
gang.domination_time += 3 * severity
..()
/obj/machinery/dominator/hulk_damage()

Some files were not shown because too many files have changed in this diff Show More