Merge pull request #5459 from Neerti/storm_enhancements

Makes Storms Thunderous
This commit is contained in:
Anewbe
2018-08-01 15:52:12 -05:00
committed by GitHub
23 changed files with 180 additions and 6 deletions

View File

@@ -133,7 +133,8 @@ var/list/admin_verbs_fun = list(
/client/proc/roll_dices,
/datum/admins/proc/call_supply_drop,
/datum/admins/proc/call_drop_pod,
/client/proc/smite
/client/proc/smite,
/client/proc/admin_lightning_strike
)
var/list/admin_verbs_spawn = list(

View File

@@ -0,0 +1,115 @@
/client/proc/admin_lightning_strike()
set name = "Lightning Stirke"
set desc = "Causes lightning to strike on your tile. This will hurt things on or nearby it severely."
set category = "Fun"
if(!check_rights(R_FUN))
return
var/result = alert(src, "Really strike your tile with lightning?", "Confirm Badmin" , "No", "Yes (Cosmetic)", "Yes (Real)")
if(result == "No")
return
var/fake_lightning = result == "Yes (Cosmetic)"
lightning_strike(get_turf(usr), fake_lightning)
log_and_message_admins("[key_name(src)] has caused [fake_lightning ? "cosmetic":"harmful"] lightning to strike at their position ([src.mob.x], [src.mob.y], [src.mob.z]). \
(<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.mob.x];Y=[src.mob.y];Z=[src.mob.z]'>JMP</a>)")
#define LIGHTNING_REDIRECT_RANGE 28 // How far in tiles certain things draw lightning from.
#define LIGHTNING_ZAP_RANGE 3 // How far the tesla effect zaps, as well as the bad effects from a direct strike.
#define LIGHTNING_POWER 20000 // How much 'zap' is in a strike, used for tesla_zap().
// The real lightning proc.
// This is global until I can figure out a better place for it.
// T is the turf that is being struck. If cosmetic is true, the lightning won't actually hurt anything.
/proc/lightning_strike(turf/T, cosmetic = FALSE)
// First, visuals.
// Do a lightning flash for the whole planet, if the turf belongs to a planet.
var/datum/planet/P = null
P = SSplanets.z_to_planet[T.z]
if(P)
var/datum/weather_holder/holder = P.weather_holder
flick("lightning_flash", holder.special_visuals)
// Before we do the other visuals, we need to see if something is going to hijack our intended target.
var/obj/machinery/power/grounding_rod/ground = null // Most of the bad effects of lightning will get negated if a grounding rod is nearby.
var/obj/machinery/power/tesla_coil/coil = null // However a tesla coil has higher priority and the strike will bounce.
for(var/obj/machinery/power/thing in range(LIGHTNING_REDIRECT_RANGE, T))
if(istype(thing, /obj/machinery/power/tesla_coil))
var/turf/simulated/coil_turf = get_turf(thing)
if(istype(coil_turf) && thing.anchored && coil_turf.outdoors)
coil = thing
break
if(istype(thing, /obj/machinery/power/grounding_rod))
var/turf/simulated/rod_turf = get_turf(thing)
if(istype(rod_turf) && thing.anchored && rod_turf.outdoors)
ground = thing
if(coil) // Coil gets highest priority.
T = coil.loc
else if(ground)
T = ground.loc
// Now make the lightning strike sprite. It will fade and delete itself in a second.
new /obj/effect/temporary_effect/lightning_strike(T)
// For those close up.
playsound(T, 'sound/effects/lightningbolt.ogg', 100, 1)
// And for those far away. If the strike happens on a planet, everyone on the planet will hear it.
// Otherwise only those on the current z-level will hear it.
var/sound = get_sfx("thunder")
for(var/mob/M in player_list)
if((P && M.z in P.expected_z_levels) || M.z == T.z)
M.playsound_local(get_turf(M), soundin = sound, vol = 70, vary = FALSE, is_global = TRUE)
if(cosmetic) // Everything beyond here involves potentially damaging things. If we don't want to do that, stop now.
return
if(ground) // All is well.
ground.tesla_act(LIGHTNING_POWER, FALSE)
return
else if(coil) // Otherwise lets bounce off the tesla coil.
coil.tesla_act(LIGHTNING_POWER, TRUE)
else // Striking the turf directly.
tesla_zap(T, zap_range = LIGHTNING_ZAP_RANGE, power = LIGHTNING_POWER, explosive = FALSE, stun_mobs = TRUE)
// Some extra effects.
// Some apply to those within zap range, others if they were a bit farther away.
for(var/mob/living/L in view(5, T))
if(get_dist(L, T) <= LIGHTNING_ZAP_RANGE) // They probably got zapped.
// The actual damage/electrocution is handled by tesla_zap().
L.Paralyse(5)
L.stuttering += 20
L.make_jittery(20)
L.emp_act(1)
to_chat(L, span("critical", "You've been struck by lightning!"))
// If a non-player simplemob was struck, inflict huge damage.
// If the damage is fatal, the SA is turned to ash.
if(istype(L, /mob/living/simple_animal) && !L.key)
var/mob/living/simple_animal/SA = L
SA.adjustFireLoss(200)
SA.updatehealth()
if(SA.health <= 0) // Might be best to check/give simple_mobs siemens when this gets ported to new mobs.
SA.visible_message(span("critical", "\The [SA] disintegrates into ash!"))
SA.ash()
continue // No point deafening something that wont exist.
// Deafen them.
if(L.get_ear_protection() < 2)
L.AdjustSleeping(-100)
if(iscarbon(L))
var/mob/living/carbon/C = L
C.ear_deaf += 10
to_chat(L, span("danger", "Lightning struck nearby, and the thunderclap is deafening!"))
#undef GROUNDING_ROD_RANGE
#undef LIGHTNING_ZAP_RANGE
#undef LIGHTNING_POWER

View File

@@ -264,6 +264,9 @@ datum/weather/sif
temp_low = 233.15 // -40c
light_modifier = 0.3
flight_failure_modifier = 10
var/next_lightning_strike = 0 // world.time when lightning will strike.
var/min_lightning_cooldown = 5 SECONDS
var/max_lightning_cooldown = 1 MINUTE
transition_chances = list(
@@ -298,6 +301,17 @@ datum/weather/sif
L.water_act(2)
to_chat(L, "<span class='warning'>Rain falls on you, drenching you in water.</span>")
handle_lightning()
// This gets called to do lightning periodically.
// There is a seperate function to do the actual lightning strike, so that badmins can play with it.
/datum/weather/sif/storm/proc/handle_lightning()
if(world.time < next_lightning_strike)
return // It's too soon to strike again.
next_lightning_strike = world.time + rand(min_lightning_cooldown, max_lightning_cooldown)
var/turf/T = pick(holder.our_planet.planet_floors) // This has the chance to 'strike' the sky, but that might be a good thing, to scare reckless pilots.
lightning_strike(T)
/datum/weather/sif/hail
name = "hail"
icon_state = "hail"

View File

@@ -10,6 +10,7 @@
// Holds the weather icon, using vis_contents. Documentation says an /atom/movable is required for placing inside another atom's vis_contents.
var/atom/movable/weather_visuals/visuals = null
var/atom/movable/weather_visuals/special/special_visuals = null
/datum/weather_holder/New(var/source)
..()
@@ -19,6 +20,7 @@
if(istype(W))
W.holder = src
visuals = new()
special_visuals = new()
/datum/weather_holder/proc/change_weather(var/new_weather)
var/old_light_modifier = null
@@ -87,3 +89,8 @@
icon = 'icons/effects/weather.dmi'
mouse_opacity = 0
plane = PLANE_PLANETLIGHTING
// This is for special effects for specific types of weather, such as lightning flashes in a storm.
// It's a seperate object to allow the use of flick().
/atom/movable/weather_visuals/special
plane = PLANE_LIGHTING_ABOVE

View File

@@ -18,6 +18,9 @@
var/last_zap = 0
var/datum/wires/tesla_coil/wires = null
/obj/machinery/power/tesla_coil/pre_mapped
anchored = TRUE
/obj/machinery/power/tesla_coil/New()
..()
wires = new(src)
@@ -103,6 +106,9 @@
can_buckle = TRUE
buckle_lying = FALSE
/obj/machinery/power/grounding_rod/pre_mapped
anchored = TRUE
/obj/machinery/power/grounding_rod/update_icon()
if(panel_open)
icon_state = "grounding_rod_open[anchored]"

View File

@@ -45,7 +45,10 @@
/obj/machinery/light/tesla_act(power, explosive = FALSE)
if(explosive)
explosion(loc, 0, 0, 0/*, flame_range = 5*/, adminlog = FALSE)
qdel(src)
qdel(src)
return
on = TRUE
broken()
/obj/structure/closet/tesla_act(var/power)
..() //extend the zap