diff --git a/code/datums/spells/lightning.dm b/code/datums/spells/lightning.dm index 7dc5189f21c..233016531cc 100644 --- a/code/datums/spells/lightning.dm +++ b/code/datums/spells/lightning.dm @@ -55,13 +55,13 @@ return playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, 1) - user.Beam(target,icon_state="lightning",icon='icons/effects/effects.dmi',time=5) + user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) Bolt(user,target,30,5,user) Reset(user) /obj/effect/proc_holder/spell/targeted/lightning/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces,mob/user = usr) - origin.Beam(target,icon_state="lightning",icon='icons/effects/effects.dmi',time=5) + origin.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) var/mob/living/carbon/current = target if(bounces < 1) current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1) diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm index baabea8b204..6f32e5c427c 100644 --- a/code/game/gamemodes/gang/dominator.dm +++ b/code/game/gamemodes/gang/dominator.dm @@ -12,6 +12,9 @@ var/operating = 0 //-1=broken, 0=standby, 1=takeover var/warned = 0 //if this device has set off the warning at <3 minutes yet +/obj/machinery/dominator/tesla_act() + qdel(src) + /obj/machinery/dominator/New() ..() SetLuminosity(2) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 2d7a67686d8..cf797fe1efb 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -434,6 +434,22 @@ to destroy them and players will be able to make replacements. /obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/stock_parts/manipulator = 1) +/obj/item/weapon/circuitboard/tesla_coil + name = "circuit board (Tesla Coil)" + build_path = /obj/machinery/power/tesla_coil + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1) + +/obj/item/weapon/circuitboard/grounding_rod + name = "circuit board (Grounding Rod)" + build_path = /obj/machinery/power/grounding_rod + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1) + /obj/item/weapon/circuitboard/processor name = "circuit board (Food processor)" build_path = /obj/machinery/processor diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 04c6e5d0bb7..7751e757690 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -12,6 +12,7 @@ var/burn_state = FIRE_PROOF // LAVA_PROOF | FIRE_PROOF | FLAMMABLE | ON_FIRE var/burntime = 10 //How long it takes to burn to ashes, in seconds var/burn_world_time //What world time the object will burn up completely + var/being_shocked = 0 /obj/Destroy() if(!istype(src, /obj/machinery)) @@ -185,10 +186,15 @@ overlays -= fire_overlay SSobj.burning -= src - - /obj/proc/empty_object_contents(burn = 0, new_loc = src.loc) for(var/obj/item/Item in contents) //Empty out the contents Item.loc = new_loc if(burn) - Item.fire_act() //Set them on fire, too \ No newline at end of file + Item.fire_act() //Set them on fire, too + +/obj/proc/tesla_act(var/power) + being_shocked = 1 + var/power_bounced = power / 2 + tesla_zap(src, 5, power_bounced) + spawn(10) + being_shocked = 0 diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 28f958f647d..eb3a13dd890 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -60,6 +60,7 @@ item_state = "eng_hardsuit" armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75) allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/internals,/obj/item/device/t_scanner, /obj/item/weapon/rcd) + siemens_coefficient = 0 var/obj/item/clothing/head/helmet/space/hardsuit/helmet action_button_name = "Toggle Helmet" var/helmettype = /obj/item/clothing/head/helmet/space/hardsuit diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 185b595132c..d1f2c2c10b2 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -80,7 +80,7 @@ . = ..() -/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0) +/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0) shock_damage *= siemens_coeff if(shock_damage<1 && !override) return 0 @@ -98,11 +98,13 @@ jitteriness += 1000 //High numbers for violent convulsions do_jitter_animation(jitteriness) stuttering += 2 - Stun(2) + if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) + Stun(2) spawn(20) jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less - Stun(3) - Weaken(3) + if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) + Stun(3) + Weaken(3) if(override) return override else diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 916587af53a..5c7cc41006e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -279,8 +279,19 @@ spreadFire(AM) //Added a safety check in case you want to shock a human mob directly through electrocute_act. -/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0) - if(!safety) +/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0) + if(tesla_shock) + var/total_coeff = 1 + if(gloves) + var/obj/item/clothing/gloves/G = gloves + if(G.siemens_coefficient <= 0) + total_coeff -= 0.5 + if(wear_suit) + var/obj/item/clothing/suit/S = wear_suit + if(S.siemens_coefficient <= 0) + total_coeff -= 0.95 + siemens_coeff = total_coeff + else if(!safety) var/gloves_siemens_coeff = 1 var/species_siemens_coeff = 1 if(gloves) @@ -294,7 +305,7 @@ heart_attack = 0 if(stat == CONSCIOUS) src << "You feel your heart beating again!" - . = ..(shock_damage,source,siemens_coeff,safety,override) + . = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock) if(.) electrocution_animation(40) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index f1754abcbd5..98eb3b5f3a8 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -386,7 +386,7 @@ Sorry Giacom. Please don't be mad :( return 0 -/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0) +/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0) return 0 //only carbon liveforms have this proc /mob/living/emp_act(severity) diff --git a/code/modules/power/singularity/generator.dm b/code/modules/power/singularity/generator.dm index 6d8e6763389..066f95d6d75 100644 --- a/code/modules/power/singularity/generator.dm +++ b/code/modules/power/singularity/generator.dm @@ -8,11 +8,12 @@ density = 1 use_power = 0 var/energy = 0 + var/creation_type = /obj/singularity /obj/machinery/the_singularitygen/process() var/turf/T = get_turf(src) if(src.energy >= 200) - new /obj/singularity/(T, 50) + new creation_type(T, 50) if(src) qdel(src) /obj/machinery/the_singularitygen/attackby(obj/item/W, mob/user, params) diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm new file mode 100644 index 00000000000..43adbc22978 --- /dev/null +++ b/code/modules/power/tesla/coil.dm @@ -0,0 +1,83 @@ +/obj/machinery/power/tesla_coil + name = "tesla coil" + desc = "For the union!" + icon = 'icons/obj/tesla_engine/tesla_coil.dmi' + icon_state = "coil" + anchored = 0 + density = 1 + var/power_loss = 2 + var/input_power_multiplier = 1 + +/obj/machinery/power/tesla_coil/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/tesla_coil(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + RefreshParts() + +/obj/machinery/power/tesla_coil/RefreshParts() + var/power_multiplier = 0 + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) + power_multiplier += C.rating + input_power_multiplier = power_multiplier + +/obj/machinery/power/tesla_coil/attackby(obj/item/W, mob/user, params) + if(default_deconstruction_screwdriver(user, "coil", "coil", W)) + return + + if(exchange_parts(user, W)) + return + + if(default_pry_open(W)) + return + + if(default_unfasten_wrench(user, W)) + if(!anchored) + disconnect_from_network() + else + connect_to_network() + return + + default_deconstruction_crowbar(W) + +/obj/machinery/power/tesla_coil/tesla_act(var/power) + being_shocked = 1 + var/power_produced = power / power_loss + add_avail(power_produced*input_power_multiplier) + flick("coilhit", src) + tesla_zap(src, 5, power_produced) + spawn(10) + being_shocked = 0 + +/obj/machinery/power/grounding_rod + name = "Grounding Rod" + desc = "Keep an area from being fried from Edison's Bane." + icon = 'icons/obj/tesla_engine/tesla_coil.dmi' + icon_state = "grounding_rod" + anchored = 0 + density = 1 + +/obj/machinery/power/grounding_rod/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/grounding_rod(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + RefreshParts() + +/obj/machinery/power/grounding_rod/attackby(obj/item/W, mob/user, params) + if(default_deconstruction_screwdriver(user, "grounding_rod", "grounding_rod", W)) + return + + if(exchange_parts(user, W)) + return + + if(default_pry_open(W)) + return + + if(default_unfasten_wrench(user, W)) + return + + default_deconstruction_crowbar(W) + +/obj/machinery/power/grounding_rod/tesla_act(var/power) + flick("coil_shock_1", src) \ No newline at end of file diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm new file mode 100644 index 00000000000..96a4d27e1df --- /dev/null +++ b/code/modules/power/tesla/energy_ball.dm @@ -0,0 +1,203 @@ +#define TESLA_DEFAULT_POWER 3476520 +#define TESLA_MINI_POWER 1738260 + +var/list/blacklisted_tesla_types = list(/obj/machinery/atmospherics, + /obj/machinery/power/emitter, + /obj/machinery/field/generator, + /mob/living/simple_animal, + /obj/machinery/particle_accelerator/control_box, + /obj/structure/particle_accelerator/fuel_chamber, + /obj/structure/particle_accelerator/particle_emitter/center, + /obj/structure/particle_accelerator/particle_emitter/left, + /obj/structure/particle_accelerator/particle_emitter/right, + /obj/structure/particle_accelerator/power_box, + /obj/structure/particle_accelerator/end_cap, + /obj/machinery/field/containment, + /obj/structure/disposalpipe) + +/obj/singularity/energy_ball + name = "energy eall" + desc = "An energy ball." + icon = 'icons/obj/tesla_engine/energy_ball.dmi' + icon_state = "energy_ball" + pixel_x = -32 + pixel_y = -32 + current_size = STAGE_TWO + move_self = 1 + grav_pull = 0 + contained = 0 + density = 1 + var/list/orbiting_balls = list() + var/produced_power + var/is_orbiting + +/obj/singularity/energy_ball/Destroy() + for(var/obj/singularity/energy_ball/EB in orbiting_balls) + qdel(EB) + ..() + +/obj/singularity/energy_ball/process() + if(!is_orbiting) + handle_energy() + var/amount_to_move = 2 + orbiting_balls.len * 2 + move_the_basket_ball(amount_to_move) + pixel_x = 0 + pixel_y = 0 + tesla_zap(src, 7, TESLA_DEFAULT_POWER) + pixel_x = -32 + pixel_y = -32 + energy += rand(1,3) // ensure it generates energy without needing to be blasted by the PA too much due to its size, and that a tesla engine will always get bigger over time + else + tesla_zap(src, 7, TESLA_MINI_POWER) + energy = 0 // ensure we dont have miniballs of miniballs + return + +/obj/singularity/energy_ball/examine(mob/user) + ..() + if(orbiting_balls.len) + user << "The amount of orbiting mini-balls is [orbiting_balls.len]." + + +/obj/singularity/energy_ball/proc/move_the_basket_ball(var/move_amount) + for(var/i = 0, i < move_amount, i++) + var/move_dir = pick(alldirs) + var/turf/T = get_step(src,move_dir) + if(can_move(T)) + loc = get_step(src,move_dir) + +/obj/singularity/energy_ball/proc/handle_energy() + if(energy >= 300) + energy = 0 + var/obj/singularity/energy_ball/EB = new(loc) + orbiting_balls.Add(EB) + EB.transform *= pick(0.3,0.4,0.5,0.6,0.7) + EB.is_orbiting = 1 + var/icon/I = icon(icon,icon_state,dir) + + var/orbitsize = (I.Width()+I.Height())*pick(0.5,0.6,0.7) + orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25) + spawn(1) + EB.orbit(src,orbitsize, pick(FALSE,TRUE), rand(10,25), pick(3,4,5,6,36)) + + + +/obj/singularity/energy_ball/Bump(atom/A) + dust_mobs(A) + +/obj/singularity/energy_ball/Bumped(atom/A) + dust_mobs(A) + +/obj/singularity/energy_ball/proc/dust_mobs(atom/A) + if(istype(A, /mob/living/carbon)) + var/mob/living/carbon/C = A + C.dust() + return + +/proc/get_closest_atom(type, list, source) + var/closest_atom + var/closest_distance + for(var/A in list) + if(!istype(A, type)) + continue + var/distance = get_dist(source, A) + if(!closest_distance) + closest_distance = distance + closest_atom = A + else + if(closest_distance > distance) + closest_distance = distance + closest_atom = A + return closest_atom + +/proc/tesla_zap(var/atom/source, zap_range = 3, power) + if(power < 1000) + return + var/list/tesla_coils = list() + var/list/grounding_rods = list() + var/list/potential_machine_zaps = list() + var/list/potential_mob_zaps = list() + var/list/potential_structure_zaps = list() + var/closest_atom + for(var/atom/A in oview(source, zap_range)) + if(istype(A, /obj/machinery/power/tesla_coil)) + var/obj/machinery/power/tesla_coil/C = A + if(C.being_shocked) + continue + tesla_coils.Add(C) + continue + if(istype(A, /obj/machinery/power/grounding_rod)) + var/obj/machinery/power/grounding_rod/R = A + grounding_rods.Add(R) + continue + if(istype(A, /obj/machinery)) + var/obj/machinery/M = A + if(is_type_in_list(M, blacklisted_tesla_types)) + continue + if(M.being_shocked) + continue + potential_machine_zaps.Add(M) + continue + if(istype(A, /obj/structure)) + var/obj/structure/M = A + if(is_type_in_list(M, blacklisted_tesla_types)) + continue + if(M.being_shocked) + continue + potential_structure_zaps.Add(M) + continue + if(istype(A, /mob/living)) + var/mob/living/L = A + if(L.stat == DEAD) + continue + if(is_type_in_list(L, blacklisted_tesla_types)) + continue + potential_mob_zaps.Add(L) + continue + closest_atom = get_closest_atom(/obj/machinery/power/tesla_coil, tesla_coils, source) + if(closest_atom && istype(closest_atom, /obj/machinery/power/tesla_coil)) + var/obj/machinery/power/tesla_coil/C = closest_atom + source.Beam(C,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) + C.tesla_act(power) + return + if(!closest_atom) + closest_atom = get_closest_atom(/obj/machinery/power/grounding_rod, grounding_rods, source) + if(closest_atom && istype(closest_atom, /obj/machinery/power/grounding_rod)) + var/obj/machinery/power/grounding_rod/R = closest_atom + source.Beam(R,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) + R.tesla_act(power) + return + if(!closest_atom) + closest_atom = get_closest_atom(/mob/living, potential_mob_zaps, source) + if(closest_atom && istype(closest_atom, /mob/living)) + var/mob/living/L = closest_atom + var/shock_damage = Clamp(round(power/400), 10, 90) + rand(-5,5) + source.Beam(L,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) + L.electrocute_act(shock_damage, source, 1, tesla_shock = 1) + if(istype(L, /mob/living/silicon)) + var/mob/living/silicon/S = L + S.emp_act(2) + return + if(!closest_atom) + closest_atom = get_closest_atom(/obj/machinery, potential_machine_zaps, source) + if(closest_atom) + var/obj/machinery/M = closest_atom + source.Beam(M,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) + M.tesla_act(power) + if(prob(85)) + M.emp_act(2) + else + if(prob(50)) + M.ex_act(3) + else + if(prob(90)) + M.ex_act(2) + else + M.ex_act(1) + return + if(!closest_atom) + closest_atom = get_closest_atom(/obj/structure, potential_structure_zaps, source) + if(closest_atom) + var/obj/structure/S = closest_atom + source.Beam(S,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) + S.tesla_act(power) + return diff --git a/code/modules/power/tesla/generator.dm b/code/modules/power/tesla/generator.dm new file mode 100644 index 00000000000..f511c650c8c --- /dev/null +++ b/code/modules/power/tesla/generator.dm @@ -0,0 +1,6 @@ +/obj/machinery/the_singularitygen/tesla + name = "energy ball generator" + desc = "Makes the wardenclyffe look like a child's plaything when shot with a particle accelerator." + icon = 'icons/obj/tesla_engine/tesla_generator.dmi' + icon_state = "TheSingGen" + creation_type = /obj/singularity/energy_ball \ No newline at end of file diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index 6caa1004192..44e8d65f49e 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -452,3 +452,23 @@ materials = list(MAT_GLASS = 1000, "sacid" = 20) build_path = /obj/item/weapon/circuitboard/mining_equipment_vendor category = list ("Misc. Machinery") + +/datum/design/tesla_coil + name = "Machine Design (Tesla Coil Board)" + desc = "The circuit board for a tesla coil." + id = "tesla_coil" + req_tech = list("programming" = 1) + build_type = IMPRINTER + materials = list(MAT_GLASS = 1000, "sacid" = 20) + build_path = /obj/item/weapon/circuitboard/tesla_coil + category = list ("Misc. Machinery") + +/datum/design/grounding_rod + name = "Machine Design (Grounding Rod Board)" + desc = "The circuit board for a grounding rod." + id = "grounding_rod" + req_tech = list("programming" = 1) + build_type = IMPRINTER + materials = list(MAT_GLASS = 1000, "sacid" = 20) + build_path = /obj/item/weapon/circuitboard/grounding_rod + category = list ("Misc. Machinery") \ No newline at end of file diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index da5434e8968..6c1343f2485 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/obj/machines/particle_accelerator.dmi b/icons/obj/machines/particle_accelerator.dmi index a8b0097e73d..f092bd5a97b 100644 Binary files a/icons/obj/machines/particle_accelerator.dmi and b/icons/obj/machines/particle_accelerator.dmi differ diff --git a/icons/obj/tesla_engine/energy_ball.dmi b/icons/obj/tesla_engine/energy_ball.dmi new file mode 100644 index 00000000000..7f68e4b0071 Binary files /dev/null and b/icons/obj/tesla_engine/energy_ball.dmi differ diff --git a/icons/obj/tesla_engine/tesla_coil.dmi b/icons/obj/tesla_engine/tesla_coil.dmi new file mode 100644 index 00000000000..5c3646dde80 Binary files /dev/null and b/icons/obj/tesla_engine/tesla_coil.dmi differ diff --git a/icons/obj/tesla_engine/tesla_generator.dmi b/icons/obj/tesla_engine/tesla_generator.dmi new file mode 100644 index 00000000000..adf5fbaa8ec Binary files /dev/null and b/icons/obj/tesla_engine/tesla_generator.dmi differ diff --git a/tgstation.dme b/tgstation.dme index e5a9aa6781f..ce37b51c2ca 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1442,6 +1442,9 @@ #include "code\modules\power\singularity\particle_accelerator\particle_power.dm" #include "code\modules\power\supermatter\supermatter.dm" #include "code\modules\power\supermatter\supermatter_crate.dm" +#include "code\modules\power\tesla\coil.dm" +#include "code\modules\power\tesla\energy_ball.dm" +#include "code\modules\power\tesla\generator.dm" #include "code\modules\procedural mapping\mapGenerator.dm" #include "code\modules\procedural mapping\mapGeneratorModule.dm" #include "code\modules\procedural mapping\mapGeneratorReadme.dm"