Skip to content

Commit

Permalink
Meteor shield refactor part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Absolucy committed Jun 21, 2024
1 parent 7d765c5 commit c542501
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 82 deletions.
4 changes: 4 additions & 0 deletions code/__DEFINES/~monkestation/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@

#define ABDUCTOR_GLAND_VENTCRAWLING_TRAIT "abductor_gland_ventcrawling"
#define TRAIT_BETTER_CYBERCONNECTOR "better_cyberconnector_hacking"

// /turf/open
/// If a trait is considered as having "coverage" by a meteor shield.
#define TRAIT_COVERED_BY_METEOR_SHIELD "covered_by_meteor_shield"
12 changes: 6 additions & 6 deletions code/controllers/subsystem/explosions.dm
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ SUBSYSTEM_DEF(explosions)
* - [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(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(SFX_EXPLOSION_CREAKING)), hull_creaking_sound = sound(get_sfx(SFX_HULL_CREAKING)))
/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(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(SFX_EXPLOSION_CREAKING)), hull_creaking_sound = sound(get_sfx(SFX_HULL_CREAKING)), pressure_affected = TRUE) // monkestation edit: add pressure_affected
var/frequency = get_rand_frequency()
var/blast_z = epicenter.z
if(isnull(creaking)) // Autoset creaking.
Expand All @@ -535,18 +535,18 @@ SUBSYSTEM_DEF(explosions)
var/base_shake_amount = sqrt(near_distance / (distance + 1))

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, sound_to_use = near_sound)
listener.playsound_local(epicenter, null, 100, TRUE, frequency, pressure_affected = pressure_affected, sound_to_use = near_sound) // monkestation edit: pressure_affected
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, sound_to_use = creaking_sound, distance_multiplier = 0)
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, pressure_affected = pressure_affected, sound_to_use = creaking_sound, distance_multiplier = 0) // monkestation edit: pressure_affected
else if(prob(FAR_SOUND_PROB)) // Sound variety during meteor storm/tesloose/other bad event
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, sound_to_use = far_sound, distance_multiplier = 0)
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, pressure_affected = pressure_affected, sound_to_use = far_sound, distance_multiplier = 0) // monkestation edit: pressure_affected
else
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, sound_to_use = echo_sound, distance_multiplier = 0)
listener.playsound_local(epicenter, null, far_volume, TRUE, frequency, pressure_affected = pressure_affected, sound_to_use = echo_sound, distance_multiplier = 0) // monkestation edit: pressure_affected

if(base_shake_amount || quake_factor)
base_shake_amount = max(base_shake_amount, quake_factor * 3, 0) // Devastating explosions rock the station and ground
Expand All @@ -559,7 +559,7 @@ SUBSYSTEM_DEF(explosions)
shake_camera(listener, FAR_SHAKE_DURATION, clamp(quake_factor / 4, 0, FAR_SHAKE_CAP))
else
echo_volume = 40
listener.playsound_local(epicenter, null, echo_volume, TRUE, frequency, sound_to_use = echo_sound, distance_multiplier = 0)
listener.playsound_local(epicenter, null, echo_volume, TRUE, frequency, pressure_affected = pressure_affected, sound_to_use = echo_sound, distance_multiplier = 0) // monkestation edit: pressure_affected

if(creaking) // 5 seconds after the bang, the station begins to creak
addtimer(CALLBACK(listener, TYPE_PROC_REF(/mob, playsound_local), epicenter, null, rand(FREQ_LOWER, FREQ_UPPER), TRUE, frequency, null, null, FALSE, hull_creaking_sound, 0), CREAK_DELAY)
Expand Down
5 changes: 5 additions & 0 deletions monkestation/code/modules/cargo/packs/engineering.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/datum/supply_pack/engineering/shield_sat
special = FALSE
access_view = ACCESS_ENGINEERING
contains = list(/obj/item/meteor_shield_capsule = 5)

/datum/supply_pack/engineering/shield_sat_control
special = FALSE
access_view = ACCESS_ENGINEERING
Binary file modified monkestation/code/modules/holomaps/icons/8x8.dmi
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ GLOBAL_LIST_EMPTY(meteor_shield_sats)
/// Whether the meteor sat checks for line of sight to determine if it can intercept a meteor.
var/check_sight = TRUE
/// The proximity monitor used to detect meteors entering the shield's range.
var/datum/proximity_monitor/meteor_monitor
var/datum/proximity_monitor/advanced/meteor_shield/monitor
/// A counter for how many meteors this specific satellite has zapped.
var/meteors_zapped = 0

