Adds several new map/event oriented objects (#5757)

* Adds some helpful effects to enhance PoI construction.

* Adds several features for mappers.

* Test map please go
This commit is contained in:
Neerti
2018-12-07 18:48:09 -05:00
committed by Anewbe
parent 5e2d8bbdee
commit 452fd9afb8
15 changed files with 686 additions and 11 deletions

View File

@@ -59,6 +59,10 @@
return ..()
/datum/beam/proc/Draw()
if(QDELETED(target) || !QDELETED(origin))
qdel(src)
return
var/Angle = round(Get_Angle(origin,target))
var/matrix/rot_matrix = matrix()
@@ -113,6 +117,8 @@
X.pixel_x = Pixel_x
X.pixel_y = Pixel_y
X.on_drawn()
/obj/effect/ebeam
mouse_opacity = 0
anchored = TRUE
@@ -127,10 +133,53 @@
/obj/effect/ebeam/singularity_act()
return
// Called when the beam datum finishes drawing and the ebeam object is placed correctly.
/obj/effect/ebeam/proc/on_drawn()
return
/obj/effect/ebeam/deadly/Crossed(atom/A)
..()
A.ex_act(1)
// 'Reactive' beam parts do something when touched or stood in.
/obj/effect/ebeam/reactive
/obj/effect/ebeam/reactive/initialize()
processing_objects += src
return ..()
/obj/effect/ebeam/reactive/Destroy()
processing_objects -= src
return ..()
/obj/effect/ebeam/reactive/on_drawn()
for(var/A in loc)
on_contact(A)
/obj/effect/ebeam/reactive/Crossed(atom/A)
..()
on_contact(A)
/obj/effect/ebeam/reactive/process()
for(var/A in loc)
on_contact(A)
// Override for things to do when someone touches the beam.
/obj/effect/ebeam/reactive/proc/on_contact(atom/movable/AM)
return
// Shocks things that touch it.
/obj/effect/ebeam/reactive/electric
var/shock_amount = 25 // Be aware that high numbers may stun and result in dying due to not being able to get out of the beam.
/obj/effect/ebeam/reactive/electric/on_contact(atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
L.inflict_shock_damage(shock_amount)
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
spawn(0)

View File

@@ -225,15 +225,16 @@ steam.start() -- spawns the effect
/obj/effect/effect/smoke/bad/Move()
..()
for(var/mob/living/carbon/M in get_turf(src))
affect(M)
for(var/mob/living/L in get_turf(src))
affect(L)
/obj/effect/effect/smoke/bad/affect(var/mob/living/carbon/M)
/obj/effect/effect/smoke/bad/affect(var/mob/living/L)
if (!..())
return 0
M.adjustOxyLoss(1)
if(prob(25))
M.emote("cough")
if(L.needs_to_breathe())
L.adjustOxyLoss(1)
if(prob(25))
L.emote("cough")
/* Not feasile until a later date
/obj/effect/effect/smoke/bad/Crossed(atom/movable/M as mob|obj)
@@ -251,6 +252,72 @@ steam.start() -- spawns the effect
projectiles -= proj
*/
/////////////////////////////////////////////
// 'Elemental' smoke
/////////////////////////////////////////////
/obj/effect/effect/smoke/elemental
name = "cloud"
desc = "A cloud of some kind that seems really generic and boring."
opacity = FALSE
var/strength = 5 // How much damage to do inside each affect()
/obj/effect/effect/smoke/elemental/initialize()
processing_objects += src
return ..()
/obj/effect/effect/smoke/elemental/Destroy()
processing_objects -= src
return ..()
/obj/effect/effect/smoke/elemental/Move()
..()
for(var/mob/living/L in range(1, src))
affect(L)
/obj/effect/effect/smoke/elemental/process()
for(var/mob/living/L in range(1, src))
affect(L)
/obj/effect/effect/smoke/elemental/fire
name = "burning cloud"
desc = "A cloud of something that is on fire."
color = "#FF9933"
light_color = "#FF0000"
light_range = 2
light_power = 5
/obj/effect/effect/smoke/elemental/fire/affect(mob/living/L)
L.inflict_heat_damage(strength)
L.add_modifier(/datum/modifier/fire, 6 SECONDS) // Around 15 damage per stack.
/obj/effect/effect/smoke/elemental/frost
name = "freezing cloud"
desc = "A cloud filled with brutally cold mist."
color = "#00CCFF"
/obj/effect/effect/smoke/elemental/frost/affect(mob/living/L)
L.inflict_cold_damage(strength)
/obj/effect/effect/smoke/elemental/shock
name = "charged cloud"
desc = "A cloud charged with electricity."
color = "#4D4D4D"
/obj/effect/effect/smoke/elemental/shock/affect(mob/living/L)
L.inflict_shock_damage(strength)
/obj/effect/effect/smoke/elemental/mist
name = "misty cloud"
desc = "A cloud filled with water vapor."
color = "#CCFFFF"
alpha = 128
strength = 1
/obj/effect/effect/smoke/elemental/mist/affect(mob/living/L)
L.water_act(strength)
/////////////////////////////////////////////
// Smoke spread
/////////////////////////////////////////////
@@ -282,7 +349,8 @@ steam.start() -- spawns the effect
src.location = get_turf(holder)
var/obj/effect/effect/smoke/smoke = new smoke_type(src.location)
src.total_smoke++
smoke.color = I
if(I)
smoke.color = I
var/direction = src.direction
if(!direction)
if(src.cardinals)
@@ -296,10 +364,21 @@ steam.start() -- spawns the effect
if (smoke) qdel(smoke)
src.total_smoke--
/datum/effect/effect/system/smoke_spread/bad
smoke_type = /obj/effect/effect/smoke/bad
/datum/effect/effect/system/smoke_spread/fire
smoke_type = /obj/effect/effect/smoke/elemental/fire
/datum/effect/effect/system/smoke_spread/frost
smoke_type = /obj/effect/effect/smoke/elemental/frost
/datum/effect/effect/system/smoke_spread/shock
smoke_type = /obj/effect/effect/smoke/elemental/shock
/datum/effect/effect/system/smoke_spread/mist
smoke_type = /obj/effect/effect/smoke/elemental/mist
/////////////////////////////////////////////
//////// Attach an Ion trail to any object, that spawns when it moves (like for the jetpack)
/// just pass in the object to attach it to in set_up

View File

@@ -0,0 +1,192 @@
GLOBAL_LIST_EMPTY(all_beam_points)
// Creates and manages a beam attached to itself and another beam_point.
// You can do cool things with these such as moving the beam_point to move the beam, turning them on and off on a timer, triggered by external input, and more.
/obj/effect/map_effect/beam_point
name = "beam point"
icon_state = "beam_point"
// General variables.
var/list/my_beams = list() // Instances of beams. Deleting one will kill the beam.
var/id = "A" // Two beam_points must share the same ID to be connected to each other.
var/max_beams = 10 // How many concurrent beams to seperate beam_points to have at once. Set to zero to only act as targets for other beam_points.
var/seek_range = 7 // How far to look for an end beam_point when not having a beam. Defaults to screen height/width. Make sure this is below beam_max_distance.
// Controls how and when the beam is created.
var/make_beams_on_init = FALSE
var/use_timer = FALSE // Sadly not the /tg/ timers.
var/list/on_duration = list(2 SECONDS, 2 SECONDS, 2 SECONDS) // How long the beam should stay on for, if use_timer is true. Alternates between each duration in the list.
var/list/off_duration = list(3 SECONDS, 0.5 SECOND, 0.5 SECOND) // How long it should stay off for. List length is not needed to be the same as on_duration.
var/timer_on_index = 1 // Index to use for on_duration list.
var/timer_off_index = 1// Ditto, for off_duration list.
var/initial_delay = 0 // How long to wait before first turning on the beam, to sync beam times or create a specific pattern.
var/beam_creation_sound = null // Optional sound played when one or more beams are created.
var/beam_destruction_sound = null // Optional sound played when a beam is destroyed.
// Beam datum arguments.
var/beam_icon = 'icons/effects/beam.dmi' // Icon file to use for beam visuals.
var/beam_icon_state = "b_beam" // Icon state to use for visuals.
var/beam_time = INFINITY // How long the beam lasts. By default it will last forever until destroyed.
var/beam_max_distance = 10 // If the beam is farther than this, it will be destroyed. Make sure it's higher than seek_range.
var/beam_type = /obj/effect/ebeam // The type of beam. Default has no special properties. Some others may do things like hurt things touching it.
var/beam_sleep_time = 3 // How often the beam updates visually. Suggested to leave this alone, 3 is already fast.
/obj/effect/map_effect/beam_point/initialize()
GLOB.all_beam_points += src
if(make_beams_on_init)
create_beams()
if(use_timer)
spawn(initial_delay)
handle_beam_timer()
return ..()
/obj/effect/map_effect/beam_point/Destroy()
destroy_all_beams()
use_timer = FALSE
GLOB.all_beam_points -= src
return ..()
// This is the top level proc to make the magic happen.
/obj/effect/map_effect/beam_point/proc/create_beams()
if(my_beams.len >= max_beams)
return
var/beams_to_fill = max_beams - my_beams.len
for(var/i = 1 to beams_to_fill)
var/obj/effect/map_effect/beam_point/point = seek_beam_point()
if(!point)
break // No more points could be found, no point checking repeatively.
build_beam(point)
// Finds a suitable beam point.
/obj/effect/map_effect/beam_point/proc/seek_beam_point()
for(var/obj/effect/map_effect/beam_point/point in GLOB.all_beam_points)
if(id != point.id)
continue // Not linked together by ID.
if(has_active_beam(point))
continue // Already got one.
if(point.z != src.z)
continue // Not on same z-level. get_dist() ignores z-levels by design according to docs.
if(get_dist(src, point) > seek_range)
continue // Too far.
return point
// Checks if the two points have an active beam between them.
// Used to make sure two points don't have more than one beam.
/obj/effect/map_effect/beam_point/proc/has_active_beam(var/obj/effect/map_effect/beam_point/them)
// First, check our beams.
for(var/datum/beam/B in my_beams)
if(B.target == them)
return TRUE
if(B.origin == them) // This shouldn't be needed unless the beam gets built backwards but why not.
return TRUE
// Now check theirs, to see if they have a beam on us.
for(var/datum/beam/B in them.my_beams)
if(B.target == src)
return TRUE
if(B.origin == src) // Same story as above.
return TRUE
return FALSE
/obj/effect/map_effect/beam_point/proc/build_beam(var/atom/beam_target)
if(!beam_target)
log_debug("[src] ([src.type] \[[x],[y],[z]\]) failed to build its beam due to not having a target.")
return FALSE
var/datum/beam/new_beam = Beam(beam_target, beam_icon_state, beam_icon, beam_time, beam_max_distance, beam_type, beam_sleep_time)
my_beams += new_beam
if(beam_creation_sound)
playsound(src, beam_creation_sound, 70, 1)
return TRUE
/obj/effect/map_effect/beam_point/proc/destroy_beam(var/datum/beam/B)
if(!B)
log_debug("[src] ([src.type] \[[x],[y],[z]\]) was asked to destroy a beam that does not exist.")
return FALSE
if(!(B in my_beams))
log_debug("[src] ([src.type] \[[x],[y],[z]\]) was asked to destroy a beam it did not own.")
return FALSE
my_beams -= B
qdel(B)
if(beam_destruction_sound)
playsound(src, beam_destruction_sound, 70, 1)
return TRUE
/obj/effect/map_effect/beam_point/proc/destroy_all_beams()
for(var/datum/beam/B in my_beams)
destroy_beam(B)
return TRUE
// This code makes me sad.
/obj/effect/map_effect/beam_point/proc/handle_beam_timer()
if(!use_timer || QDELETED(src))
return
if(my_beams.len) // Currently on.
destroy_all_beams()
color = "#FF0000"
timer_off_index++
if(timer_off_index > off_duration.len)
timer_off_index = 1
spawn(off_duration[timer_off_index])
.()
else // Currently off.
// If nobody's around, keep the beams off to avoid wasteful beam process(), if they have one.
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
spawn(retry_delay)
.()
return
create_beams()
color = "#00FF00"
timer_on_index++
if(timer_on_index > on_duration.len)
timer_on_index = 1
spawn(on_duration[timer_on_index])
.()
// Subtypes to use in maps and adminbuse.
// Remember, beam_points ONLY connect to other beam_points with the same id variable.
// Creates the beam when instantiated and stays on until told otherwise.
/obj/effect/map_effect/beam_point/instant
make_beams_on_init = TRUE
/obj/effect/map_effect/beam_point/instant/electric
beam_icon_state = "nzcrentrs_power"
beam_type = /obj/effect/ebeam/reactive/electric
beam_creation_sound = 'sound/effects/lightningshock.ogg'
beam_destruction_sound = "sparks"
// Turns on and off on a timer.
/obj/effect/map_effect/beam_point/timer
use_timer = TRUE
// Shocks people who touch the beam while it's on. Flicks on and off on a specific pattern.
/obj/effect/map_effect/beam_point/timer/electric
beam_icon_state = "nzcrentrs_power"
beam_type = /obj/effect/ebeam/reactive/electric
beam_creation_sound = 'sound/effects/lightningshock.ogg'
beam_destruction_sound = "sparks"
seek_range = 3
// Is only a target for other beams to connect to.
/obj/effect/map_effect/beam_point/end
max_beams = 0
// Can only have one beam.
/obj/effect/map_effect/beam_point/mono
make_beams_on_init = TRUE
max_beams = 1

View File

@@ -0,0 +1,78 @@
// Creates effects like smoke clouds every so often.
/obj/effect/map_effect/interval/effect_emitter
var/datum/effect/effect/system/effect_system = null
var/effect_system_type = null // Which effect system to attach.
var/effect_amount = 10 // How many effect objects to create on each interval. Note that there's a hard cap on certain effect_systems.
var/effect_cardinals_only = FALSE // If true, effects only move in cardinal directions.
var/effect_forced_dir = null // If set, effects emitted will always move in this direction.
/obj/effect/map_effect/interval/effect_emitter/initialize()
effect_system = new effect_system_type()
effect_system.attach(src)
configure_effects()
return ..()
/obj/effect/map_effect/interval/effect_emitter/interval/Destroy()
QDEL_NULL(effect_system)
return ..()
/obj/effect/map_effect/interval/effect_emitter/proc/configure_effects()
effect_system.set_up(effect_amount, effect_cardinals_only, usr.loc, effect_forced_dir)
/obj/effect/map_effect/interval/effect_emitter/trigger()
configure_effects() // We do this every interval in case it changes.
effect_system.start()
..()
// Creates smoke clouds every so often.
/obj/effect/map_effect/interval/effect_emitter/smoke
name = "smoke emitter"
icon_state = "smoke_emitter"
effect_system_type = /datum/effect/effect/system/smoke_spread
interval_lower_bound = 1 SECOND
interval_upper_bound = 1 SECOND
effect_amount = 2
/obj/effect/map_effect/interval/effect_emitter/smoke/bad
name = "bad smoke emitter"
effect_system_type = /datum/effect/effect/system/smoke_spread/bad
/obj/effect/map_effect/interval/effect_emitter/smoke/fire
name = "fire smoke emitter"
effect_system_type = /datum/effect/effect/system/smoke_spread/fire
/obj/effect/map_effect/interval/effect_emitter/smoke/frost
name = "frost smoke emitter"
effect_system_type = /datum/effect/effect/system/smoke_spread/frost
/obj/effect/map_effect/interval/effect_emitter/smoke/shock
name = "shock smoke emitter"
effect_system_type = /datum/effect/effect/system/smoke_spread/shock
/obj/effect/map_effect/interval/effect_emitter/smoke/mist
name = "mist smoke emitter"
effect_system_type = /datum/effect/effect/system/smoke_spread/mist
// Makes sparks.
/obj/effect/map_effect/interval/effect_emitter/sparks
name = "spark emitter"
icon_state = "spark_emitter"
effect_system_type = /datum/effect/effect/system/spark_spread
interval_lower_bound = 3 SECONDS
interval_upper_bound = 7 SECONDS
/obj/effect/map_effect/interval/effect_emitter/sparks/frequent
effect_amount = 4 // Otherwise it caps out fast.
interval_lower_bound = 1
interval_upper_bound = 3 SECONDS
// Makes ""steam"" that looks like fire extinguisher water except it does nothing.
/obj/effect/map_effect/interval/effect_emitter/steam
name = "steam emitter"
icon_state = "smoke_emitter"
effect_system_type = /datum/effect/effect/system/steam_spread

View File

@@ -0,0 +1,71 @@
// These are objects you can use inside special maps (like PoIs), or for adminbuse.
// Players cannot see or interact with these.
/obj/effect/map_effect
anchored = TRUE
invisibility = 99 // So a badmin can go view these by changing their see_invisible.
icon = 'icons/effects/map_effects.dmi'
// Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects.
var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it.
var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run.
var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement.
var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well.
var/retry_delay = 3 SECONDS // How long until we check for players again.
/obj/effect/map_effect/ex_act()
return
/obj/effect/map_effect/singularity_pull()
return
/obj/effect/map_effect/singularity_act()
return
// Base type for effects that run on variable intervals.
/obj/effect/map_effect/interval
var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger.
var/interval_upper_bound = 5 SECONDS // Higher number for above.
var/halt = FALSE // Set to true to stop the loop when it reaches the next iteration.
/obj/effect/map_effect/interval/initialize()
handle_interval_delay()
return ..()
/obj/effect/map_effect/interval/Destroy()
halt = TRUE // Shouldn't need it to GC but just in case.
return ..()
// Override this for the specific thing to do. Be sure to call parent to keep looping.
/obj/effect/map_effect/interval/proc/trigger()
handle_interval_delay()
// Handles the delay and making sure it doesn't run when it would be bad.
/obj/effect/map_effect/interval/proc/handle_interval_delay()
// Check to see if we're useful first.
if(halt)
return // Do not pass .(), do not recursively collect 200 thaler.
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
spawn(retry_delay) // Maybe someday we'll have fancy TG timers/schedulers.
if(!QDELETED(src))
.()
var/next_interval = rand(interval_lower_bound, interval_upper_bound)
spawn(next_interval)
if(!QDELETED(src))
trigger()
// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it.
/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE)
if(!proximity_to)
return FALSE
for(var/thing in player_list)
var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways.
if(ignore_ghosts && isobserver(M))
continue
if(ignore_afk && M.client && M.client.is_afk(5 MINUTES))
continue
if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius)
return TRUE
return FALSE

