deterministic explosion system (#13392)

* wae explosions

* okay

* changes

* fixes

* fix

* ok

* ok

* kills more dead code

* okay

* fix

* ok

* tiles

* ok

* okay

* woops

* ok

* fix

* okay

* mob damage

* fixes

* insanity

* more

* more

* fixes

* more

* woot

* don't commit that

* YES

* fix
This commit is contained in:
silicons
2021-05-12 04:44:53 -06:00
committed by GitHub
parent 5eb1f38f5e
commit 5601badbff
35 changed files with 822 additions and 2 deletions
+36 -1
View File
@@ -36,6 +36,14 @@
///Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
/// Flags for explosions
var/explosion_flags = NONE
/// Amount to decrease wave explosions by
var/wave_explosion_block = 0
/// Amount to multiply wave explosions by
var/wave_explosion_multiply = 1
//its inherent color, the colored paint applied on it, special color effect etc...
/**
* used to store the different colors on an atom
*
@@ -43,7 +51,6 @@
*/
var/list/atom_colours
/// a very temporary list of overlays to remove
var/list/remove_overlays
/// a very temporary list of overlays to add
@@ -556,6 +563,34 @@
contents_explosion(severity, target)
SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target)
/**
* Called when a wave explosion hits this atom. Do not override this.
*
* Returns explosion power to "allow through".
*/
/atom/proc/wave_explode(power, datum/wave_explosion/explosion, dir)
set waitfor = FALSE
// SHOULD_NOT_SLEEP(TRUE)
SHOULD_NOT_OVERRIDE(TRUE)
SEND_SIGNAL(src, COMSIG_ATOM_WAVE_EX_ACT, args)
. = wave_ex_act(power, explosion, dir) // this must happen first for stuff like destruction/damage to tick.
if(isnull(.))
stack_trace("wave_ex_act on [type] failed to return a number. defaulting to no blocking.")
return power
if((explosion_flags & EXPLOSION_FLAG_DENSITY_DEPENDENT) && !density)
return power // no block
else if((explosion_flags & EXPLOSION_FLAG_HARD_OBSTACLE) && !QDELETED(src))
return 0 // fully blocked
/**
* Called when a wave explosion hits this atom.
*
* Returns explosion power to "allow through". Standard handling and flag overrides in [wave_explode()].
*/
/atom/proc/wave_ex_act(power, datum/wave_explosion/explosion, dir)
// SHOULD_NOT_SLEEP(TRUE)
return power * wave_explosion_multiply - wave_explosion_block
/atom/proc/blob_act(obj/structure/blob/B)
SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B)
return
+4
View File
@@ -96,6 +96,10 @@ Class Procs:
flags_ricochet = RICOCHET_HARD
ricochet_chance_mod = 0.3
explosion_flags = EXPLOSION_FLAG_DENSITY_DEPENDENT
wave_explosion_block = EXPLOSION_BLOCK_MACHINE
wave_explosion_multiply = EXPLOSION_DAMPEN_MACHINE
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
+2
View File
@@ -54,6 +54,8 @@
assemblytype = /obj/structure/door_assembly
normalspeed = 1
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_WALL
wave_explosion_multiply = EXPLOSION_DAMPEN_WALL
hud_possible = list(DIAG_AIRLOCK_HUD)
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
+10
View File
@@ -16,6 +16,11 @@
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
wave_explosion_block = EXPLOSION_BLOCK_DENSE_FILLER
wave_explosion_multiply = EXPLOSION_DAMPEN_DENSE_FILLER
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE | EXPLOSION_FLAG_DENSITY_DEPENDENT
var/secondsElectrified = 0
var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close
var/shockedby
@@ -412,3 +417,8 @@
/obj/machinery/door/GetExplosionBlock()
return density ? real_explosion_block : 0
/obj/machinery/door/wave_explosion_damage(power, datum/wave_explosion/explosion)
. = ..()
if(!density)
return . * EXPLOSION_DAMAGE_OPEN_DOOR_FACTOR
@@ -71,3 +71,6 @@
/obj/machinery/door/password/ex_act(severity, target)
return
/obj/machinery/door/password/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return 0 //no.
+2
View File
@@ -8,6 +8,8 @@
closingLayer = CLOSED_BLASTDOOR_LAYER
sub_door = TRUE
explosion_block = 3
wave_explosion_block = EXPLOSION_BLOCK_BLAST_PROOF
wave_explosion_multiply = EXPLOSION_DAMPEN_BLAST_PROOF
heat_proof = TRUE
safe = FALSE
max_integrity = 600
+2
View File
@@ -360,6 +360,8 @@
max_integrity = 300 //Stronger doors for prison (regular window door health is 200)
reinf = 1
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_REINFORCED_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_REINFORCED_WINDOW
/obj/machinery/door/window/brigdoor/security/cell
name = "cell door"
+38
View File
@@ -114,6 +114,44 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
LAZYADD(message_log, messages.Join(" "))
return TRUE
/obj/machinery/doppler_array/proc/sense_wave_explosion(turf/epicenter, power, speed)
if(stat & NOPOWER)
return FALSE
var/turf/zone = get_turf(src)
if(zone.z != epicenter.z)
return FALSE
if(next_announce > world.time)
return FALSE
next_announce = world.time + cooldown
var/distance = get_dist(epicenter, zone)
var/direct = get_dir(zone, epicenter)
if(distance > max_dist)
return FALSE
if(!(direct & dir) && !integrated)
return FALSE
var/list/messages = list("Explosive shockwave detected.", \
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Shockwave expanding at a theoretical speed of [speed] m/s.", \
"Wave energy: [power]MJ.")
if(integrated)
var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc
if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit))
return FALSE
helm.display_visor_message("Waveform explosion detected! Wave energy: [power]MJ.")
else
for(var/message in messages)
say(message)
if(LAZYLEN(message_log) > list_limit)
say("Storage buffer is full! Clearing buffers...")
LAZYCLEARLIST(message_log)
LAZYADD(message_log, messages.Join(" "))
return TRUE
/obj/machinery/doppler_array/examine(mob/user)
. = ..()
. += "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>"
@@ -50,6 +50,10 @@
/obj/effect/decal/cleanable/glass/ex_act()
qdel(src)
/obj/effect/decal/cleanable/glass/wave_ex_act(power, datum/wave_explosion/explosion, dir)
qdel(src)
return power
/obj/effect/decal/cleanable/glass/plasma
icon_state = "plasmatiny"
@@ -131,6 +135,9 @@
/obj/effect/decal/cleanable/greenglow/ex_act()
return
/obj/effect/decal/cleanable/greenglow/wave_ex_act(power, datum/wave_explosion/explosion, dir)
return power
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
@@ -253,6 +260,11 @@
if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion.
qdel(src)
/obj/effect/decal/cleanable/shreds/wave_ex_act(power, datum/wave_explosion/explosion, dir)
if(power > EXPLOSION_POWER_ERASE_SHREDS)
qdel(src)
return power // no block
/obj/effect/decal/cleanable/shreds/Initialize()
pixel_x = rand(-10, 10)
pixel_y = rand(-10, 10)
+8
View File
@@ -248,6 +248,14 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
loc = null
loc = T
/obj/item/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
if(!anchored)
var/throw_dist = round(rand(3, max(3, 2.5 * sqrt(power))), 1)
throw_speed = EXPLOSION_THROW_SPEED
var/turf/target = get_ranged_target_turf(src, dir, throw_dist)
throw_at(target, throw_dist, EXPLOSION_THROW_SPEED)
/obj/item/examine(mob/user) //This might be spammy. Remove?
. = ..()
+13
View File
@@ -71,6 +71,19 @@
if(3)
take_damage(rand(10, 90), BRUTE, "bomb", 0)
/obj/wave_ex_act(power, datum/wave_explosion/explosion, dir)
if(resistance_flags & INDESTRUCTIBLE)
return power
. = ..()
if(explosion.source == src)
obj_integrity = 0
qdel(src)
return
take_damage(wave_explosion_damage(power, explosion), BRUTE, "bomb", 0)
/obj/proc/wave_explosion_damage(power, datum/wave_explosion/explosion)
return (explosion_flags & EXPLOSION_FLAG_HARD_OBSTACLE)? EXPLOSION_POWER_STANDARD_SCALE_HARD_OBSTACLE_DAMAGE(power, explosion.hard_obstacle_mod) : EXPLOSION_POWER_STANDARD_SCALE_OBJECT_DAMAGE(power, explosion.object_damage_mod)
/obj/bullet_act(obj/item/projectile/P)
. = ..()
playsound(src, P.hitsound, 50, 1)
+15
View File
@@ -43,6 +43,10 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE
wave_explosion_block = EXPLOSION_BLOCK_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_WINDOW
/// Electrochromatic status
var/electrochromatic_status = NOT_ELECTROCHROMATIC
/// Electrochromatic ID. Set the first character to ! to replace with a SSmapping generated pseudorandom obfuscated ID for mapping purposes.
@@ -111,6 +115,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
return TRUE
return FALSE
/obj/structure/window/wave_explosion_damage(power, datum/wave_explosion/explosion)
return EXPLOSION_POWER_STANDARD_SCALE_WINDOW_DAMAGE(power, explosion.window_shatter_mod)
/obj/structure/window/narsie_act()
add_atom_colour(NARSIE_WINDOW_COLOUR, FIXED_COLOUR_PRIORITY)
@@ -520,6 +527,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
max_integrity = 50
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_REINFORCED_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_REINFORCED_WINDOW
glass_type = /obj/item/stack/sheet/rglass
rad_insulation = RAD_HEAVY_INSULATION
ricochet_chance_mod = 0.8
@@ -545,6 +554,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 75, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 45, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 150
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
glass_type = /obj/item/stack/sheet/plasmaglass
cleanable_type = /obj/effect/decal/cleanable/glass/plasma
rad_insulation = RAD_NO_INSULATION
@@ -570,6 +581,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
armor = list("melee" = 85, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 100, "rad" = 100, "fire" = 99, "acid" = 100)
max_integrity = 500
explosion_block = 2
wave_explosion_block = EXPLOSION_BLOCK_EXTREME
wave_explosion_multiply = EXPLOSION_BLOCK_EXTREME
glass_type = /obj/item/stack/sheet/plasmarglass
/obj/structure/window/plasma/reinforced/spawner/east
@@ -742,6 +755,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
max_integrity = 80
armor = list("melee" = 60, "bullet" = 25, "laser" = 0, "energy" = 0, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 100)
explosion_block = 2 //fancy AND hard to destroy. the most useful combination.
wave_explosion_block = EXPLOSION_BLOCK_BOROSILICATE_WINDOW
wave_explosion_multiply = EXPLOSION_DAMPEN_BOROSILICATE_WINDOW
decon_speed = 40
glass_type = /obj/item/stack/tile/brass
glass_amount = 1
+3
View File
@@ -6,6 +6,8 @@
blocks_air = 1
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/turf/closed/Initialize()
. = ..()
@@ -28,6 +30,7 @@
name = "wall"
icon = 'icons/turf/walls.dmi'
explosion_block = 50
wave_explosion_block = INFINITY
/turf/closed/indestructible/rust_heretic_act()
return
+55
View File
@@ -12,6 +12,19 @@
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
/// Minimum explosion power to break tile
var/explosion_power_break_tile = EXPLOSION_POWER_FLOOR_TILE_BREAK
/// Minimum explosion power to break turf
var/explosion_power_break_turf = EXPLOSION_POWER_FLOOR_TURF_BREAK
//// Minimum explosion power to scrape away the floor
var/explosion_power_turf_scrape = EXPLOSION_POWER_FLOOR_TURF_SCRAPE
//// Shielded turfs are completely protected from anything under this
var/explosion_power_protect_shielded = EXPLOSION_POWER_FLOOR_SHIELDED_IMMUNITY
/// Starting from here, there's a chance for this to break
var/explosion_power_minimum_chance_break = EXPLOSION_POWER_FLOOR_MINIMUM_TURF_BREAK
/// Starting from here, +20% chance to break turf.
var/explosion_power_break_turf_bonus = EXPLOSION_POWER_FLOOR_TURF_BREAK_BONUS
var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default
var/icon_plating = "plating"
thermal_conductivity = 0.004
@@ -98,6 +111,48 @@
src.break_tile()
src.hotspot_expose(1000,CELL_VOLUME)
/turf/open/floor/wave_ex_act(power, datum/wave_explosion/explosion, dir)
var/shielded = is_shielded()
. = ..()
if(shielded)
if(power < explosion_power_protect_shielded)
return
else
power -= explosion_power_protect_shielded
hotspot_expose(1000, CELL_VOLUME)
if(power < explosion_power_break_tile)
return
if(power < explosion_power_minimum_chance_break)
if(prob(33 + ((explosion_power_break_turf - power) / (explosion_power_break_turf - explosion_power_break_tile))))
break_tile()
return
if((power < explosion_power_turf_scrape) && ((power >= explosion_power_break_turf) || prob((1 - ((explosion_power_break_turf - power) / (explosion_power_break_turf - explosion_power_minimum_chance_break))) * 100 + ((power > explosion_power_break_turf_bonus)? 20 : 0))))
switch(pick(1, 2;75, 3))
if(1)
if(!length(baseturfs) || !ispath(baseturfs[baseturfs.len-1], /turf/open/floor))
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
ReplaceWithLattice()
else
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
if(prob(33))
new /obj/item/stack/sheet/metal(src)
return
if(2)
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
return
if(3)
if(prob(80))
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return
else
break_tile()
hotspot_expose(1000,CELL_VOLUME)
if(prob(33))
new /obj/item/stack/sheet/metal(src)
if(power >= explosion_power_turf_scrape)
ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
return
/turf/open/floor/is_shielded()
for(var/obj/structure/A in contents)
if(A.level == 3)
@@ -12,6 +12,11 @@
sheet_amount = 1
girder_type = /obj/structure/girder/reinforced
explosion_block = 2
wave_explosion_block = EXPLOSION_BLOCK_BLAST_PROOF
wave_explosion_multiply = EXPLOSION_DAMPEN_BLAST_PROOF
explosion_power_to_scrape = EXPLOSION_POWER_RWALL_SCRAPE
explosion_power_to_dismantle = EXPLOSION_POWER_RWALL_DISMANTLE
explosion_power_minimum_chance_dismantle = EXPLOSION_POWER_RWALL_MINIMUM_DISMANTLE
rad_insulation = RAD_HEAVY_INSULATION
/turf/closed/wall/r_wall/deconstruction_hints(mob/user)
+17
View File
@@ -6,6 +6,8 @@
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
explosion_block = 1
wave_explosion_block = EXPLOSION_BLOCK_WALL
wave_explosion_multiply = EXPLOSION_DAMPEN_WALL
flags_1 = DEFAULT_RICOCHET_1
flags_ricochet = RICOCHET_HARD
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
@@ -15,6 +17,14 @@
baseturfs = /turf/open/floor/plating
explosion_flags = EXPLOSION_FLAG_HARD_OBSTACLE
/// Explosion power to disintegrate the wall
var/explosion_power_to_scrape = EXPLOSION_POWER_WALL_SCRAPE
/// Explosion power to dismantle the wall
var/explosion_power_to_dismantle = EXPLOSION_POWER_WALL_DISMANTLE
/// Explosion power to potentially dismantle the wall
var/explosion_power_minimum_chance_dismantle = EXPLOSION_POWER_WALL_MINIMUM_DISMANTLE
var/hardness = 40 //lower numbers are harder. Used to determine the probability of a hulk smashing through.
var/slicing_duration = 100 //default time taken to slice the wall
var/sheet_type = /obj/item/stack/sheet/metal
@@ -91,6 +101,13 @@
if(!density)
..()
/turf/closed/wall/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
var/resultant_power = power * explosion.wall_destroy_mod
if(resultant_power >= explosion_power_to_scrape)
ScrapeAway()
else if((resultant_power >= explosion_power_to_dismantle) || ((resultant_power >= explosion_power_minimum_chance_dismantle) && prob(((resultant_power - explosion_power_minimum_chance_dismantle) / (explosion_power_to_dismantle - explosion_power_minimum_chance_dismantle)) * 100)))
dismantle_wall(prob((resultant_power - explosion_power_to_dismantle)/(explosion_power_to_scrape - explosion_power_to_dismantle)), TRUE)
/turf/closed/wall/blob_act(obj/structure/blob/B)
if(prob(50))
+2
View File
@@ -8,6 +8,8 @@
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
wave_explosion_multiply = EXPLOSION_DAMPEN_SPACE
wave_explosion_block = EXPLOSION_BLOCK_SPACE
var/destination_z
var/destination_x
+18
View File
@@ -462,6 +462,24 @@ GLOBAL_LIST_EMPTY(station_turfs)
A.ex_act(severity, target)
CHECK_TICK
/turf/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
var/affecting_level
if(is_shielded())
affecting_level = 3
else if(intact)
affecting_level = 2
else
affecting_level = 1
var/atom/A
for(var/i in contents)
if(. <= 0)
return 0
A = i
if(!QDELETED(A) && A.level >= affecting_level)
. = A.wave_explode(., explosion, dir)
maptext = "[.]"
/turf/narsie_act(force, ignore_mobs, probability = 20)
. = (prob(probability) || force)
for(var/I in src)