Expand All @@ -25,17 +25,17 @@ GLOBAL_LIST_EMPTY(meteor_shield_sats)

/obj/machinery/satellite/meteor_shield/Destroy()
GLOB.meteor_shield_sats -= src
if(meteor_monitor)
QDEL_NULL(meteor_monitor)
QDEL_NULL(monitor)
return ..()

/obj/machinery/satellite/meteor_shield/vv_edit_var(vname, vval)
. = ..()
if(.)
switch(vname)
if(NAMEOF(src, kill_range))
meteor_monitor?.set_range(kill_range)
monitor?.set_range(kill_range)
if(NAMEOF(src, active))
set_anchored(active)
setup_proximity()

/obj/machinery/satellite/meteor_shield/add_context(atom/source, list/context, obj/item/held_item, mob/user)
Expand All @@ -44,50 +44,6 @@ GLOBAL_LIST_EMPTY(meteor_shield_sats)
context[SCREENTIP_CONTEXT_RMB] = "Pick up"
return CONTEXTUAL_SCREENTIP_SET

/obj/machinery/satellite/meteor_shield/HasProximity(obj/effect/meteor/meteor)
if(!active || !istype(meteor) || QDELING(meteor) || (obj_flags & EMAGGED))
return
var/turf/our_turf = get_turf(src)
var/turf/meteor_turf = get_turf(meteor)
if(!check_los(our_turf, meteor_turf))
return
our_turf.Beam(meteor_turf, icon_state = "sat_beam", time = 5)
if(meteor.shield_defense(src))
new /obj/effect/temp_visual/explosion(meteor_turf)
INVOKE_ASYNC(src, PROC_REF(play_zap_sound), meteor_turf)
SSblackbox.record_feedback("tally", "meteors_zapped", 1, "[meteor.type]")
meteors_zapped++
qdel(meteor)

/obj/machinery/satellite/meteor_shield/proc/check_los(turf/source, turf/target) as num
// if something goes fucky wucky, let's just assume line-of-sight by default
if(!check_sight)
return TRUE
for(var/turf/segment as anything in get_line(source, target))
if(QDELETED(segment))
continue
if(isclosedturf(segment) && !istransparentturf(segment))
return FALSE
return TRUE

/obj/machinery/satellite/meteor_shield/proc/play_zap_sound(turf/epicenter)
if(QDELETED(epicenter))
return
var/static/near_distance
if(isnull(near_distance))
var/list/world_view = getviewsize(world.view)
near_distance = max(world_view[1], world_view[2])
SSexplosions.shake_the_room(
epicenter,
near_distance,
far_distance = near_distance * 3,
quake_factor = 0,
echo_factor = 0,
creaking = FALSE,
near_sound = sound('sound/weapons/lasercannonfire.ogg'),
far_sound = sound('sound/weapons/marauder.ogg')
)

/obj/machinery/satellite/meteor_shield/toggle(user)
. = ..()
setup_proximity()
Expand All @@ -98,27 +54,15 @@ GLOBAL_LIST_EMPTY(meteor_shield_sats)

/obj/machinery/satellite/meteor_shield/proc/setup_proximity()
if((obj_flags & EMAGGED) || !active)
if(!QDELETED(meteor_monitor))
QDEL_NULL(meteor_monitor)
if(!QDELETED(monitor))
QDEL_NULL(monitor)
else
if(QDELETED(meteor_monitor))
meteor_monitor = new(src, kill_range)
if(QDELETED(monitor))
monitor = new(src, kill_range)

/obj/machinery/satellite/meteor_shield/piercing
check_sight = FALSE

/proc/get_meteor_sat_coverage() as num
var/list/covered_tiles = list()
for(var/obj/machinery/satellite/meteor_shield/sat as anything in GLOB.meteor_shield_sats)
if(QDELETED(sat) || !sat.active || !is_station_level(sat.z) || (sat.obj_flags & EMAGGED))
continue
if(sat.check_sight)
covered_tiles |= view(sat.kill_range, sat)
else
covered_tiles |= range(sat.kill_range, sat)
return length(covered_tiles)


/obj/machinery/satellite/meteor_shield/proc/change_meteor_chance(mod = 1)
var/static/list/meteor_event_typecache
if(!meteor_event_typecache)
Expand Down Expand Up @@ -146,14 +90,3 @@ GLOBAL_LIST_EMPTY(meteor_shield_sats)
var/obj/item/meteor_shield_capsule/capsule = new(drop_location())
user.put_in_hands(capsule)
qdel(src)