View File

@@ -0,0 +1,9 @@
// Emits light forever with magic. Useful for mood lighting in Points of Interest.
// Be sure to check how it looks ingame, and fiddle with the settings until it looks right.
/obj/effect/map_effect/perma_light
name = "permanent light"
icon_state = "permalight"
light_range = 3
light_power = 1
light_color = "#FFFFFF"

View File

@@ -0,0 +1,19 @@
// Constantly emites radiation from the tile it's placed on.
/obj/effect/map_effect/radiation_emitter
name = "radiation emitter"
icon_state = "radiation_emitter"
var/radiation_power = 30 // Bigger numbers means more radiation.
/obj/effect/map_effect/radiation_emitter/initialize()
processing_objects += src
return ..()
/obj/effect/map_effect/radiation_emitter/Destroy()
processing_objects -= src
return ..()
/obj/effect/map_effect/radiation_emitter/process()
radiation_repository.radiate(src, radiation_power)
/obj/effect/map_effect/radiation_emitter/strong
radiation_power = 100

View File

@@ -0,0 +1,18 @@
// Makes the screen shake for nearby players every so often.
/obj/effect/map_effect/interval/screen_shaker
name = "screen shaker"
icon_state = "screen_shaker"
interval_lower_bound = 1 SECOND
interval_upper_bound = 2 SECONDS
var/shake_radius = 7 // How far the shaking effect extends to. By default it is one screen length.
var/shake_duration = 2 // How long the shaking lasts.
var/shake_strength = 1 // How much it shakes.
/obj/effect/map_effect/interval/screen_shaker/trigger()
for(var/A in player_list)
var/mob/M = A
if(M.z == src.z && get_dist(src, M) <= shake_radius)
shake_camera(M, shake_duration, shake_strength)
..()

