diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 0b7e5b585e3..8e03130f8b3 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -134,10 +134,11 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define ZAP_OBJ_DAMAGE (1<<2) #define ZAP_MOB_DAMAGE (1<<3) #define ZAP_MOB_STUN (1<<4) +#define ZAP_GENERATES_POWER (1<<5) -#define ZAP_DEFAULT_FLAGS ZAP_MOB_STUN | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE +#define ZAP_DEFAULT_FLAGS ZAP_MOB_STUN | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE #define ZAP_FUSION_FLAGS ZAP_OBJ_DAMAGE | ZAP_MOB_DAMAGE | ZAP_MOB_STUN -#define ZAP_SUPERMATTER_FLAGS NONE +#define ZAP_SUPERMATTER_FLAGS ZAP_GENERATES_POWER //EMP protection #define EMP_PROTECT_SELF (1<<0) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 239e4bd14c8..9f3b88b8bc8 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -283,4 +283,5 @@ DEFINE_BITFIELD(zap_flags, list( "ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE, "ZAP_MOB_STUN" = ZAP_MOB_STUN, "ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE, + "ZAP_GENERATES_POWER" = ZAP_GENERATES_POWER, )) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 609d9bcc34b..0c22882d217 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -412,4 +412,9 @@ if(. && !(machine_stat & NOPOWER)) autoclose_in(DOOR_CLOSE_WAIT) +/obj/machinery/door/zap_act(power, zap_flags) + zap_flags &= ~ZAP_OBJ_DAMAGE + . = ..() + + #undef DOOR_CLOSE_WAIT diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 8f83559622c..949568b9dec 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -131,4 +131,10 @@ return "It's falling apart!" /obj/structure/rust_heretic_act() - take_damage(500, BRUTE, MELEE, 1) + take_damage(500, BRUTE, "melee", 1) + +/obj/structure/zap_act(power, zap_flags) + if(zap_flags & ZAP_OBJ_DAMAGE) + take_damage(power/8000, BURN, "energy") + power -= power/2000 //walls take a lot out of ya + . = ..() diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 4c0cf0af3ef..0fa0c772dd3 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -15,7 +15,7 @@ var/allowed_size = 1 var/contained = 1 //Are we going to move around? var/energy = 100 //How strong are we? - var/dissipate = 1 //Do we lose energy over time? + var/dissipate = TRUE //Do we lose energy over time? var/dissipate_delay = 10 var/dissipate_track = 0 var/dissipate_strength = 1 //How much energy do we lose? diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 7e0620cc49c..93f20e54f5f 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -437,10 +437,10 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) S.consume(src) return //No boom for me sir else if(power > POWER_PENALTY_THRESHOLD) - investigate_log("has released tritium from an overcharge.", INVESTIGATE_SUPERMATTER) + investigate_log("has spawned additional energy balls.", INVESTIGATE_SUPERMATTER) if(T) - atmos_spawn_air("tritium=2500;TEMP=500000") //extremely fucking hot and could do fusion if you tried hard enough //GEORGE SEARS DID 9/11 - investigate_log("has exploded.", INVESTIGATE_SUPERMATTER) + var/obj/singularity/energy_ball/E = new(T) + E.energy = 200 //Gets us about 9 balls //Dear mappers, balance the sm max explosion radius to 17.5, 37, 39, 41 explosion(get_turf(T), explosion_power * max(gasmix_power_ratio, 0.205) * 0.5 , explosion_power * max(gasmix_power_ratio, 0.205) + 2, explosion_power * max(gasmix_power_ratio, 0.205) + 4 , explosion_power * max(gasmix_power_ratio, 0.205) + 6, 1, 1) qdel(src) diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 74502cfe07c..a6309ee762c 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -75,16 +75,18 @@ if(anchored && !panel_open) //don't lose arc power when it's not connected to anything //please place tesla coils all around the station to maximize effectiveness + obj_flags |= BEING_SHOCKED + addtimer(CALLBACK(src, .proc/reset_shocked), 1 SECONDS) + zap_buckle_check(power) + if(zap_flags & ZAP_GENERATES_POWER) //I don't want no tesla revolver making 8GW you hear + return power / 2 var/power_produced = powernet ? power * input_power_multiplier : power add_avail(power_produced) var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG) if(D) D.adjust_money(min(power_produced, 1)) flick("coilhit", src) - zap_buckle_check(power) playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) - obj_flags |= BEING_SHOCKED - addtimer(CALLBACK(src, .proc/reset_shocked), 1 SECONDS) return power - power_produced //You get back the amount we didn't use else . = ..() @@ -102,7 +104,7 @@ /obj/machinery/power/grounding_rod name = "grounding rod" - desc = "Keep an area from being fried." + desc = "Keeps an area from being fried by Edison's Bane." icon = 'icons/obj/tesla_engine/tesla_coil.dmi' icon_state = "grounding_rod0" anchored = FALSE diff --git a/code/modules/power/tesla/tesla_zap.dm b/code/modules/power/tesla/energy_ball.dm similarity index 51% rename from code/modules/power/tesla/tesla_zap.dm rename to code/modules/power/tesla/energy_ball.dm index 4191853fd49..56c9175007a 100644 --- a/code/modules/power/tesla/tesla_zap.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -10,9 +10,185 @@ #define BLOB (STRUCTURE + 1) #define STRUCTURE (1) +/obj/singularity/energy_ball + name = "energy ball" + 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 = TRUE + energy = 0 + dissipate = FALSE + dissipate_delay = 5 + dissipate_strength = 1 + var/list/orbiting_balls = list() + var/miniball = FALSE + var/produced_power + var/energy_to_raise = 32 + var/energy_to_lower = -20 + var/list/shocked_things = list() + +/obj/singularity/energy_ball/Initialize(mapload, starting_energy = 50, is_miniball = FALSE) + miniball = is_miniball + . = ..() + if(!is_miniball) + set_light(10, 7, "#5e5edd") + +/obj/singularity/energy_ball/ex_act(severity, target) + return + +/obj/singularity/energy_ball/consume(severity, target) + return + +/obj/singularity/energy_ball/Destroy() + if(orbiting && istype(orbiting.parent, /obj/singularity/energy_ball)) + var/obj/singularity/energy_ball/EB = orbiting.parent + EB.orbiting_balls -= src + + for(var/ball in orbiting_balls) + var/obj/singularity/energy_ball/EB = ball + QDEL_NULL(EB) + . = ..() + +/obj/singularity/energy_ball/admin_investigate_setup() + if(miniball) + return //don't annnounce miniballs + ..() + + +/obj/singularity/energy_ball/process() + if(!orbiting) + handle_energy() + + move_the_basket_ball(4 + orbiting_balls.len * 1.5) + + playsound(src.loc, 'sound/magic/lightningbolt.ogg', 100, TRUE, extrarange = 30) + + pixel_x = 0 + pixel_y = 0 + shocked_things.Cut() + tesla_zap(src, 3, TESLA_DEFAULT_POWER, shocked_targets = shocked_things) + + pixel_x = -32 + pixel_y = -32 + for (var/ball in orbiting_balls) + var/range = rand(1, clamp(orbiting_balls.len, 2, 3)) + var/list/temp_shock = list() + tesla_zap(ball, range, TESLA_MINI_POWER/7*range, shocked_targets = temp_shock) + shocked_things += temp_shock + else + energy = 0 // ensure we dont have miniballs of miniballs //But it'll be cool broooooooooooooooo + +/obj/singularity/energy_ball/examine(mob/user) + . = ..() + if(orbiting_balls.len) + . += "There are [orbiting_balls.len] mini-balls orbiting it." + + +/obj/singularity/energy_ball/proc/move_the_basket_ball(move_amount) + var/list/dirs = GLOB.alldirs.Copy() + for(var/I in 1 to 30) + var/atom/real_thing = pick(shocked_things) + dirs += get_dir(src, real_thing) //Carry some momentum yeah? Just a bit tho + for(var/i in 0 to move_amount) + var/move_dir = pick(dirs) //ensures teslas don't just sit around + if(target && prob(10)) + move_dir = get_dir(src,target) + var/turf/T = get_step(src, move_dir) + if(can_move(T)) + forceMove(T) + setDir(move_dir) + for(var/mob/living/carbon/C in loc) + dust_mobs(C) + + +/obj/singularity/energy_ball/proc/handle_energy() + if(energy >= energy_to_raise) + energy_to_lower = energy_to_raise - 20 + energy_to_raise = energy_to_raise * 1.25 + + playsound(src.loc, 'sound/magic/lightning_chargeup.ogg', 100, TRUE, extrarange = 30) + addtimer(CALLBACK(src, .proc/new_mini_ball), 100) + + else if(energy < energy_to_lower && orbiting_balls.len) + energy_to_raise = energy_to_raise / 1.25 + energy_to_lower = (energy_to_raise / 1.25) - 20 + + var/Orchiectomy_target = pick(orbiting_balls) + qdel(Orchiectomy_target) + + else if(orbiting_balls.len) + dissipate() //sing code has a much better system. + +/obj/singularity/energy_ball/proc/new_mini_ball() + if(!loc) + return + var/obj/singularity/energy_ball/EB = new(loc, 0, TRUE) + + EB.transform *= pick(0.3, 0.4, 0.5, 0.6, 0.7) + var/icon/I = icon(icon,icon_state,dir) + + var/orbitsize = (I.Width() + I.Height()) * pick(0.4, 0.5, 0.6, 0.7, 0.8) + orbitsize -= (orbitsize / world.icon_size) * (world.icon_size * 0.25) + + 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/movable/AM) + dust_mobs(AM) + +/obj/singularity/energy_ball/attack_tk(mob/user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + to_chat(C, "That was a shockingly dumb idea.") + var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs + C.ghostize(0) + qdel(rip_u) + C.death() + +/obj/singularity/energy_ball/orbit(obj/singularity/energy_ball/target) + if (istype(target)) + target.orbiting_balls += src + GLOB.poi_list -= src + target.dissipate_strength = target.orbiting_balls.len + . = ..() + +/obj/singularity/energy_ball/stop_orbit() + if (orbiting && istype(orbiting.parent, /obj/singularity/energy_ball)) + var/obj/singularity/energy_ball/orbitingball = orbiting.parent + orbitingball.orbiting_balls -= src + orbitingball.dissipate_strength = orbitingball.orbiting_balls.len + . = ..() + if (!QDELETED(src)) + qdel(src) + + +/obj/singularity/energy_ball/proc/dust_mobs(atom/A) + if(isliving(A)) + var/mob/living/L = A + if(L.incorporeal_move || L.status_flags & GODMODE) + return + if(!iscarbon(A)) + return + for(var/obj/machinery/power/grounding_rod/GR in orange(src, 2)) + if(GR.anchored) + return + var/mob/living/carbon/C = A + C.dust() + /proc/tesla_zap(atom/source, zap_range = 3, power, zap_flags = ZAP_DEFAULT_FLAGS, list/shocked_targets = list()) if(QDELETED(source)) return + if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) + LAZYSET(shocked_targets, source, TRUE) //I don't want no null refs in my list yeah? . = source.dir if(power < 1000) return @@ -24,6 +200,7 @@ var/closest_type = 0 var/static/things_to_shock = typecacheof(list(/obj/machinery, /mob/living, /obj/structure, /obj/vehicle/ridden)) var/static/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics, + /obj/machinery/portable_atmospherics, /obj/machinery/power/emitter, /obj/machinery/field/generator, /mob/living/simple_animal, @@ -125,13 +302,11 @@ return //common stuff source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", time=5, maxdistance = INFINITY) - if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) - LAZYSET(shocked_targets, closest_atom, TRUE) var/zapdir = get_dir(source, closest_atom) if(zapdir) . = zapdir - var/next_range = 3 + var/next_range = 2 if(closest_type == COIL) next_range = 5 diff --git a/tgstation.dme b/tgstation.dme index 60f4fd0a4f9..a1a30d3029a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2678,7 +2678,7 @@ #include "code\modules\power\singularity\singularity.dm" #include "code\modules\power\supermatter\supermatter.dm" #include "code\modules\power\tesla\coil.dm" -#include "code\modules\power\tesla\tesla_zap.dm" +#include "code\modules\power\tesla\energy_ball.dm" #include "code\modules\procedural_mapping\mapGenerator.dm" #include "code\modules\procedural_mapping\mapGeneratorModule.dm" #include "code\modules\procedural_mapping\mapGeneratorObj.dm"