/obj/item/meteor_shield_capsule
name = "meteor shield satellite capsule"
desc = "A bluespace capsule which a single unit of meteor shield satellite is compressed within. If you activate this capsule, a meteor shield satellite will pop out. You still need to install these."
icon_state = "capsule"
icon = 'icons/obj/mining.dmi'
w_class = WEIGHT_CLASS_TINY

/obj/item/meteor_shield_capsule/Initialize(mapload)
. = ..()
AddComponent(/datum/component/deployable, 5 SECONDS, /obj/machinery/satellite/meteor_shield, delete_on_use = TRUE)
10 changes: 10 additions & 0 deletions monkestation/code/modules/meteor_shield/meteor_shield_capsule.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/obj/item/meteor_shield_capsule
name = "meteor shield satellite capsule"
desc = "A bluespace capsule which a single unit of meteor shield satellite is compressed within. If you activate this capsule, a meteor shield satellite will pop out. You still need to install these."
icon_state = "capsule"
icon = 'icons/obj/mining.dmi'
w_class = WEIGHT_CLASS_TINY

/obj/item/meteor_shield_capsule/Initialize(mapload)
. = ..()
AddComponent(/datum/component/deployable, 5 SECONDS, /obj/machinery/satellite/meteor_shield, delete_on_use = TRUE)
40 changes: 40 additions & 0 deletions monkestation/code/modules/meteor_shield/meteor_shield_coverage.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#define TRAIT_METEOR_SHIELD_FIELD_MONITORED "meteor_shield_field_monitored"

GLOBAL_LIST_EMPTY(meteor_shielded_turfs)

/// Stupid element to handle tracking which turfs are in a meteor sat's range,
/// without messing up in situations like with overlapping ranges.
/datum/element/meteor_shield_coverage
// Detach whenever destroyed, so we can ensure there's no hanging references to the turf in GLOB.meteor_shielded_turfs
element_flags = ELEMENT_DETACH_ON_HOST_DESTROY
/// Signals to attach to all turfs.
var/static/list/attach_signals = list(
SIGNAL_ADDTRAIT(TRAIT_COVERED_BY_METEOR_SHIELD),
SIGNAL_REMOVETRAIT(TRAIT_COVERED_BY_METEOR_SHIELD)
)

/datum/element/meteor_shield_coverage/Attach(turf/open/target)
. = ..()
if(!isgroundlessturf(target))
return ELEMENT_INCOMPATIBLE
// We use a trait to prevent duplicate assignments.
if(!HAS_TRAIT(target, TRAIT_METEOR_SHIELD_FIELD_MONITORED))
ADD_TRAIT(target, TRAIT_METEOR_SHIELD_FIELD_MONITORED, ELEMENT_TRAIT(type))
RegisterSignals(target, attach_signals, PROC_REF(update_global_shield_list))
GLOB.meteor_shielded_turfs += target

/datum/element/meteor_shield_coverage/Detach(turf/open/target)
REMOVE_TRAIT(target, TRAIT_METEOR_SHIELD_FIELD_MONITORED, ELEMENT_TRAIT(type))
UnregisterSignal(target, attach_signals)
GLOB.meteor_shielded_turfs -= target
return ..()

/datum/element/meteor_shield_coverage/proc/update_global_shield_list(turf/open/source)
SIGNAL_HANDLER
if(!isgroundlessturf(source) || !HAS_TRAIT(source, TRAIT_COVERED_BY_METEOR_SHIELD))
source.RemoveElement(/datum/element/meteor_shield_coverage)

/proc/get_meteor_sat_coverage() as num
return length(GLOB.meteor_shielded_turfs)

#undef TRAIT_METEOR_SHIELD_FIELD_MONITORED
29 changes: 29 additions & 0 deletions monkestation/code/modules/meteor_shield/meteor_shield_field.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
GLOBAL_LIST_EMPTY_TYPED(meteor_shield_fields, /datum/proximity_monitor/advanced/meteor_shield)

/// A proximity monitor field that marks openspace turfs within as being covered by a meteor shield.
/datum/proximity_monitor/advanced/meteor_shield
edge_is_a_field = TRUE

/datum/proximity_monitor/advanced/meteor_shield/New(atom/_host, range, _ignore_if_not_on_turf)
. = ..()
GLOB.meteor_shield_fields += src