View File

@@ -0,0 +1,117 @@
// Plays a sound at its location every so often.
/obj/effect/map_effect/interval/sound_emitter
name = "sound emitter"
icon_state = "sound_emitter"
var/list/sounds_to_play = list(null) // List containing sound files or strings of sound groups.
// A sound or string is picked randomly each run.
var/sound_volume = 50 // How loud the sound is. 0 is silent, and 100 is loudest. Please be reasonable with the volume.
// Note that things like vacuum may affect the volume heard by other mobs.
var/sound_frequency_variance = TRUE // If the sound will sound somewhat different each time.
// If a specific frequency is desired, sound_frequency must also be set.
var/sound_extra_range = 0 // Set to make sounds heard from farther away than normal.
var/sound_fallout = 0 // Within the 'fallout distance', the sound stays at the same volume, otherwise it attenuates.
// Higher numbers make the sound fade out more slowly with distance.
var/sound_global = FALSE // If true, sounds will not be distorted due to the current area's 'sound environment'.
// It DOES NOT make the sound have a constant volume or z-level wide range, despite the misleading name.
var/sound_frequency = null // Sets a specific custom frequency. sound_frequency_variance must be true as well.
// If sound_frequency is null, but sound_frequency_variance is true, a semi-random frequency will be chosen to the sound each time.
var/sound_channel = 0 // BYOND allows a sound to play in 1 through 1024 sound channels.
// 0 will have BYOND give it the lowest available channel, it is not recommended to change this without a good reason.
var/sound_pressure_affected = TRUE // If false, people in low pressure or vacuum will hear the sound.
var/sound_ignore_walls = TRUE // If false, walls will completely muffle the sound.
var/sound_preference = null // Player preference to check before playing this sound to them, if any.
/obj/effect/map_effect/interval/sound_emitter/trigger()
playsound(
src,
pick(sounds_to_play),
sound_volume,
sound_frequency_variance,
sound_extra_range,
sound_fallout,
sound_global,
sound_frequency,
sound_channel,
sound_pressure_affected,
sound_ignore_walls,
sound_preference
)
..()
/obj/effect/map_effect/interval/sound_emitter/thunder
sounds_to_play = list("thunder")
interval_lower_bound = 10 SECONDS
interval_upper_bound = 15 SECONDS
/obj/effect/map_effect/interval/sound_emitter/geiger
sounds_to_play = list("geiger")
interval_lower_bound = 2 SECONDS
interval_upper_bound = 2 SECONDS
/obj/effect/map_effect/interval/sound_emitter/geiger_weak
sounds_to_play = list("geiger_weak")
interval_lower_bound = 1 SECOND
interval_upper_bound = 1 SECOND
/obj/effect/map_effect/interval/sound_emitter/punching
sounds_to_play = list("punch")
interval_lower_bound = 5
interval_upper_bound = 1 SECOND
/obj/effect/map_effect/interval/sound_emitter/explosions
sounds_to_play = list("explosion")
interval_lower_bound = 5 SECONDS
interval_upper_bound = 10 SECONDS
/obj/effect/map_effect/interval/sound_emitter/distant_explosions
sounds_to_play = list('sound/effects/explosionfar.ogg')
interval_lower_bound = 5 SECONDS
interval_upper_bound = 10 SECONDS
/obj/effect/map_effect/interval/sound_emitter/ballistic_gunfight
sounds_to_play = list(
'sound/weapons/gunshot.ogg',
'sound/weapons/deagle.ogg',
'sound/weapons/rifleshot.ogg',
'sound/weapons/sniper.ogg',
'sound/weapons/shotgun.ogg',
'sound/weapons/gunshot3.ogg',
'sound/weapons/machinegun.ogg'
)
interval_lower_bound = 5
interval_upper_bound = 2 SECONDS
/obj/effect/map_effect/interval/sound_emitter/energy_gunfight
sounds_to_play = list(
'sound/weapons/Taser.ogg',
'sound/weapons/laser.ogg',
'sound/weapons/eLuger.ogg',
'sound/weapons/laser3.ogg',
'sound/weapons/pulse.ogg',
'sound/weapons/gauss_shoot.ogg',
'sound/weapons/emitter.ogg'
)
interval_lower_bound = 5
interval_upper_bound = 2 SECONDS
// I'm not sorry.
/obj/effect/map_effect/interval/sound_emitter/clownsteps
sounds_to_play = list("clownstep")
interval_lower_bound = 5
interval_upper_bound = 1 SECOND
/obj/effect/map_effect/interval/sound_emitter/bikehorns
sounds_to_play = list('sound/items/bikehorn.ogg')
interval_lower_bound = 5
interval_upper_bound = 1 SECOND

