mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
Makes the explosive compressor and blastcannon actually use the TTVs they're given + the explosion changes to support that. (#58015)
* Adds explosion SFX to the blastcannon and explosive compressor - Extracts the explosion SFX and screenshake proc from the SSexplosions explosion handling proc and lets the explosive compressor and blastcannon use it. * Miscellaneous changes - Adds defines for the internal explosion arglist keys - Reverses the values of the explosion severity defines - Changes almost everything that uses `/proc/explosion` to use named arguments - Removes a whole bunch of argname = 0 in explosion calls. * Removes named callback arguments. * Changes the explosion signals to just use the arguments list Adds a simple framework to let objects respond to explosions occurring inside of them. Changes a whole bunch of explosions to use the object being exploded as the origin of the explosion rather than the turf the object is on. Makes the explosive compressor and blastcannon actually use the TTVs they are given. Adds support for things responding to internal explosions. Less snowflake code for the explosive compressor and blastcannon calculating bomb range.* Less confusing explosion severity defines. Less opaque explosion arguments *does not guarantee that the solution to letting them actually use the TTV is any less snowflake.
This commit is contained in:
@@ -153,12 +153,12 @@ SUBSYSTEM_DEF(explosions)
|
||||
A.color = null
|
||||
A.maptext = ""
|
||||
|
||||
/proc/dyn_explosion(turf/epicenter, power, flash_range, adminlog = TRUE, ignorecap = TRUE, flame_range = 0, silent = FALSE, smoke = TRUE)
|
||||
/proc/dyn_explosion(turf/epicenter, power, flame_range = 0, flash_range = null, adminlog = TRUE, ignorecap = TRUE, silent = FALSE, smoke = TRUE)
|
||||
if(!power)
|
||||
return
|
||||
var/range = 0
|
||||
range = round((2 * power)**GLOB.DYN_EX_SCALE)
|
||||
explosion(epicenter, round(range * 0.25), round(range * 0.5), round(range), flash_range*range, adminlog, ignorecap, flame_range*range, silent, smoke)
|
||||
explosion(epicenter, devastation_range = round(range * 0.25), heavy_impact_range = round(range * 0.5), light_impact_range = round(range), flame_range = flame_range*range, flash_range = flash_range*range, adminlog = adminlog, ignorecap = ignorecap, silent = silent, smoke = smoke)
|
||||
|
||||
// Using default dyn_ex scale:
|
||||
// 100 explosion power is a (5, 10, 20) explosion.
|
||||
@@ -169,20 +169,86 @@ SUBSYSTEM_DEF(explosions)
|
||||
// 5 explosion power is a (0, 1, 3) explosion.
|
||||
// 1 explosion power is a (0, 0, 1) explosion.
|
||||
|
||||
/proc/explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0, silent = FALSE, smoke = FALSE)
|
||||
/**
|
||||
* Makes a given atom explode.
|
||||
*
|
||||
* Arguments:
|
||||
* - [origin][/atom]: The atom that's exploding.
|
||||
* - devastation_range: The range at which the effects of the explosion are at their strongest.
|
||||
* - heavy_impact_range: The range at which the effects of the explosion are relatively severe.
|
||||
* - light_impact_range: The range at which the effects of the explosion are relatively weak.
|
||||
* - flash_range: The range at which the explosion flashes people.
|
||||
* - adminlog: Whether to log the explosion/report it to the administration.
|
||||
* - ignorecap: Whether to ignore the relevant bombcap. Defaults to FALSE.
|
||||
* - flame_range: The range at which the explosion should produce hotspots.
|
||||
* - silent: Whether to generate/execute sound effects.
|
||||
* - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it.
|
||||
*/
|
||||
/proc/explosion(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = 0, flash_range = 0, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE)
|
||||
. = SSexplosions.explode(arglist(args))
|
||||
|
||||
#define CREAK_DELAY 5 SECONDS //Time taken for the creak to play after explosion, if applicable.
|
||||
#define DEVASTATION_PROB 30 //The probability modifier for devistation, maths!
|
||||
#define HEAVY_IMPACT_PROB 5 //ditto
|
||||
#define FAR_UPPER 60 //Upper limit for the far_volume, distance, clamped.
|
||||
#define FAR_LOWER 40 //lower limit for the far_volume, distance, clamped.
|
||||
#define PROB_SOUND 75 //The probability modifier for a sound to be an echo, or a far sound. (0-100)
|
||||
#define SHAKE_CLAMP 2.5 //The limit for how much the camera can shake for out of view booms.
|
||||
#define FREQ_UPPER 40 //The upper limit for the randomly selected frequency.
|
||||
#define FREQ_LOWER 25 //The lower of the above.
|
||||
|
||||
/datum/controller/subsystem/explosions/proc/explode(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
|
||||
/**
|
||||
* Makes a given atom explode. Now on the explosions subsystem!
|
||||
*
|
||||
* Arguments:
|
||||
* - [origin][/atom]: The atom that's exploding.
|
||||
* - devastation_range: The range at which the effects of the explosion are at their strongest.
|
||||
* - heavy_impact_range: The range at which the effects of the explosion are relatively severe.
|
||||
* - light_impact_range: The range at which the effects of the explosion are relatively weak.
|
||||
* - flash_range: The range at which the explosion flashes people.
|
||||
* - adminlog: Whether to log the explosion/report it to the administration.
|
||||
* - ignorecap: Whether to ignore the relevant bombcap. Defaults to FALSE.
|
||||
* - flame_range: The range at which the explosion should produce hotspots.
|
||||
* - silent: Whether to generate/execute sound effects.
|
||||
* - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it.
|
||||
*/
|
||||
/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = 0, flash_range = 0, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE)
|
||||
var/list/arguments = list(EXARG_KEY_ORIGIN = origin, EXARG_KEY_DEV_RANGE = devastation_range, EXARG_KEY_HEAVY_RANGE = heavy_impact_range, EXARG_KEY_LIGHT_RANGE = light_impact_range, EXARG_KEY_FLAME_RANGE = flame_range, EXARG_KEY_FLASH_RANGE = flash_range, EXARG_KEY_ADMIN_LOG = adminlog, EXARG_KEY_IGNORE_CAP = ignorecap, EXARG_KEY_SILENT = silent, EXARG_KEY_SMOKE = smoke)
|
||||
var/atom/location = isturf(origin) ? origin : origin.loc
|
||||
if(SEND_SIGNAL(origin, COMSIG_ATOM_EXPLODE, arguments) & COMSIG_CANCEL_EXPLOSION)
|
||||
return // Signals are incompatible with `arglist(...)` so we can't actually use that for these. Additionally,
|
||||
|
||||
while(location)
|
||||
var/next_loc = location.loc
|
||||
if(SEND_SIGNAL(location, COMSIG_ATOM_INTERNAL_EXPLOSION, arguments) & COMSIG_CANCEL_EXPLOSION)
|
||||
return
|
||||
if(isturf(location))
|
||||
break
|
||||
location = next_loc
|
||||
|
||||
if(!location)
|
||||
return
|
||||
|
||||
var/area/epicenter_area = get_area(location)
|
||||
if(SEND_SIGNAL(epicenter_area, COMSIG_AREA_INTERNAL_EXPLOSION, arguments) & COMSIG_CANCEL_EXPLOSION)
|
||||
return
|
||||
|
||||
arguments -= EXARG_KEY_ORIGIN
|
||||
propagate_blastwave(arglist(list(location) + arguments))
|
||||
|
||||
|
||||
/**
|
||||
* Handles the effects of an explosion originating from a given point.
|
||||
*
|
||||
* Primarily handles popagating the balstwave of the explosion to the relevant turfs.
|
||||
* Also handles the fireball from the explosion.
|
||||
* Also handles the smoke cloud from the explosion.
|
||||
* Also handles sfx and screenshake.
|
||||
*
|
||||
* Arguments:
|
||||
* - [epicenter][/atom]: The location of the explosion rounded to the nearest turf.
|
||||
* - devastation_range: The range at which the effects of the explosion are at their strongest.
|
||||
* - heavy_impact_range: The range at which the effects of the explosion are relatively severe.
|
||||
* - light_impact_range: The range at which the effects of the explosion are relatively weak.
|
||||
* - flash_range: The range at which the explosion flashes people.
|
||||
* - adminlog: Whether to log the explosion/report it to the administration.
|
||||
* - ignorecap: Whether to ignore the relevant bombcap. Defaults to TRUE for some mysterious reason.
|
||||
* - flame_range: The range at which the explosion should produce hotspots.
|
||||
* - silent: Whether to generate/execute sound effects.
|
||||
* - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it.
|
||||
*/
|
||||
/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke)
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter)
|
||||
return
|
||||
@@ -197,7 +263,7 @@ SUBSYSTEM_DEF(explosions)
|
||||
var/orig_heavy_range = heavy_impact_range
|
||||
var/orig_light_range = light_impact_range
|
||||
|
||||
var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range)
|
||||
var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range)
|
||||
|
||||
//Zlevel specific bomb cap multiplier
|
||||
var/cap_multiplier = SSmapping.level_trait(epicenter.z, ZTRAIT_BOMBCAP_MULTIPLIER)
|
||||
@@ -221,7 +287,7 @@ SUBSYSTEM_DEF(explosions)
|
||||
var/y0 = epicenter.y
|
||||
var/z0 = epicenter.z
|
||||
var/area/areatype = get_area(epicenter)
|
||||
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1)))
|
||||
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flame" = flame_range, "flash" = flash_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1)))
|
||||
|
||||
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
||||
// Stereo users will also hear the direction of the explosion!
|
||||
@@ -234,56 +300,7 @@ SUBSYSTEM_DEF(explosions)
|
||||
far_dist += devastation_range * 20
|
||||
|
||||
if(!silent)
|
||||
var/frequency = get_rand_frequency()
|
||||
var/sound/explosion_sound = sound(get_sfx("explosion"))
|
||||
var/sound/far_explosion_sound = sound('sound/effects/explosionfar.ogg')
|
||||
var/sound/creaking_explosion_sound = sound(get_sfx("explosion_creaking"))
|
||||
var/sound/hull_creaking_sound = sound(get_sfx("hull_creaking"))
|
||||
var/sound/explosion_echo_sound = sound('sound/effects/explosion_distant.ogg')
|
||||
var/on_station = SSmapping.level_trait(epicenter.z, ZTRAIT_STATION)
|
||||
var/creaking_explosion = FALSE
|
||||
|
||||
if(prob(devastation_range*DEVASTATION_PROB+heavy_impact_range*HEAVY_IMPACT_PROB) && on_station) // Huge explosions are near guaranteed to make the station creak and whine, smaller ones might.
|
||||
creaking_explosion = TRUE // prob over 100 always returns true
|
||||
|
||||
for(var/MN in GLOB.player_list)
|
||||
var/mob/M = MN
|
||||
// Double check for client
|
||||
var/turf/M_turf = get_turf(M)
|
||||
if(M_turf && M_turf.z == z0)
|
||||
var/dist = get_dist(M_turf, epicenter)
|
||||
var/baseshakeamount
|
||||
if(orig_max_distance - dist > 0)
|
||||
baseshakeamount = sqrt((orig_max_distance - dist)*0.1)
|
||||
// If inside the blast radius + world.view - 2
|
||||
if(dist <= round(max_range + world.view - 2, 1))
|
||||
M.playsound_local(epicenter, null, 100, 1, frequency, S = explosion_sound)
|
||||
if(baseshakeamount > 0)
|
||||
shake_camera(M, 25, clamp(baseshakeamount, 0, 10))
|
||||
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
|
||||
else if(dist <= far_dist)
|
||||
var/far_volume = clamp(far_dist/2, FAR_LOWER, FAR_UPPER) // Volume is based on explosion size and dist
|
||||
if(creaking_explosion)
|
||||
M.playsound_local(epicenter, null, far_volume, 1, frequency, S = creaking_explosion_sound, distance_multiplier = 0)
|
||||
else if(prob(PROB_SOUND)) // Sound variety during meteor storm/tesloose/other bad event
|
||||
M.playsound_local(epicenter, null, far_volume, 1, frequency, S = far_explosion_sound, distance_multiplier = 0) // Far sound
|
||||
else
|
||||
M.playsound_local(epicenter, null, far_volume, 1, frequency, S = explosion_echo_sound, distance_multiplier = 0) // Echo sound
|
||||
|
||||
if(baseshakeamount > 0 || devastation_range)
|
||||
if(!baseshakeamount) // Devastating explosions rock the station and ground
|
||||
baseshakeamount = devastation_range*3
|
||||
shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, SHAKE_CLAMP))
|
||||
else if(!isspaceturf(get_turf(M)) && heavy_impact_range) // Big enough explosions echo throughout the hull
|
||||
var/echo_volume = 40
|
||||
if(devastation_range)
|
||||
baseshakeamount = devastation_range
|
||||
shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, SHAKE_CLAMP))
|
||||
echo_volume = 60
|
||||
M.playsound_local(epicenter, null, echo_volume, 1, frequency, S = explosion_echo_sound, distance_multiplier = 0)
|
||||
|
||||
if(creaking_explosion) // 5 seconds after the bang, the station begins to creak
|
||||
addtimer(CALLBACK(M, /mob/proc/playsound_local, epicenter, null, rand(FREQ_LOWER, FREQ_UPPER), 1, frequency, null, null, FALSE, hull_creaking_sound, 0), CREAK_DELAY)
|
||||
shake_the_room(epicenter, orig_max_distance, far_dist, devastation_range, heavy_impact_range)
|
||||
|
||||
if(heavy_impact_range > 1)
|
||||
var/datum/effect_system/explosion/E
|
||||
@@ -383,13 +400,110 @@ SUBSYSTEM_DEF(explosions)
|
||||
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EXPLOSION, epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||
|
||||
// Explosion SFX defines...
|
||||
/// The probability that a quaking explosion will make the station creak per unit. Maths!
|
||||
#define QUAKE_CREAK_PROB 30
|
||||
/// The probability that an echoing explosion will make the station creak per unit.
|
||||
#define ECHO_CREAK_PROB 5
|
||||
/// Time taken for the hull to begin to creak after an explosion, if applicable.
|
||||
#define CREAK_DELAY (5 SECONDS)
|
||||
/// Lower limit for far explosion SFX volume.
|
||||
#define FAR_LOWER 40
|
||||
/// Upper limit for far explosion SFX volume.
|
||||
#define FAR_UPPER 60
|
||||
/// The probability that a distant explosion SFX will be a far explosion sound rather than an echo. (0-100)
|
||||
#define FAR_SOUND_PROB 75
|
||||
/// The upper limit on screenshake amplitude for nearby explosions.
|
||||
#define NEAR_SHAKE_CAP 10
|
||||
/// The upper limit on screenshake amplifude for distant explosions.
|
||||
#define FAR_SHAKE_CAP 2.5
|
||||
/// The duration of the screenshake for nearby explosions.
|
||||
#define NEAR_SHAKE_DURATION (2.5 SECONDS)
|
||||
/// The duration of the screenshake for distant explosions.
|
||||
#define FAR_SHAKE_DURATION (1 SECONDS)
|
||||
/// The lower limit for the randomly selected hull creaking frequency.
|
||||
#define FREQ_LOWER 25
|
||||
/// The upper limit for the randomly selected hull creaking frequency.
|
||||
#define FREQ_UPPER 40
|
||||
|
||||
/**
|
||||
* Handles the sfx and screenshake caused by an explosion.
|
||||
*
|
||||
* Arguments:
|
||||
* - [epicenter][/turf]: The location of the explosion.
|
||||
* - near_distance: How close to the explosion you need to be to get the full effect of the explosion.
|
||||
* - far_distance: How close to the explosion you need to be to hear more than echos.
|
||||
* - quake_factor: Main scaling factor for screenshake.
|
||||
* - echo_factor: Whether to make the explosion echo off of very distant parts of the station.
|
||||
* - creaking: Whether to make the station creak. Autoset if null.
|
||||
* - [near_sound][/sound]: The sound that plays if you are close to the explosion.
|
||||
* - [far_sound][/sound]: The sound that plays if you are far from the explosion.
|
||||
* - [echo_sound][/sound]: The sound that plays as echos for the explosion.
|
||||
* - [creaking_sound][/sound]: The sound that plays when the station creaks during the explosion.
|
||||
* - [hull_creaking_sound][/sound]: The sound that plays when the station creaks after the explosion.
|
||||
*/
|
||||
/datum/controller/subsystem/explosions/proc/shake_the_room(turf/epicenter, near_distance, far_distance, quake_factor, echo_factor, creaking, sound/near_sound = sound(get_sfx("explosion")), sound/far_sound = sound('sound/effects/explosionfar.ogg'), sound/echo_sound = sound('sound/effects/explosion_distant.ogg'), sound/creaking_sound = sound(get_sfx("explosion_creaking")), hull_creaking_sound = sound(get_sfx("hull_creaking")))
|
||||
var/frequency = get_rand_frequency()
|
||||
var/blast_z = epicenter.z
|
||||
if(isnull(creaking)) // Autoset creaking.
|
||||
var/on_station = SSmapping.level_trait(epicenter.z, ZTRAIT_STATION)
|
||||
if(on_station && prob((quake_factor * QUAKE_CREAK_PROB) + (echo_factor * ECHO_CREAK_PROB))) // Huge explosions are near guaranteed to make the station creak and whine, smaller ones might.
|
||||
creaking = TRUE // prob over 100 always returns true
|
||||
else
|
||||
creaking = FALSE
|
||||
|
||||
for(var/mob/listener as anything in GLOB.player_list)
|
||||
var/turf/listener_turf = get_turf(listener)
|
||||
if(!listener_turf || listener_turf.z != blast_z)
|
||||
continue
|
||||
|
||||
var/distance = get_dist(epicenter, listener_turf)
|
||||
var/base_shake_amount
|
||||
if(near_distance > distance)
|
||||
base_shake_amount = sqrt((near_distance - distance) / 10)
|
||||
|
||||
if(distance <= round(near_distance + world.view - 2, 1)) // If you are close enough to see the effects of the explosion first-hand (ignoring walls)
|
||||
listener.playsound_local(epicenter, null, 100, TRUE, frequency, S = near_sound)
|
||||
if(base_shake_amount > 0)
|
||||
shake_camera(listener, NEAR_SHAKE_DURATION, clamp(base_shake_amount, 0, NEAR_SHAKE_CAP))
|
||||
|
||||
else if(distance < far_distance) // You can hear a far explosion if you are outside the blast radius. Small explosions shouldn't be heard throughout the station.
|
||||
var/far_volume = clamp(far_distance / 2, FAR_LOWER, FAR_UPPER)
|
||||
if(creaking)
|
||||
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, S = creaking_sound, distance_multiplier = 0)
|
||||
else if(prob(FAR_SOUND_PROB)) // Sound variety during meteor storm/tesloose/other bad event
|
||||
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, S = far_sound, distance_multiplier = 0)
|
||||
else
|
||||
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, S = echo_sound, distance_multiplier = 0)
|
||||
|
||||
if(base_shake_amount || quake_factor)
|
||||
if(!base_shake_amount) // Devastating explosions rock the station and ground
|
||||
base_shake_amount = quake_factor * 3
|
||||
shake_camera(listener, FAR_SHAKE_DURATION, clamp(base_shake_amount / 4, 0, FAR_SHAKE_CAP))
|
||||
|
||||
else if(!isspaceturf(listener_turf) && echo_factor) // Big enough explosions echo through the hull.
|
||||
var/echo_volume
|
||||
if(quake_factor)
|
||||
base_shake_amount = quake_factor
|
||||
echo_volume = 60
|
||||
shake_camera(listener, FAR_SHAKE_DURATION, clamp(base_shake_amount / 4, 0, FAR_SHAKE_CAP))
|
||||
else
|
||||
echo_volume = 40
|
||||
listener.playsound_local(epicenter, null, echo_volume, TRUE, frequency, S = echo_sound, distance_multiplier = 0)
|
||||
|
||||
if(creaking) // 5 seconds after the bang, the station begins to creak
|
||||
addtimer(CALLBACK(listener, /mob/proc/playsound_local, epicenter, null, rand(FREQ_LOWER, FREQ_UPPER), TRUE, frequency, null, null, FALSE, hull_creaking_sound, 0), CREAK_DELAY)
|
||||
|
||||
#undef CREAK_DELAY
|
||||
#undef DEVASTATION_PROB
|
||||
#undef HEAVY_IMPACT_PROB
|
||||
#undef QUAKE_CREAK_PROB
|
||||
#undef ECHO_CREAK_PROB
|
||||
#undef FAR_UPPER
|
||||
#undef FAR_LOWER
|
||||
#undef PROB_SOUND
|
||||
#undef SHAKE_CLAMP
|
||||
#undef FAR_SOUND_PROB
|
||||
#undef NEAR_SHAKE_CAP
|
||||
#undef FAR_SHAKE_CAP
|
||||
#undef NEAR_SHAKE_DURATION
|
||||
#undef FAR_SHAKE_DURATION
|
||||
#undef FREQ_UPPER
|
||||
#undef FREQ_LOWER
|
||||
|
||||
|
||||
Reference in New Issue
Block a user