/datum/proximity_monitor/advanced/meteor_shield/Destroy()
GLOB.meteor_shield_fields -= src
return ..()

/datum/proximity_monitor/advanced/meteor_shield/setup_field_turf(turf/open/target)
if(!isgroundlessturf(target))
return
var/obj/machinery/satellite/meteor_shield/host_sat = host
if(host_sat.check_los(get_turf(host_sat), target))
ADD_TRAIT(target, TRAIT_COVERED_BY_METEOR_SHIELD, REF(src))
target.AddElement(/datum/element/meteor_shield_coverage)

/datum/proximity_monitor/advanced/meteor_shield/cleanup_field_turf(turf/target)
REMOVE_TRAIT(target, TRAIT_COVERED_BY_METEOR_SHIELD, REF(src))

/datum/proximity_monitor/advanced/meteor_shield/set_range(range, force_rebuild)
. = ..()
if(.)
recalculate_field(full_recalc = TRUE)
44 changes: 44 additions & 0 deletions monkestation/code/modules/meteor_shield/meteor_shield_zap.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/obj/machinery/satellite/meteor_shield/HasProximity(obj/effect/meteor/meteor)
if(!active || !istype(meteor) || QDELING(meteor) || (obj_flags & EMAGGED))
return
var/turf/our_turf = get_turf(src)
var/turf/meteor_turf = get_turf(meteor)
if(!check_los(our_turf, meteor_turf))
return
our_turf.Beam(meteor_turf, icon_state = "sat_beam", time = 5)
if(meteor.shield_defense(src))
new /obj/effect/temp_visual/explosion(meteor_turf)
INVOKE_ASYNC(src, PROC_REF(play_zap_sound), meteor_turf)
SSblackbox.record_feedback("tally", "meteors_zapped", 1, "[meteor.type]")
meteors_zapped++
qdel(meteor)

/obj/machinery/satellite/meteor_shield/proc/check_los(turf/source, turf/target) as num
// if something goes fucky wucky, let's just assume line-of-sight by default
. = TRUE
if(!check_sight)
return TRUE
for(var/turf/segment as anything in get_line(source, target))
if(QDELETED(segment))
continue
if(isclosedturf(segment) && !istransparentturf(segment))
return FALSE

/obj/machinery/satellite/meteor_shield/proc/play_zap_sound(turf/epicenter)
if(QDELETED(epicenter))
return
var/static/near_distance
if(isnull(near_distance))
var/list/world_view = getviewsize(world.view)
near_distance = max(world_view[1], world_view[2])
SSexplosions.shake_the_room(
epicenter,
near_distance,
far_distance = near_distance * 8,
quake_factor = 0,
echo_factor = 0,
creaking = FALSE,
near_sound = sound('sound/weapons/lasercannonfire.ogg'),
far_sound = sound('sound/weapons/marauder.ogg'),
pressure_affected = FALSE
)
6 changes: 5 additions & 1 deletion tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -6622,6 +6622,11 @@
#include "monkestation\code\modules\mentor\mentor_pm.dm"
#include "monkestation\code\modules\mentor\mentor_say.dm"
#include "monkestation\code\modules\mentor\mentor_who.dm"
#include "monkestation\code\modules\meteor_shield\meteor_shield_capsule.dm"
#include "monkestation\code\modules\meteor_shield\meteor_shield.dm"
#include "monkestation\code\modules\meteor_shield\meteor_shield_coverage.dm"
#include "monkestation\code\modules\meteor_shield\meteor_shield_field.dm"
#include "monkestation\code\modules\meteor_shield\meteor_shield_zap.dm"
#include "monkestation\code\modules\meteors\meteor_dark_matteor.dm"
#include "monkestation\code\modules\metrics\metric_subsystem.dm"
#include "monkestation\code\modules\metrics\subsystem_analytics\generics.dm"
Expand Down Expand Up @@ -7169,7 +7174,6 @@
#include "monkestation\code\modules\spells\spell_types\aoe_spell\mind_swap.dm"
#include "monkestation\code\modules\spells\spell_types\conjure_item\summon_mjollnir.dm"
#include "monkestation\code\modules\spells\spell_types\pointed\smite.dm"
#include "monkestation\code\modules\station_goals\meteor_shield.dm"
#include "monkestation\code\modules\store\admin\admin_coin_modification.dm"
#include "monkestation\code\modules\store\atm\_atm.dm"
#include "monkestation\code\modules\store\pre_round\_pre_round_store.dm"
Expand Down

0 comments on commit c542501

Please sign in to comment.