diff --git a/code/game/objects/effects/decals/turfdecal/weakpoint.dm b/code/game/objects/effects/decals/turfdecal/weakpoint.dm index 915d948e6e2..5dcdf28183c 100644 --- a/code/game/objects/effects/decals/turfdecal/weakpoint.dm +++ b/code/game/objects/effects/decals/turfdecal/weakpoint.dm @@ -2,17 +2,22 @@ #define CRACK_PROPAGATION_DELAY 0.1 SECONDS #define CRACK_TURN_CHANCE 50 #define CRACK_DELAY_CHANCE 33 +#define CRACK_LENGTH_DEFAULT 8 /obj/effect/weakpoint name = "weakpoint crack" desc = "A suspicious crack runs along the ground." icon = 'icons/effects/effects.dmi' icon_state = "weakpoint" + base_icon_state = "weakpoint" + layer = ABOVE_NORMAL_TURF_LAYER + move_resist = INFINITY + alpha = 0 /// The required strength of explosion for a weakpoint to propogate var/required_strength = EXPLODE_LIGHT //How many turfs should this weakpoint crack when triggered? Crack length splits by default and doesn't recurse - var/crack_length = 8 + var/crack_length = CRACK_LENGTH_DEFAULT /// How many split off cracks are expected? var/crack_split_count = 2 @@ -20,25 +25,33 @@ var/spawns_children = TRUE /// How many children weakpoints will this crack spawn when it propagates? var/new_weakpoints = 2 - -/obj/effect/weakpoint/Initialize(mapload) - . = ..() - AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE) - register_context() - -/obj/effect/weakpoint/ex_act(severity, target) - . = ..() + /// These turfs are things we don't want to spawn new cracks onto. var/static/list/skip_turfs = typecacheof(list( /turf/open/space, /turf/open/misc/asteroid, /turf/open/misc/snow, )) + +/obj/effect/weakpoint/Initialize(mapload) + . = ..() + AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE) + RegisterSignal(src, COMSIG_TURF_CHANGE, PROC_REF(turf_changed)) + register_context() + animate(src, alpha = 255, time = 0.3 SECONDS) + +/obj/effect/weakpoint/ex_act(severity, target) + . = ..() if(severity < required_strength) balloon_alert_to_hearers("*crack*") playsound(source = src, soundin = SFX_HULL_CREAKING, vol = 50, vary = TRUE, pressure_affected = FALSE, ignore_walls = TRUE) return //return ominous sounds when we're under the threshold. - var/list/chain_turfs = get_crack_chain(get_turf(src), 8, TRUE, skip_turfs) // Get a nice chain of turfs + var/list/chain_turfs = get_crack_chain(get_turf(src), crack_length, TRUE, skip_turfs) // Get a nice chain of turfs + for(var/atom/along_length in chain_turfs) + for(var/extra_turfs in get_adjacent_turfs(chain_turfs[along_length])) //use get_adjacent turfs to help add extra turfs. + if(chain_turfs[extra_turfs]) + continue + chain_turfs += extra_turfs var/crack_delay = 0 for(var/turf/crack_turf in chain_turfs) @@ -48,14 +61,7 @@ crack_delay++ if(spawns_children) - chain_turfs = typecache_filter_list_reverse(chain_turfs, skip_turfs) //Filter out things that we don't want to spawn new weakpoints onto. - - for(var/i in 1 to new_weakpoints) - var/obj/effect/weakpoint/newpoint = new(pick(chain_turfs)) - //inherit parent var values in case of var-editing. - newpoint.new_weakpoints = new_weakpoints - newpoint.crack_length = crack_length - newpoint.crack_split_count = crack_split_count + addtimer(CALLBACK(loc, TYPE_PROC_REF(/turf, create_new_cracks), chain_turfs, new_weakpoints, skip_turfs, crack_length, crack_split_count), CRACK_PROPAGATION_DELAY * crack_delay) qdel(src) /obj/effect/weakpoint/welder_act(mob/living/user, obj/item/tool) @@ -93,39 +99,90 @@ * * start_location: The turf to begin the chain of turfs from. * * length: How many lengths this chain needs to be. * * add_splits: Should this crack chain apply additional instances of get_crack_chain while recursively cracking even further. - * * turfs_to_skip: a typecache of turfs that we block spreading to when getting a chain. */ -/obj/effect/weakpoint/proc/get_crack_chain(start_location, length, add_splits = TRUE, turfs_to_skip = list()) +/obj/effect/weakpoint/proc/get_crack_chain(start_location, length, add_splits = TRUE) if(!length) CRASH("Weakpoint spawned with no length value!") if(!start_location) CRASH("No start location for crack specified!") var/list/turf/cracked_turfs = list() - var/turf/current = loc //Start on top of ourselves + var/turf/current = start_location //Start on top of ourselves var/direction = pick(NORTH, SOUTH, EAST, WEST) for(var/i in 1 to length) - if(length(turfs_to_skip) && is_type_in_typecache(current, turfs_to_skip)) - direction = turn(direction, pick(90, 135, 180, 225, 270)) //We'll either turn or reverse the direction of the crack if we can't get around our obstacle. - current = get_turf(get_step(current, direction)) - continue - cracked_turfs += current // Randomly branch or continue if(prob(CRACK_TURN_CHANCE)) - direction = turn(direction, pick(-90, -45, 45, 90)) + direction = turn(direction, pick(90, 135, 180, 225, 270)) current = get_turf(get_step(current, direction)) if(!isturf(current)) break + if(length(skip_turfs) && is_type_in_typecache(current, skip_turfs)) + continue + cracked_turfs += current + if(add_splits) for(var/subcrack in 1 to crack_split_count) cracked_turfs += get_crack_chain(pick(cracked_turfs), max(round(length/2 ), 1), FALSE) //Stop recursion here message_admins("Station weakpoint triggered, affecting [length(cracked_turfs)] turfs in [loc_name(start_location)].") log_game("Station weakpoint triggered, affecting [length(cracked_turfs)] turfs in [loc_name(start_location)].") - return cracked_turfs +/// If this turf becomes something we can't spawn a crack on, we should try and shift the crack or otherwise qdel. +/obj/effect/weakpoint/proc/turf_changed(turf/source) + SIGNAL_HANDLER + var/turf/option + var/list/turf/choices = get_adjacent_open_turfs(src) + while(!option && length(choices)) + option = pick_n_take(get_adjacent_open_turfs(src)) + if(locate(/obj/effect/weakpoint) in option) + continue + if(is_type_in_typecache(option, skip_turfs)) + continue + if(!option) + qdel(src) + return + forceMove(option) + +/** + * Used by weakpoint cracks to spawn new cracks after the crack is finished propagating. + * * chain_turfs: The list of turfs that we're going to pull from in order to generate a new weakpoint. Generated by ex_act on the parent weakpoint. + */ +/turf/proc/create_new_cracks(list/chain_turfs, new_weakpoints = 1, skip_turfs = list(), crack_length = 2, crack_split_count = 1) + if(!chain_turfs || !length(chain_turfs)) + chain_turfs = list(src) + chain_turfs += get_adjacent_turfs(src) + if(skip_turfs) + chain_turfs = typecache_filter_list_reverse(chain_turfs, skip_turfs) //Filter out things that we don't want to spawn new weakpoints onto. + + var/active_count = 0 + var/list/new_cracks = list() + while(active_count < new_weakpoints) + if(!length(chain_turfs)) + return + var/turf/spawn_location = pick_n_take(chain_turfs) + if(locate(/obj/effect/weakpoint) in spawn_location) + continue + if(skip_turfs) + if(is_type_in_typecache(spawn_location, skip_turfs)) + continue + var/obj/effect/weakpoint/newpoint = new(spawn_location) + //inherit parent var values in case of var-editing. + newpoint.new_weakpoints = new_weakpoints + newpoint.crack_length = crack_length + newpoint.crack_split_count = crack_split_count + new_cracks += newpoint + spawn_location.levelupdate() + active_count++ + + notify_ghosts( + "A new crack has been spawned in [get_area(src)].", + source = pick(new_cracks), + header = "Weakpoint created", + ghost_sound = 'sound/effects/hit_kick.ogg', + ) + /obj/effect/weakpoint/big name = "dangerous weakpoint" desc = "A suspicious crack runs along the ground. This one makes you feel particuarly uneasy." @@ -137,3 +194,4 @@ #undef CRACK_PROPAGATION_DELAY #undef CRACK_TURN_CHANCE #undef CRACK_DELAY_CHANCE +#undef CRACK_LENGTH_DEFAULT