From e8944e087de66b9db07a19a38b012c4ff80c64de Mon Sep 17 00:00:00 2001 From: FenodyreeAv Date: Tue, 7 Apr 2026 21:08:41 +0100 Subject: [PATCH] Modular laser fixes and nerfs (#22147) **Fixes the bugs found on the recent nations round.** - Fixed firedelay doing nothing on modlasers with the shotgun lens. Also fixed the existing laser shotgun as a side effect. Fixes #22141 and Fixes #22137 - Fixes the shotgun lens not having any dispersion. - Fixes bluespace capacitors not teleporting you on a failure. - Fixes phoron capacitors not hurting the user when they explode. - Fixes messages about malfunctions not displaying to the user. - Fixes a bunch of bugs related to repairing components - Stops components getting qdeled but leaving their references on all other components, breaking them if reused. **Nerfs a few of the most problematic things.** - Cut the damage of the blaster projectile by 20% and reduced it's AP from 60 to 35, also drops it's incendiary value to 1. This projectile was FAR more powerful than any other, ignored all armour and set the user on fire without a damage penalty. With this change, lasers are now better on unarmoured targets, the blaster is better on 40+ armour, so Heavy and Specialist Ablative. - Added an immediate electric shock to the user (and anyone within one tile if the capacitor is unstable enough). The previous low level failures all irradiated the user. This did more damage in the long term, but didn't affect the outcome of any fights and was easy to negate with suits. The tesla shock is obvious to everyone nearby, causes immediate pain and the gun to be dropped if the capacitor is overcharged. This makes minor failures a significant factor mid fight, especially on powerful guns. - Makes the phoron capacitor directly damage the hand holding it when it explodes. This capacitor can be built with phoron and uranium, which both spawn at roundstart, though uranium isn't accessible. It's therefore the most common capacitor, and the second most powerful. This increases downside a lot, in addition to the explosion being fixed, it will break the hand that fires it when it malfunctions. If the capacitor is unstable, such as in a 60 damage monster, it will gib the hand that fires it on malfunction. **Tweaks, aimed at making the guns easier to understand, repair and test** - Adds a locker and boxes of modlaser parts. Not mapped in, but easy to spawn for testing. - Adds big red warning messages, visible to everyone nearby, explaining what happened to the gun, who was holding it and how bad the malfunction was. - Made the lenses repairable with glass, or reinforced glass. The nanopaste cost of a repair was more than 50x the cost of just printing a new lens. --- .../objects/items/weapons/storage/boxes.dm | 74 ++++++++++ .../closets/secure/scientist.dm | 12 ++ code/modules/projectiles/gun.dm | 6 +- .../projectiles/guns/energy/modular.dm | 38 ++--- .../modules/projectiles/modular/laser_base.dm | 37 +++-- .../projectiles/modular/laser_components.dm | 131 ++++++++++++------ code/modules/projectiles/projectile/energy.dm | 6 + code/modules/research/weaponsanalyzer.dm | 10 +- .../Fenodyree-ModLaserFixesAndNerfs.yml | 69 +++++++++ 9 files changed, 301 insertions(+), 82 deletions(-) create mode 100644 html/changelogs/Fenodyree-ModLaserFixesAndNerfs.yml diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index b8ce445fadb..ca1eca34511 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -513,6 +513,80 @@ illustration = "firingpin" starts_with = list(/obj/item/firing_pin = 2, /obj/item/firing_pin/access = 2, /obj/item/firing_pin/implant/loyalty = 2, /obj/item/firing_pin/psionic = 1, /obj/item/firing_pin/dna = 1) +/obj/item/storage/box/modlaser + name = "box of modular laser capacitors" + desc = "A box full of laser capacitors, used to build laser weapons." + color = COLOR_PURPLE_GRAY + illustration = "scicircuit" + starts_with = list( + /obj/item/laser_components/capacitor = 1, + /obj/item/laser_components/capacitor/potato = 1, + /obj/item/laser_components/capacitor/reinforced = 1, + /obj/item/laser_components/capacitor/nuclear = 1, + /obj/item/laser_components/capacitor/teranium = 1, + /obj/item/laser_components/capacitor/phoron = 2, + /obj/item/laser_components/capacitor/bluespace = 2 + ) + +/obj/item/storage/box/modlaser/modulators + name = "box of modular laser modulators" + desc = "A box full of laser modulators, used to build laser weapons." + illustration = "firecracker" + starts_with = list( + /obj/item/laser_components/modulator/taser = 1, + /obj/item/laser_components/modulator/tesla = 1, + /obj/item/laser_components/modulator/ion = 1, + /obj/item/laser_components/modulator/floramut = 1, + /obj/item/laser_components/modulator/floramut2 = 1, + /obj/item/laser_components/modulator/arodentia = 1, + /obj/item/laser_components/modulator/red = 1, + /obj/item/laser_components/modulator/blue = 1, + /obj/item/laser_components/modulator/omni = 1, + /obj/item/laser_components/modulator/practice = 1, + /obj/item/laser_components/modulator/mindflayer = 1, + /obj/item/laser_components/modulator/decloner = 1, + /obj/item/laser_components/modulator/ebow = 1, + /obj/item/laser_components/modulator/blaster = 1, + /obj/item/laser_components/modulator/tox = 1, + /obj/item/laser_components/modulator/net = 1, + /obj/item/laser_components/modulator/freeze = 1 + ) + +/obj/item/storage/box/modlaser/modifiers + name = "box of modular laser mods" + desc = "A box full of laser mods, used to build laser weapons." + illustration = "circuit" + starts_with = list( + /obj/item/laser_components/modifier/silencer = 1, + /obj/item/laser_components/modifier/aeg = 1, + /obj/item/laser_components/modifier/surge = 1, + /obj/item/laser_components/modifier/repeater = 1, + /obj/item/laser_components/modifier/auxiliarycap = 1, + /obj/item/laser_components/modifier/overcharge = 1, + /obj/item/laser_components/modifier/gatling = 1, + /obj/item/laser_components/modifier/scope = 1, + /obj/item/laser_components/modifier/barrel = 1, + /obj/item/laser_components/modifier/barrel/nano = 1, + /obj/item/laser_components/modifier/vents = 1, + /obj/item/laser_components/modifier/grip = 1, + /obj/item/laser_components/modifier/grip/improved = 1, + /obj/item/laser_components/modifier/stock = 1, + /obj/item/laser_components/modifier/stock/gyro = 1, + /obj/item/laser_components/modifier/bayonet = 1, + /obj/item/laser_components/modifier/ebayonet = 1 + ) + +/obj/item/storage/box/modlaser/lens + name = "box of modular laser lenses" + desc = "A box full of laser lenses, used to build laser weapons." + illustration = "petridish" + starts_with = list( + /obj/item/laser_components/focusing_lens = 2, + /obj/item/laser_components/focusing_lens/shotgun = 2, + /obj/item/laser_components/focusing_lens/sniper = 2, + /obj/item/laser_components/focusing_lens/strong = 2 + ) + /obj/item/storage/box/unique/freezer/organcooler/psireceiver name = "psionic receivers cooler" desc = "A cooling box for psionic receivers, which can be surgically implanted to act as a replacement for an underdeveloped or non-existent zona bovinae. This one has a large sticker on the side reading FOR RESEARCH USE ONLY." diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index 0b4a6dae673..2a0d1775215 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -14,6 +14,18 @@ new /obj/item/taperoll/science(src) new /obj/item/sampler(src) +/obj/structure/closet/secure_closet/scientist/modlaser + name = "scientist's laser locker" + +/obj/structure/closet/secure_closet/scientist/modlaser/fill() + new /obj/item/laser_assembly(src) + new /obj/item/laser_assembly/medium(src) + new /obj/item/laser_assembly/large(src) + new /obj/item/storage/box/modlaser(src) + new /obj/item/storage/box/modlaser/modulators(src) + new /obj/item/storage/box/modlaser/lens(src) + new /obj/item/storage/box/modlaser/modifiers(src) + /obj/structure/closet/secure_closet/RD name = "research director's locker" req_access = list(ACCESS_RD) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index b349ca4511f..b56e374d53a 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -477,6 +477,8 @@ ABSTRACT_TYPE(/obj/item/gun) // Custom formula here because otherwise you can fire bursts within the burst. var/shoot_time = burst > 1 ? burst_delay + 1 : fire_delay + if (burst > 1 && burst_delay == 0) //Prevents guns with no burst delay (laser shotguns) from firing as fast as you can click. + shoot_time = fire_delay user.setClickCooldown(shoot_time) /// Similar to the Fire() proc, but does not require a user, which is ideal for things like turrets. @@ -994,9 +996,9 @@ ABSTRACT_TYPE(/obj/item/gun) */ /obj/item/gun/proc/handle_reliability_fail(var/mob/user) var/severity = 1 - if(prob(100-reliability)) + if(prob(80-reliability)) //Medium severity failures only possible under 80% reliability. severity = 2 - if(prob(100-reliability)) + if(prob(65-reliability)) //Critical failures only possible under 65% reliability. severity = 3 switch(severity) if(1) diff --git a/code/modules/projectiles/guns/energy/modular.dm b/code/modules/projectiles/guns/energy/modular.dm index ca018e6d570..22bdf9de1b6 100644 --- a/code/modules/projectiles/guns/energy/modular.dm +++ b/code/modules/projectiles/guns/energy/modular.dm @@ -68,7 +68,10 @@ reliability = initial(reliability) burst_delay = initial(burst_delay) max_shots = initial(max_shots) + charge_cost = initial(charge_cost) chargetime = initial(chargetime) + fire_delay = initial(fire_delay) + fire_delay_wielded = initial(fire_delay_wielded) accuracy = initial(accuracy) criticality = initial(criticality) fire_sound = initial(fire_sound) @@ -83,18 +86,18 @@ return update_chassis() + //TODO: When the skill system test is merged, rework this to give high skills a chance to avoid the failure. + // if(capacitor.reliability - capacitor.condition <= 0) + // if(prob(66)) + // capacitor.small_fail(user) + // else + // capacitor.medium_fail(user) + // qdel(capacitor) + // capacitor = null - if(capacitor.reliability - capacitor.condition <= 0) - if(prob(66)) - capacitor.small_fail(user) - else - capacitor.medium_fail(user) - qdel(capacitor) - capacitor = null - - if(focusing_lens.reliability - focusing_lens.condition <= 0) - qdel(focusing_lens) - focusing_lens = null + // if(focusing_lens.reliability - focusing_lens.condition <= 0) + // qdel(focusing_lens) + // focusing_lens = null if(!focusing_lens || !capacitor || !modulator) disassemble(user) @@ -116,8 +119,8 @@ if(gun_mods.len) handle_mod() - max_shots = max_shots * burst power_supply.maxcharge = max_shots*charge_cost + charge_cost /= max(1, (burst - 1)) fire_delay_wielded = fire_delay * 0.75 accuracy_wielded = accuracy + accuracy/4 scoped_accuracy = accuracy_wielded + accuracy/4 @@ -184,12 +187,12 @@ A.damage = min(A.damage, 60) //Caps the maximum damage one shot can do, this matches the laser cannon if(!bypass_degrade) for(var/obj/item/laser_components/modifier/modifier in gun_mods) //This repeats for EVERY MOD, fail chance goes up quadratically with the number of mods - if(prob((gun_mods.len * 2 * damage_coeff)/(max(1,(burst - 1))))) + if(prob((gun_mods.len * damage_coeff)/(max(1,(burst))))) capacitor.degrade(modifier.malus) - if(prob((gun_mods.len * 2 * damage_coeff)/(max(1,(burst - 1))))) + if(prob((gun_mods.len * damage_coeff)/(max(1,(burst))))) focusing_lens.degrade(modifier.malus) - if(prob((33 + capacitor.damage)/(max(1,(burst - 1))))) //Firing a gun with a damaged capacitor risks arcing to other components, damaging them - modifier.degrade(1) + if(prob((5 + capacitor.damage)/(max(1,(burst))))) //Firing a gun with a damaged capacitor risks arcing to other components, damaging them + modifier.degrade(0.2) updatetype(ismob(loc) ? loc : null) return A @@ -228,6 +231,7 @@ /obj/item/gun/energy/laser/prototype/small_fail(var/mob/user) if(capacitor) to_chat(user, SPAN_DANGER("\The [src]'s [capacitor] short-circuits!")) + visible_message(SPAN_DANGER("Sparks fly from \the [src] as it short-circuits!"), range = 6) capacitor.small_fail(user, src) return @@ -339,7 +343,7 @@ . += "Reliability: [initial(l_component.reliability)]
" . += "Damage Modifier: [initial(l_component.damage)]
" . += "Fire Delay Modifier: [initial(l_component.fire_delay)]
" - . += "Shots Modifier: [initial(l_component.fire_delay)]
" + . += "Shots Modifier: [initial(l_component.shots)]
" . += "Burst Modifier: [initial(l_component.burst)]
" . += "Accuracy Modifier: [initial(l_component.accuracy)]
" . += "Repair Tool: [l_repair_name]
" diff --git a/code/modules/projectiles/modular/laser_base.dm b/code/modules/projectiles/modular/laser_base.dm index 95a6fb893ad..97c4c661454 100644 --- a/code/modules/projectiles/modular/laser_base.dm +++ b/code/modules/projectiles/modular/laser_base.dm @@ -2,11 +2,13 @@ icon = 'icons/obj/guns/modular_laser.dmi' icon_state = "bfg" contained_sprite = TRUE - w_class = WEIGHT_CLASS_TINY //A dissasembled gun is easier to carry, this lets people bring bits of their broken gun back to R&D. + w_class = WEIGHT_CLASS_SMALL //A dissasembled gun is easier to carry, this lets people bring bits of their broken gun back to R&D. var/reliability = 0 var/damage = 1 var/fire_delay = 1 var/condition = 0 //inverse health of the component. subtracted from reliability. + var/base_malus = 0 //when modifiers get damaged they do not break, but make other components break faster + var/malus = 0 //subtracted from weapon's overall reliability everytime it's fired var/shots = 1 var/burst = 0 var/accuracy = 0 @@ -22,8 +24,11 @@ /obj/item/laser_components/attackby(obj/item/attacking_item, mob/user) if(!istype(attacking_item, repair_item)) return ..() + if (condition == 0 && malus == base_malus) + to_chat(user, SPAN_WARNING("\The [src] is not damaged.")) + return ..() to_chat(user, SPAN_WARNING("You begin repairing \the [src].")) - if(do_after(user, 20) && repair_module(attacking_item)) + if(do_after(user, rand(2 SECONDS, 6 SECONDS), src, DO_UNIQUE) && repair_module(attacking_item)) to_chat(user, SPAN_NOTICE("You repair \the [src].")) else to_chat(user, SPAN_WARNING("You fail to repair \the [src].")) @@ -36,8 +41,6 @@ desc = "A basic laser weapon modifier." reliability = -5 var/mod_type - var/base_malus = 2 //when modifiers get damaged they do not break, but make other components break faster - var/malus = 2 //subtracted from weapon's overall reliability everytime it's fired var/gun_force = 0 //melee damage of the gun var/chargetime = 0 var/burst_delay = 0 @@ -62,7 +65,7 @@ return if(malus == base_malus) return 0 - if(W.use(5)) + if(W.use(2)) malus = max(malus - 5, base_malus) return 1 return 0 @@ -87,40 +90,44 @@ return if(!condition > 0) return 0 - if(C.use(5)) + if(C.use(2)) condition = max(condition - 5, 0) return 1 return 0 -/obj/item/laser_components/capacitor/proc/small_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) +/obj/item/laser_components/capacitor/proc/small_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 0, 1000*max(prototype.criticality, 1)) return -/obj/item/laser_components/capacitor/proc/medium_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) +/obj/item/laser_components/capacitor/proc/medium_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 0, 1500*max(prototype.criticality, 1)) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] sparks a little angrily as it overloads!"), range = 3) return -/obj/item/laser_components/capacitor/proc/critical_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - qdel(src) +/obj/item/laser_components/capacitor/proc/critical_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 1, 2000*max(prototype.criticality, 1)) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] goes critical in a shower of sparks!"), range = 5) return /obj/item/laser_components/focusing_lens name = "focusing lens" desc = "A basic laser weapon focusing lens." icon_state = "lens" - var/list/dispersion = list(0.6,1.0,1.0,1.0,1.2,0.6,1.0,1.0,1.0,1.2,0.6,1.0,1.0,1.0,1.2,0.6,1.0,1.0,1.0,1.2) + var/list/dispersion = list(0, 5, 10, 15, 20, 25, 30, 35, 40, 45) reliability = 25 - repair_item = /obj/item/stack/nanopaste + repair_item = /obj/item/stack/material/glass /obj/item/laser_components/focusing_lens/condition_hints(mob/user, distance, is_adjacent) . += ..() if(distance <= 1 && condition > 0) . += SPAN_WARNING("\The [src] appears damaged.") -/obj/item/laser_components/focusing_lens/repair_module(var/obj/item/stack/nanopaste/N) - if(!istype(N)) +/obj/item/laser_components/focusing_lens/repair_module(var/obj/item/stack/material/G) + if(!istype(G)) return if(!condition > 0) return 0 - if(N.use(5)) + if(G.use(1)) condition = max(condition - 5, 0) return 1 return 0 diff --git a/code/modules/projectiles/modular/laser_components.dm b/code/modules/projectiles/modular/laser_components.dm index b89032b22b5..0a01f5f1d82 100644 --- a/code/modules/projectiles/modular/laser_components.dm +++ b/code/modules/projectiles/modular/laser_components.dm @@ -44,24 +44,43 @@ shots = 10 reliability = 60 -/obj/item/laser_components/capacitor/nuclear/small_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it - if (M != user) - to_chat(M, SPAN_WARNING("You feel a warm sensation.")) - M.apply_effect(rand(1,10)*(prototype.criticality+1), DAMAGE_RADIATION) + +/obj/item/laser_components/capacitor/reinforced/small_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 0, 1000*max((prototype.criticality / 2), 1)) //This capacitor is the safest you can make. return -/obj/item/laser_components/capacitor/nuclear/medium_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(round((prototype.criticality+1)),src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it - if (M != user) - to_chat(M, SPAN_WARNING("You feel a warm sensation.")) - M.apply_effect(rand(1,40)*(prototype.criticality+1), DAMAGE_RADIATION) +/obj/item/laser_components/capacitor/reinforced/medium_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 0, 1200*max((prototype.criticality / 2), 1)) + visible_message(SPAN_DANGER("\The [src] powering \the [prototype] mostly contains the sparks as it overloads!"), range = 3) return -/obj/item/laser_components/capacitor/nuclear/critical_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(rand(2,6)*(prototype.criticality+1),src)) +/obj/item/laser_components/capacitor/reinforced/critical_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 1, 1600*max((prototype.criticality / 2), 1)) + visible_message(SPAN_DANGER("\The [src] powering \the [prototype] goes critical but contains the worst of the sparks!"), range = 4) + return + +/obj/item/laser_components/capacitor/nuclear/small_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 1, 1000*max(prototype.criticality, 1)) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(0, T)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it + to_chat(M, SPAN_WARNING("You feel a warm sensation.")) + M.apply_damage(rand(1,10)*max(prototype.criticality, 1), DAMAGE_RADIATION) + return + +/obj/item/laser_components/capacitor/nuclear/medium_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] glows ominously as it overloads!"), range = 6) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(round(max(prototype.criticality, 1)),T)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it + to_chat(M, SPAN_WARNING("You feel a warm sensation.")) + M.apply_damage(rand(1,40)*max(prototype.criticality, 1), DAMAGE_RADIATION) + return + +/obj/item/laser_components/capacitor/nuclear/critical_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] goes critical and explodes in a burst of radiation!"), range = 6) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(rand(2,6)*max(prototype.criticality, 1),T)) to_chat(M, SPAN_WARNING("You feel a wave of heat wash over you.")) - M.apply_effect(300*(prototype.criticality+1), DAMAGE_RADIATION) + M.apply_damage(300*max(prototype.criticality, 1), DAMAGE_RADIATION) ..() /obj/item/laser_components/capacitor/teranium @@ -73,16 +92,17 @@ reliability = 55 /obj/item/laser_components/capacitor/teranium/small_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - tesla_zap(prototype, 3, 1000*(prototype.criticality+1)) + tesla_zap(prototype, 2, 1000*max(prototype.criticality, 1)) return /obj/item/laser_components/capacitor/teranium/medium_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - tesla_zap(prototype, round((prototype.criticality+1)*2), 2000*(prototype.criticality+1)) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] shoots random arcs of electricity as it overloads!"), range = 6) + tesla_zap(prototype, round(max(prototype.criticality, 1)*2,1), 2000*max(prototype.criticality, 1)) return /obj/item/laser_components/capacitor/teranium/critical_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/i = 0 to round((prototype.criticality+1))) - tesla_zap(prototype, round((prototype.criticality+1)*2,1), 4000*(prototype.criticality+1)) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] blasts huge lightning bolts in all directions as it goes critical!"), range = 6) + tesla_zap(prototype, round(max(prototype.criticality, 1)*2,1), 4000*max(prototype.criticality, 1), TRUE) ..() /obj/item/laser_components/capacitor/phoron @@ -93,21 +113,37 @@ shots = 25 reliability = 50 -/obj/item/laser_components/capacitor/phoron/small_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it - if (M != user) - to_chat(M, SPAN_WARNING("You feel a warm sensation.")) - M.apply_effect(rand(1,10)*(prototype.criticality+1), DAMAGE_RADIATION) +/obj/item/laser_components/capacitor/phoron/small_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 1, 1000*max(prototype.criticality, 1)) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(0, T)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it + to_chat(M, SPAN_WARNING("You feel a warm sensation.")) + M.apply_damage(rand(1,10)*max(prototype.criticality, 1), DAMAGE_RADIATION) return -/obj/item/laser_components/capacitor/phoron/medium_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - empulse(get_turf(src), 0, round((prototype.criticality+1)*3,1)) - explosion(get_turf(prototype), 0, 0, round((prototype.criticality+1)*2,1)) +/obj/item/laser_components/capacitor/phoron/medium_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + if (user) + visible_message(SPAN_DANGER("\The [src] powering \the [prototype] hisses in \the [user]'s hand and explosively vents hot phoron!"), range = 6) + if (prototype in list(user.l_hand)) + user.apply_damage(25*max(prototype.criticality, 1), DAMAGE_BRUTE, BP_L_HAND, prototype, DAMAGE_FLAG_EXPLODE) + else if (prototype in list(user.r_hand)) + user.apply_damage(25*max(prototype.criticality, 1), DAMAGE_BRUTE, BP_R_HAND, prototype, DAMAGE_FLAG_EXPLODE) + else + visible_message(SPAN_DANGER("\The [src] powering \the [prototype] hisses and explosively vents hot phoron!"), range = 6) + explosion(get_turf(prototype), 0, 0, round(max(prototype.criticality, 1)*2,1)) return -/obj/item/laser_components/capacitor/phoron/critical_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - empulse(get_turf(src), round((prototype.criticality+1),1), round((prototype.criticality+1)*4,1)) - explosion(get_turf(prototype), 0, round((prototype.criticality+1),1), round((prototype.criticality+1)*3,1)) +/obj/item/laser_components/capacitor/phoron/critical_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + if (user) + visible_message(SPAN_DANGER("\The [src] powering \the [prototype] goes critical in \the [user]'s hand causing a massive explosion!"), range = 6) + if (prototype in list(user.l_hand)) + user.apply_damage(40*max(prototype.criticality, 1), DAMAGE_BRUTE, BP_L_HAND, prototype, DAMAGE_FLAG_EXPLODE) + else if (prototype in list(user.r_hand)) + user.apply_damage(40*max(prototype.criticality, 1), DAMAGE_BRUTE, BP_R_HAND, prototype, DAMAGE_FLAG_EXPLODE) + else + visible_message(SPAN_DANGER("\The [src] powering \the [prototype] goes critical causing a massive explosion!"), range = 6) + empulse(get_turf(src), round(max(prototype.criticality, 1),1), round(max(prototype.criticality, 1)*4,1)) + explosion(get_turf(prototype), 0, round(max(prototype.criticality, 1),1), round(max(prototype.criticality, 1)*3,1)) ..() /obj/item/laser_components/capacitor/bluespace @@ -118,21 +154,27 @@ shots = 30 reliability = 45 -/obj/item/laser_components/capacitor/bluespace/small_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(round((prototype.criticality+1),1),src)) - empulse(get_turf(M), 0, round((prototype.criticality+1)*2,1)) +/obj/item/laser_components/capacitor/bluespace/small_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + tesla_zap(prototype, 1, 1000*max(prototype.criticality, 1)) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(round(max(prototype.criticality, 1),1),T)) + do_teleport(M, get_turf(M), rand(1,3)*round(max(prototype.criticality, 1),1), asoundin = 'sound/effects/phasein.ogg') return -/obj/item/laser_components/capacitor/bluespace/medium_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(round(3*(prototype.criticality+1),1),src)) - empulse(get_turf(M), 0, round((prototype.criticality+1)*2,1)) - do_teleport(M, get_turf(M), rand(1,3)*round((prototype.criticality+1),1), asoundin = 'sound/effects/phasein.ogg') +/obj/item/laser_components/capacitor/bluespace/medium_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] flickers then vanishes along with everything around it!"), range = 6) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(round(3*max(prototype.criticality, 1),1),T)) + empulse(get_turf(M), 0, round(max(prototype.criticality, 1)*2,1)) + do_teleport(M, get_turf(M), rand(2,6)*round(max(prototype.criticality, 1),1), asoundin = 'sound/effects/phasein.ogg') return -/obj/item/laser_components/capacitor/bluespace/critical_fail(var/mob/user, var/obj/item/gun/energy/laser/prototype/prototype) - for (var/mob/living/M in range(round(6*(prototype.criticality+1),1),src)) - empulse(get_turf(M), 0, round((prototype.criticality+1)*4,1)) - do_teleport(M, get_turf(M), rand(6,18)*round((prototype.criticality+1),1), asoundin = 'sound/effects/phasein.ogg') +/obj/item/laser_components/capacitor/bluespace/critical_fail(var/mob/living/user, var/obj/item/gun/energy/laser/prototype/prototype) + visible_message(SPAN_DANGER("\The [src] in \the [prototype] implodes in a catastrophic spatial anomaly, teleporting everything around it!"), range = 6) + var/turf/T = get_turf(src) + for (var/mob/living/M in range(round(6*max(prototype.criticality, 1),1),T)) + empulse(get_turf(M), 0, round(max(prototype.criticality, 1)*4,1)) + do_teleport(M, get_turf(M), rand(4,12)*round(max(prototype.criticality, 1),1), asoundin = 'sound/effects/phasein.ogg') ..() //Lenses @@ -140,7 +182,7 @@ name = "splitter lens" desc = "A focusing lens that splits the beam into several sub-beams." icon_state = "splitter_lens" - dispersion = list(1,-1,2,-2,3,-3,4,-4,5,-5,6,-6,7,-7,8,-8,9,-9,10,-10,11,-11,12,-12,13,-13,14,-14,15,-15) + dispersion = list(5, 15, 25, 35, 45, 55, 65, 75) burst = 4 accuracy = -1 reliability = 35 @@ -172,6 +214,8 @@ desc = "An internal nuclear reactor which recharges the energy cell of the weapon. Feels tingly." icon_state = "mini_reactor" mod_type = MOD_NUCLEAR_CHARGE + base_malus = 2 + malus = 2 reliability = -10 criticality = 1.5 @@ -240,8 +284,6 @@ name = "reinforced barrel" desc = "Reinforcement along the barrel extends the longevity of the prototype." reliability = 25 - base_malus = 0 - malus = 0 icon_state = "reinforced_barrel" /obj/item/laser_components/modifier/barrel/nano @@ -417,8 +459,9 @@ /obj/item/laser_components/modulator/blaster name = "blaster-bolt modulator" - desc = "Modulates the beam into firing disparate energy bolts." - projectile = /obj/projectile/energy/blaster/incendiary + desc = "Modulates the beam into firing disparate energy bolts designed to burn through armour." + projectile = /obj/projectile/energy/blaster/incendiary/light + damage = 0.8 //Specialist anti-armour incendiary projectile. icon_state = "lensatic" origin_tech = list(TECH_COMBAT = 2, TECH_PHORON = 4) diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index cf6d2c969ae..cf3c272699c 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -193,6 +193,12 @@ armor_penetration = 60 incinerate = 2 +/obj/projectile/energy/blaster/incendiary/light + icon_state = "laser" + damage = 30 + armor_penetration = 35 + incinerate = 1 + /obj/projectile/energy/disruptorskrell // for nralakk fed consular pistol name = "disruptor bolt" icon_state = "bluelaser" diff --git a/code/modules/research/weaponsanalyzer.dm b/code/modules/research/weaponsanalyzer.dm index 73db862b20f..57efc61d46c 100644 --- a/code/modules/research/weaponsanalyzer.dm +++ b/code/modules/research/weaponsanalyzer.dm @@ -188,12 +188,14 @@ if(istype(gun, /obj/item/gun/energy/laser/prototype)) var/obj/item/gun/energy/laser/prototype/E_prototype = gun var/list/mods = list() - var/l_modified_damage = 1 //E_prototype.capacitor.damage * E_prototype.modulator.damage + var/l_modified_damage = 1 / (max(1, gun.burst - 1)) //E_prototype.capacitor.damage * E_prototype.modulator.damage var/l_modified_max_shots = 1 //E_prototype.capacitor.shots for(var/i in list(E_prototype.capacitor, E_prototype.focusing_lens, E_prototype.modulator) + E_prototype.gun_mods) var/obj/item/laser_components/l_component = i - l_modified_damage *= l_component.damage - l_modified_max_shots *= l_component.shots + if (l_component.damage != 0) + l_modified_damage *= l_component.damage + if (l_component.shots != 0) + l_modified_max_shots *= l_component.shots var/l_repair_name = initial(l_component.repair_item.name) ? initial(l_component.repair_item.name) : "nothing" mods += list(list( "name" = initial(l_component.name), @@ -205,7 +207,7 @@ "accuracy_modifier" = initial(l_component.accuracy), "repair_tool" = l_repair_name )) - data["gun"]["damage"] = l_modified_damage + data["gun"]["damage"] = min(60, l_modified_damage) data["gun"]["max_shots"] = l_modified_max_shots data["gun_mods"] = mods diff --git a/html/changelogs/Fenodyree-ModLaserFixesAndNerfs.yml b/html/changelogs/Fenodyree-ModLaserFixesAndNerfs.yml new file mode 100644 index 00000000000..50f21a51ca6 --- /dev/null +++ b/html/changelogs/Fenodyree-ModLaserFixesAndNerfs.yml @@ -0,0 +1,69 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +author: Fenodyree + +delete-after: True + +changes: + - bugfix: "Fixes laser shotguns having no dispersion." + - bugfix: "Fixes laser shotguns having no delay between shots." + - bugfix: "Fixes mod laser bluespace capacitors not teleporting you." + - bugfix: "Fixes mod laser phoron capacitors not hurting when they explode." + - bugfix: "Fixes mod laser malfunction messages not displaying." + - bugfix: "Fixes mod laser wielded firedelay." + - bugfix: "Fixes being able to spam click to repair mod laser components." + - bugfix: "Fixes being able to attempt a repair on undamaged components." + - bugfix: "Fixes the weapons analyzer to correctly display damage on burst fire weapons." + - bugfix: "The power capacity of the modlasers is no longer multiplied by the shot count. Instead burst fire reduces power cost." + - bugfix: "Capacitors no longer get deleted when at reliability 0 as this broke all other components. You can keep shooting until it kills you." + - rscadd: "Adds new messages for mod laser malfunctions, visible to everyone nearby." + - rscadd: "Adds a locker that spawns with boxes of mod laser components, mostly for testing purposes." + - balance: "Modifiers no longer break immediately, they instead degrade over multiple shots." + - balance: "Makes mod laser lenses repairable with glass or reinforced glass." + - balance: "Adds an electric shock on all minor capacitor failures, as an instant consequence, radiation was too slow to affect an in progress fight." + - balance: "Adds a direct damage component to phoron capacitor overloads, if the gun is being held." + - balance: "Reduces the damage of mod laser blasters by 20%, cuts their AP in half and halves the firestacks they cause." + - balance: "Critical capacitor failures are now very dangerous, probably deadly without apporiate protection or medical help."