View File

@@ -387,3 +387,8 @@
if(isSynthetic())
return 0
return !(species.flags & NO_PAIN)
/mob/living/carbon/needs_to_breathe()
if(does_not_breathe)
return FALSE
return ..()

View File

@@ -529,7 +529,7 @@ default behaviour is:
// and one for electricity because why not
/mob/living/proc/inflict_shock_damage(amount)
electrocute_act(amount, null, 1 - get_shock_protection())
electrocute_act(amount, null, 1 - get_shock_protection(), pick(BP_HEAD, BP_TORSO, BP_GROIN))
// also one for water (most things resist it entirely, except for slimes)
/mob/living/proc/inflict_water_damage(amount)
@@ -1270,4 +1270,7 @@ default behaviour is:
/mob/living/proc/dirties_floor() // If we ever decide to add fancy conditionals for making dirty floors (floating, etc), here's the proc.
return makes_dirt
return makes_dirt
/mob/living/proc/needs_to_breathe()
return !isSynthetic()

View File

@@ -176,6 +176,11 @@
var/rigged = 0 // true if rigged to explode
var/auto_flicker = FALSE // If true, will constantly flicker, so long as someone is around to see it (otherwise its a waste of CPU).
/obj/machinery/light/flicker
auto_flicker = TRUE
// the smaller bulb light fixture
/obj/machinery/light/small
@@ -187,6 +192,9 @@
desc = "A small lighting fixture."
light_type = /obj/item/weapon/light/bulb
/obj/machinery/light/small/flicker
auto_flicker = TRUE
/obj/machinery/light/flamp
icon_state = "flamp1"
base_state = "flamp"
@@ -199,10 +207,18 @@
light_type = /obj/item/weapon/light/bulb
var/lamp_shade = 1
/obj/machinery/light/flamp/flicker
auto_flicker = TRUE
/obj/machinery/light/small/emergency
brightness_range = 4
brightness_color = "#da0205"
/obj/machinery/light/small/emergency/flicker
auto_flicker = TRUE
/obj/machinery/light/spot
name = "spotlight"
fitting = "large tube"
@@ -210,6 +226,10 @@
brightness_range = 12
brightness_power = 0.9
/obj/machinery/light/spot/flicker
auto_flicker = TRUE
/obj/machinery/light/built/New()
status = LIGHT_EMPTY
update(0)
@@ -292,7 +312,8 @@
update_icon()
if(on)
if(light_range != brightness_range || light_power != brightness_power || light_color != brightness_color)
switchcount++
if(!auto_flicker)
switchcount++
if(rigged)
if(status == LIGHT_OK && trigger)
@@ -675,6 +696,13 @@
if(on)
use_power(light_range * LIGHTING_POWER_FACTOR, LIGHT)
if(auto_flicker && !flickering)
if(check_for_player_proximity(src, radius = 12, ignore_ghosts = FALSE, ignore_afk = TRUE))
seton(TRUE) // Lights must be on to flicker.
flicker(5)
else
seton(FALSE) // Otherwise keep it dark and spooky for when someone shows up.
// called when area power state changes
/obj/machinery/light/power_change()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 KiB

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -833,6 +833,13 @@
#include "code\game\objects\effects\decals\Cleanable\tracks.dm"
#include "code\game\objects\effects\decals\posters\bs12.dm"
#include "code\game\objects\effects\decals\posters\polarisposters.dm"
#include "code\game\objects\effects\map_effects\beam_point.dm"
#include "code\game\objects\effects\map_effects\effect_emitter.dm"
#include "code\game\objects\effects\map_effects\map_effects.dm"
#include "code\game\objects\effects\map_effects\perma_light.dm"
#include "code\game\objects\effects\map_effects\radiation_emitter.dm"
#include "code\game\objects\effects\map_effects\screen_shaker.dm"
#include "code\game\objects\effects\map_effects\sound_emitter.dm"
#include "code\game\objects\effects\spawners\bombspawner.dm"
#include "code\game\objects\effects\spawners\gibspawner.dm"
#include "code\game\objects\effects\temporary_visuals\miscellaneous.dm"