diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index 13e7501bb1..d7db6f2a0c 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -61,5 +61,6 @@ pixel_x = -32 /obj/effect/temporary_effect/lightning_strike/initialize() - icon_state += rand(1,2) // To have two variants of lightning sprites. + icon_state += "[rand(1,2)]" // To have two variants of lightning sprites. + animate(src, alpha = 0, time = time_to_die - 1) . = ..() \ No newline at end of file diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index 5b3a74ad03..8b7f5bf042 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -52,12 +52,12 @@ animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING) // Used when the tree gets hurt. -/obj/structure/flora/tree/proc/adjust_health(var/amount, var/is_ranged = FALSE) +/obj/structure/flora/tree/proc/adjust_health(var/amount, var/damage_wood = FALSE) if(is_stump) return // Bullets and lasers ruin some of the wood - if(is_ranged && product_amount > 0) + if(damage_wood && product_amount > 0) var/wood = initial(product_amount) product_amount -= round(wood * (abs(amount)/max_health)) @@ -90,12 +90,16 @@ set_light(0) /obj/structure/flora/tree/ex_act(var/severity) - adjust_health(-(max_health / severity)) + adjust_health(-(max_health / severity), TRUE) /obj/structure/flora/tree/bullet_act(var/obj/item/projectile/Proj) if(Proj.get_structure_damage()) adjust_health(-Proj.get_structure_damage(), TRUE) +/obj/structure/flora/tree/tesla_act(power, explosive) + adjust_health(-power / 100, TRUE) // Kills most trees in one lightning strike. + ..() + /obj/structure/flora/tree/get_description_interaction() var/list/results = list() diff --git a/code/game/sound.dm b/code/game/sound.dm index 2db1e433bd..8e206300a8 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -130,6 +130,9 @@ if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') if ("geiger") soundin = pick('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') if ("geiger_weak") soundin = pick('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') + if ("thunder") soundin = pick('sound/effects/thunder/thunder1.ogg', 'sound/effects/thunder/thunder2.ogg', 'sound/effects/thunder/thunder3.ogg', 'sound/effects/thunder/thunder4.ogg', + 'sound/effects/thunder/thunder5.ogg', 'sound/effects/thunder/thunder6.ogg', 'sound/effects/thunder/thunder7.ogg', 'sound/effects/thunder/thunder8.ogg', 'sound/effects/thunder/thunder9.ogg', + 'sound/effects/thunder/thunder10.ogg') return soundin //Are these even used? diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index dfbd142908..56a440b639 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -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( diff --git a/code/modules/admin/verbs/lightning_strike.dm b/code/modules/admin/verbs/lightning_strike.dm new file mode 100644 index 0000000000..688652e3a7 --- /dev/null +++ b/code/modules/admin/verbs/lightning_strike.dm @@ -0,0 +1,112 @@ +/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 + + lightning_strike(get_turf(usr), result == "Yes (Cosmetic)") + +#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 \ No newline at end of file diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index 250a688ec8..3491fac2db 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -312,32 +312,6 @@ datum/weather/sif 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) -// 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) - world << "Going to strike turf [T] ([T.x],[T.y],[T.z])." - // 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) - world << "Planet [P] ([P.name]) is hopefully not null." - var/datum/weather_holder/holder = P.weather_holder - world << "Weather holder is hopefully not null." - flick("lightning_flash", holder.special_visuals) - - // Now make the lightning strike sprite. It will delete itself in a second. - new /obj/effect/temporary_effect/lightning_strike(T) - - // Todo: Thunder. - - if(cosmetic) // Everything beyond here involves damaging things. If we don't want to do that, stop now. - return - -// Test verb -/mob/verb/test_lightning() - lightning_strike(get_turf(src)) - /datum/weather/sif/hail name = "hail" icon_state = "hail" diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm index 55ddfbee2a..c3939956c5 100644 --- a/code/modules/planet/weather.dm +++ b/code/modules/planet/weather.dm @@ -93,5 +93,4 @@ // 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 - alpha = 127 \ No newline at end of file + plane = PLANE_LIGHTING_ABOVE \ No newline at end of file diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 07dedf5b2b..82e84718cf 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -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]" diff --git a/code/modules/power/tesla/tesla_act.dm b/code/modules/power/tesla/tesla_act.dm index 8e3f1c6996..605c9e3021 100644 --- a/code/modules/power/tesla/tesla_act.dm +++ b/code/modules/power/tesla/tesla_act.dm @@ -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 diff --git a/icons/effects/weather.dmi b/icons/effects/weather.dmi index b6b38c55cd..5ae794c898 100644 Binary files a/icons/effects/weather.dmi and b/icons/effects/weather.dmi differ diff --git a/polaris.dme b/polaris.dme index 587300118e..d24cfc7d9b 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1243,6 +1243,7 @@ #include "code\modules\admin\verbs\dice.dm" #include "code\modules\admin\verbs\getlogs.dm" #include "code\modules\admin\verbs\grief_fixers.dm" +#include "code\modules\admin\verbs\lightning_strike.dm" #include "code\modules\admin\verbs\map_template_loadverb.dm" #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" diff --git a/sound/effects/thunder/thunder1.ogg b/sound/effects/thunder/thunder1.ogg new file mode 100644 index 0000000000..7ec34e88e8 Binary files /dev/null and b/sound/effects/thunder/thunder1.ogg differ diff --git a/sound/effects/thunder/thunder10.ogg b/sound/effects/thunder/thunder10.ogg new file mode 100644 index 0000000000..43aefb098f Binary files /dev/null and b/sound/effects/thunder/thunder10.ogg differ diff --git a/sound/effects/thunder/thunder2.ogg b/sound/effects/thunder/thunder2.ogg new file mode 100644 index 0000000000..bc2f581dda Binary files /dev/null and b/sound/effects/thunder/thunder2.ogg differ diff --git a/sound/effects/thunder/thunder3.ogg b/sound/effects/thunder/thunder3.ogg new file mode 100644 index 0000000000..0df287aa78 Binary files /dev/null and b/sound/effects/thunder/thunder3.ogg differ diff --git a/sound/effects/thunder/thunder4.ogg b/sound/effects/thunder/thunder4.ogg new file mode 100644 index 0000000000..6c671b8010 Binary files /dev/null and b/sound/effects/thunder/thunder4.ogg differ diff --git a/sound/effects/thunder/thunder5.ogg b/sound/effects/thunder/thunder5.ogg new file mode 100644 index 0000000000..3d5187a716 Binary files /dev/null and b/sound/effects/thunder/thunder5.ogg differ diff --git a/sound/effects/thunder/thunder6.ogg b/sound/effects/thunder/thunder6.ogg new file mode 100644 index 0000000000..65aef886ff Binary files /dev/null and b/sound/effects/thunder/thunder6.ogg differ diff --git a/sound/effects/thunder/thunder7.ogg b/sound/effects/thunder/thunder7.ogg new file mode 100644 index 0000000000..b72848a2b6 Binary files /dev/null and b/sound/effects/thunder/thunder7.ogg differ diff --git a/sound/effects/thunder/thunder8.ogg b/sound/effects/thunder/thunder8.ogg new file mode 100644 index 0000000000..a25fe21e32 Binary files /dev/null and b/sound/effects/thunder/thunder8.ogg differ diff --git a/sound/effects/thunder/thunder9.ogg b/sound/effects/thunder/thunder9.ogg new file mode 100644 index 0000000000..9ebc1045bf Binary files /dev/null and b/sound/effects/thunder/thunder9.ogg differ