mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 22:19:30 +01:00
Modernizing Radiation -- TL;DR: Radiation is now a status effect healed by tox healing, and contamination is removed (#62265)
Implements the Modernizing radiation design document ( https://hackmd.io/@tgstation/rJNIyeBHt ) and replaces the current radiation sources with the new system, as well as replacing/removing a bunch of old consumers of radiation that either had no reason to exist, or could be replaced by something else. Diverges from the doc in that items radiation don't go up like explained. I was going to, but items get irradiated so easily that it just feels pretty lame. Items still get irradiated, but it's mostly just so that radiation sources look cooler (wow, lots of stuff around going green), and for things like the geiger counter. Instead of the complicated radiation_wave system, radiation now just checks everything between the radiation source and the potential target, losing power along the way based on the radiation insulation of whats in between. If this reaches too low a point (specified by radiation_pulse consumers), then the radiation will not pass. Otherwise, will roll a chance to irradiate. Uranium structures allow a delay before irradiating, so stay away!
This commit is contained in:
@@ -7,7 +7,6 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
#define PDA_SCANNER_MEDICAL 1
|
||||
#define PDA_SCANNER_FORENSICS 2 //unused
|
||||
#define PDA_SCANNER_REAGENT 3
|
||||
#define PDA_SCANNER_HALOGEN 4
|
||||
#define PDA_SCANNER_GAS 5
|
||||
#define PDA_SPAM_DELAY 2 MINUTES
|
||||
|
||||
@@ -26,7 +25,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
|
||||
actions_types = list(/datum/action/item_action/toggle_light)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 100, ACID = 100)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
light_system = MOVABLE_LIGHT_DIRECTIONAL
|
||||
light_range = 2.3
|
||||
@@ -321,8 +320,6 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=53'>[PDAIMG(notes)]Newscaster Access </a></li>"
|
||||
if (cartridge.access & CART_REAGENT_SCANNER)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Reagent Scan'>[PDAIMG(reagent)][scanmode == 3 ? "Disable" : "Enable"] Reagent Scanner</a></li>"
|
||||
if (cartridge.access & CART_ENGINE)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Halogen Counter'>[PDAIMG(reagent)][scanmode == 4 ? "Disable" : "Enable"] Halogen Counter</a></li>"
|
||||
if (cartridge.access & CART_ATMOS)
|
||||
dat += "<li><a href='byond://?src=[REF(src)];choice=Gas Scan'>[PDAIMG(reagent)][scanmode == 5 ? "Disable" : "Enable"] Gas Scanner</a></li>"
|
||||
if (cartridge.access & CART_REMOTE_DOOR)
|
||||
@@ -566,13 +563,6 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
scanmode = PDA_SCANNER_NONE
|
||||
else if((!isnull(cartridge)) && (cartridge.access & CART_REAGENT_SCANNER))
|
||||
scanmode = PDA_SCANNER_REAGENT
|
||||
if("Halogen Counter")
|
||||
if(scanmode == PDA_SCANNER_HALOGEN)
|
||||
scanmode = PDA_SCANNER_NONE
|
||||
else if((!isnull(cartridge)) && (cartridge.access & CART_ENGINE))
|
||||
scanmode = PDA_SCANNER_HALOGEN
|
||||
if(!silent)
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 15, TRUE)
|
||||
if("Honk")
|
||||
if ( !(last_noise && world.time < last_noise + 20) )
|
||||
playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE)
|
||||
@@ -1103,15 +1093,6 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
healthscan(user, C, 1)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(PDA_SCANNER_HALOGEN)
|
||||
C.visible_message(span_notice("[user] analyzes [C]'s radiation levels."))
|
||||
|
||||
user.show_message(span_notice("Analyzing Results for [C]:"))
|
||||
if(C.radiation)
|
||||
user.show_message("\green Radiation Level: \black [C.radiation]")
|
||||
else
|
||||
user.show_message(span_notice("No radiation detected."))
|
||||
|
||||
/obj/item/pda/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
@@ -1288,6 +1269,5 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
#undef PDA_SCANNER_MEDICAL
|
||||
#undef PDA_SCANNER_FORENSICS
|
||||
#undef PDA_SCANNER_REAGENT
|
||||
#undef PDA_SCANNER_HALOGEN
|
||||
#undef PDA_SCANNER_GAS
|
||||
#undef PDA_SPAM_DELAY
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
can_atmos_pass = ATMOS_PASS_DENSITY
|
||||
armor = list(MELEE = 0, BULLET = 25, LASER = 50, ENERGY = 50, BOMB = 25, BIO = 100, RAD = 100, FIRE = 100, ACID = 100)
|
||||
armor = list(MELEE = 0, BULLET = 25, LASER = 50, ENERGY = 50, BOMB = 25, BIO = 100, FIRE = 100, ACID = 100)
|
||||
var/obj/item/forcefield_projector/generator
|
||||
|
||||
/obj/structure/projected_forcefield/Initialize(mapload, obj/item/forcefield_projector/origin)
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
#define RAD_LEVEL_NORMAL 9
|
||||
#define RAD_LEVEL_MODERATE 100
|
||||
#define RAD_LEVEL_HIGH 400
|
||||
#define RAD_LEVEL_VERY_HIGH 800
|
||||
#define RAD_LEVEL_CRITICAL 1500
|
||||
|
||||
/obj/item/geiger_counter //DISCLAIMER: I know nothing about how real-life Geiger counters work. This will not be realistic. ~Xhuis
|
||||
name = "\improper Geiger counter"
|
||||
desc = "A handheld device used for detecting and measuring radiation pulses."
|
||||
@@ -18,158 +12,102 @@
|
||||
item_flags = NOBLUDGEON
|
||||
custom_materials = list(/datum/material/iron = 150, /datum/material/glass = 150)
|
||||
|
||||
var/grace = RAD_GEIGER_GRACE_PERIOD
|
||||
var/datum/looping_sound/geiger/soundloop
|
||||
var/last_perceived_radiation_danger = null
|
||||
|
||||
var/scanning = FALSE
|
||||
var/radiation_count = 0
|
||||
var/current_tick_amount = 0
|
||||
var/last_tick_amount = 0
|
||||
var/fail_to_receive = 0
|
||||
var/current_warning = 1
|
||||
|
||||
/obj/item/geiger_counter/Initialize(mapload)
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
soundloop = new(src, FALSE)
|
||||
|
||||
/obj/item/geiger_counter/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_NULL(soundloop)
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/geiger_counter/process(delta_time)
|
||||
if(scanning)
|
||||
radiation_count = LPFILTER(radiation_count, current_tick_amount, delta_time, RAD_GEIGER_RC)
|
||||
|
||||
if(current_tick_amount)
|
||||
grace = RAD_GEIGER_GRACE_PERIOD
|
||||
last_tick_amount = current_tick_amount
|
||||
|
||||
else if(!(obj_flags & EMAGGED))
|
||||
grace -= delta_time
|
||||
if(grace <= 0)
|
||||
radiation_count = 0
|
||||
|
||||
current_tick_amount = 0
|
||||
|
||||
update_appearance()
|
||||
update_sound()
|
||||
RegisterSignal(src, COMSIG_IN_RANGE_OF_IRRADIATION, .proc/on_pre_potential_irradiation)
|
||||
|
||||
/obj/item/geiger_counter/examine(mob/user)
|
||||
. = ..()
|
||||
if(!scanning)
|
||||
return
|
||||
. += span_info("Alt-click it to clear stored radiation levels.")
|
||||
if(obj_flags & EMAGGED)
|
||||
. += span_warning("The display seems to be incomprehensible.")
|
||||
return
|
||||
switch(radiation_count)
|
||||
if(-INFINITY to RAD_LEVEL_NORMAL)
|
||||
switch(last_perceived_radiation_danger)
|
||||
if(null)
|
||||
. += span_notice("Ambient radiation level count reports that all is well.")
|
||||
if(RAD_LEVEL_NORMAL + 1 to RAD_LEVEL_MODERATE)
|
||||
if(PERCEIVED_RADIATION_DANGER_LOW)
|
||||
. += span_alert("Ambient radiation levels slightly above average.")
|
||||
if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH)
|
||||
if(PERCEIVED_RADIATION_DANGER_MEDIUM)
|
||||
. += span_warning("Ambient radiation levels above average.")
|
||||
if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH)
|
||||
if(PERCEIVED_RADIATION_DANGER_HIGH)
|
||||
. += span_danger("Ambient radiation levels highly above average.")
|
||||
if(RAD_LEVEL_VERY_HIGH + 1 to RAD_LEVEL_CRITICAL)
|
||||
. += span_suicide("Ambient radiation levels nearing critical level.")
|
||||
if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
|
||||
. += span_boldannounce("Ambient radiation levels above critical level!")
|
||||
|
||||
. += span_notice("The last radiation amount detected was [last_tick_amount]")
|
||||
if(PERCEIVED_RADIATION_DANGER_EXTREME)
|
||||
. += span_suicide("Ambient radiation levels reaching critical level!")
|
||||
|
||||
/obj/item/geiger_counter/update_icon_state()
|
||||
if(!scanning)
|
||||
icon_state = "geiger_off"
|
||||
return ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
icon_state = "geiger_on_emag"
|
||||
return ..()
|
||||
|
||||
switch(radiation_count)
|
||||
if(-INFINITY to RAD_LEVEL_NORMAL)
|
||||
switch(last_perceived_radiation_danger)
|
||||
if(null)
|
||||
icon_state = "geiger_on_1"
|
||||
if(RAD_LEVEL_NORMAL + 1 to RAD_LEVEL_MODERATE)
|
||||
if(PERCEIVED_RADIATION_DANGER_LOW)
|
||||
icon_state = "geiger_on_2"
|
||||
if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH)
|
||||
if(PERCEIVED_RADIATION_DANGER_MEDIUM)
|
||||
icon_state = "geiger_on_3"
|
||||
if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH)
|
||||
if(PERCEIVED_RADIATION_DANGER_HIGH)
|
||||
icon_state = "geiger_on_4"
|
||||
if(RAD_LEVEL_VERY_HIGH + 1 to RAD_LEVEL_CRITICAL)
|
||||
icon_state = "geiger_on_4"
|
||||
if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
|
||||
if(PERCEIVED_RADIATION_DANGER_EXTREME)
|
||||
icon_state = "geiger_on_5"
|
||||
return ..()
|
||||
|
||||
/obj/item/geiger_counter/proc/update_sound()
|
||||
var/datum/looping_sound/geiger/loop = soundloop
|
||||
if(!scanning)
|
||||
loop.stop()
|
||||
return
|
||||
if(!radiation_count)
|
||||
loop.stop()
|
||||
return
|
||||
loop.last_radiation = radiation_count
|
||||
loop.start()
|
||||
|
||||
/obj/item/geiger_counter/rad_act(amount)
|
||||
. = ..()
|
||||
if(amount <= RAD_BACKGROUND_RADIATION || !scanning)
|
||||
return
|
||||
current_tick_amount += amount
|
||||
update_appearance()
|
||||
|
||||
/obj/item/geiger_counter/attack_self(mob/user)
|
||||
scanning = !scanning
|
||||
update_appearance()
|
||||
|
||||
if (scanning)
|
||||
AddComponent(/datum/component/geiger_sound)
|
||||
else
|
||||
qdel(GetComponent(/datum/component/geiger_sound))
|
||||
|
||||
update_appearance(UPDATE_ICON)
|
||||
to_chat(user, span_notice("[icon2html(src, user)] You switch [scanning ? "on" : "off"] [src]."))
|
||||
|
||||
/obj/item/geiger_counter/afterattack(atom/target, mob/living/user, params)
|
||||
. = ..()
|
||||
if(!user.combat_mode)
|
||||
if(!(obj_flags & EMAGGED))
|
||||
user.visible_message(span_notice("[user] scans [target] with [src]."), span_notice("You scan [target]'s radiation levels with [src]..."))
|
||||
addtimer(CALLBACK(src, .proc/scan, target, user), 20, TIMER_UNIQUE) // Let's not have spamming GetAllContents
|
||||
else
|
||||
user.visible_message(span_notice("[user] scans [target] with [src]."), span_danger("You project [src]'s stored radiation into [target]!"))
|
||||
target.rad_act(radiation_count)
|
||||
radiation_count = 0
|
||||
return TRUE
|
||||
|
||||
/obj/item/geiger_counter/proc/scan(atom/A, mob/user)
|
||||
var/rad_strength = get_rad_contamination(A)
|
||||
if (user.combat_mode)
|
||||
return
|
||||
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
if(!M.radiation)
|
||||
to_chat(user, span_notice("[icon2html(src, user)] Radiation levels within normal boundaries."))
|
||||
else
|
||||
to_chat(user, span_boldannounce("[icon2html(src, user)] Subject is irradiated. Radiation levels: [M.radiation]."))
|
||||
if (!CAN_IRRADIATE(target))
|
||||
return
|
||||
|
||||
if(rad_strength)
|
||||
to_chat(user, span_boldannounce("[icon2html(src, user)] Target contains radioactive contamination. Radioactive strength: [rad_strength]"))
|
||||
else
|
||||
to_chat(user, span_notice("[icon2html(src, user)] Target is free of radioactive contamination."))
|
||||
user.visible_message(span_notice("[user] scans [target] with [src]."), span_notice("You scan [target]'s radiation levels with [src]..."))
|
||||
addtimer(CALLBACK(src, .proc/scan, target, user), 20, TIMER_UNIQUE) // Let's not have spamming GetAllContents
|
||||
|
||||
/obj/item/geiger_counter/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER && (obj_flags & EMAGGED))
|
||||
if(scanning)
|
||||
to_chat(user, span_warning("Turn off [src] before you perform this action!"))
|
||||
return FALSE
|
||||
user.visible_message(span_notice("[user] unscrews [src]'s maintenance panel and begins fiddling with its innards..."), span_notice("You begin resetting [src]..."))
|
||||
if(!I.use_tool(src, user, 40, volume=50))
|
||||
return FALSE
|
||||
user.visible_message(span_notice("[user] refastens [src]'s maintenance panel!"), span_notice("You reset [src] to its factory settings!"))
|
||||
obj_flags &= ~EMAGGED
|
||||
radiation_count = 0
|
||||
update_appearance()
|
||||
return TRUE
|
||||
else
|
||||
return ..()
|
||||
/obj/item/geiger_counter/equipped(mob/user, slot, initial)
|
||||
. = ..()
|
||||
|
||||
RegisterSignal(user, COMSIG_IN_RANGE_OF_IRRADIATION, .proc/on_pre_potential_irradiation)
|
||||
|
||||
/obj/item/geiger_counter/dropped(mob/user, silent = FALSE)
|
||||
. = ..()
|
||||
|
||||
UnregisterSignal(user, COMSIG_IN_RANGE_OF_IRRADIATION, .proc/on_pre_potential_irradiation)
|
||||
|
||||
/obj/item/geiger_counter/proc/on_pre_potential_irradiation(datum/source, datum/radiation_pulse_information/pulse_information, insulation_to_target)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
last_perceived_radiation_danger = get_perceived_radiation_danger(pulse_information, insulation_to_target)
|
||||
addtimer(CALLBACK(src, .proc/reset_perceived_danger), TIME_WITHOUT_RADIATION_BEFORE_RESET, TIMER_UNIQUE | TIMER_OVERRIDE)
|
||||
|
||||
if (scanning)
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
/obj/item/geiger_counter/proc/reset_perceived_danger()
|
||||
last_perceived_radiation_danger = null
|
||||
if (scanning)
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
/obj/item/geiger_counter/proc/scan(atom/target, mob/user)
|
||||
if (SEND_SIGNAL(target, COMSIG_GEIGER_COUNTER_SCAN, user, src) & COMSIG_GEIGER_COUNTER_SCAN_SUCCESSFUL)
|
||||
return
|
||||
|
||||
to_chat(user, span_notice("[icon2html(src, user)] [isliving(target) ? "Subject" : "Target"] is free of radioactive contamination."))
|
||||
|
||||
/obj/item/geiger_counter/AltClick(mob/living/user)
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
@@ -177,50 +115,6 @@
|
||||
if(!scanning)
|
||||
to_chat(usr, span_warning("[src] must be on to reset its radiation level!"))
|
||||
return
|
||||
radiation_count = 0
|
||||
to_chat(usr, span_notice("You flush [src]'s radiation counts, resetting it to normal."))
|
||||
update_appearance()
|
||||
|
||||
/obj/item/geiger_counter/emag_act(mob/user)
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
if(scanning)
|
||||
to_chat(user, span_warning("Turn off [src] before you perform this action!"))
|
||||
return
|
||||
to_chat(user, span_warning("You override [src]'s radiation storing protocols. It will now generate small doses of radiation, and stored rads are now projected into creatures you scan."))
|
||||
obj_flags |= EMAGGED
|
||||
|
||||
|
||||
|
||||
/obj/item/geiger_counter/cyborg
|
||||
var/mob/listeningTo
|
||||
|
||||
/obj/item/geiger_counter/cyborg/cyborg_unequip(mob/user)
|
||||
if(!scanning)
|
||||
return
|
||||
scanning = FALSE
|
||||
update_appearance()
|
||||
|
||||
/obj/item/geiger_counter/cyborg/equipped(mob/user)
|
||||
. = ..()
|
||||
if(listeningTo == user)
|
||||
return
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
|
||||
RegisterSignal(user, COMSIG_ATOM_RAD_ACT, .proc/redirect_rad_act)
|
||||
listeningTo = user
|
||||
|
||||
/obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount)
|
||||
SIGNAL_HANDLER
|
||||
rad_act(amount)
|
||||
|
||||
/obj/item/geiger_counter/cyborg/dropped()
|
||||
. = ..()
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
|
||||
|
||||
#undef RAD_LEVEL_NORMAL
|
||||
#undef RAD_LEVEL_MODERATE
|
||||
#undef RAD_LEVEL_HIGH
|
||||
#undef RAD_LEVEL_VERY_HIGH
|
||||
#undef RAD_LEVEL_CRITICAL
|
||||
last_perceived_radiation_danger = null
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
@@ -174,6 +174,8 @@ GENE SCANNER
|
||||
|
||||
render_list += "[span_info("Analyzing results for [M]:")]\n<span class='info ml-1'>Overall status: [mob_status]</span>\n"
|
||||
|
||||
SEND_SIGNAL(M, COMSIG_LIVING_HEALTHSCAN, render_list, advanced, user, mode)
|
||||
|
||||
// Husk detection
|
||||
if(advanced && HAS_TRAIT_FROM(M, TRAIT_HUSK, BURN))
|
||||
render_list += "<span class='alert ml-1'>Subject has been husked by severe burns.</span>\n"
|
||||
@@ -238,10 +240,8 @@ GENE SCANNER
|
||||
if(advanced)
|
||||
render_list += "<span class='info ml-1'>Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.</span>\n"
|
||||
|
||||
if (M.radiation)
|
||||
render_list += "<span class='alert ml-1'>Subject is irradiated.</span>\n"
|
||||
if(advanced)
|
||||
render_list += "<span class='info ml-1'>Radiation Level: [M.radiation]%.</span>\n"
|
||||
if (HAS_TRAIT(M, TRAIT_IRRADIATED))
|
||||
render_list += "<span class='alert ml-1'>Subject is irradiated. Supply toxin healing.</span>\n"
|
||||
|
||||
if(advanced && M.hallucinating())
|
||||
render_list += "<span class='info ml-1'>Subject is hallucinating.</span>\n"
|
||||
|
||||
@@ -97,7 +97,6 @@ effective or pretty fucking useless.
|
||||
return
|
||||
if(passed_intensity >= 5)
|
||||
M.apply_effect(round(passed_intensity/0.075), EFFECT_UNCONSCIOUS) //to save you some math, this is a round(intensity * (4/3)) second long knockout
|
||||
M.rad_act(passed_intensity*10)
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/proc/get_cooldown()
|
||||
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
|
||||
|
||||
Reference in New Issue
Block a user