diff --git a/code/__DEFINES/modular_guns.dm b/code/__DEFINES/modular_guns.dm
index 8a268ea1c14..162908f45b2 100644
--- a/code/__DEFINES/modular_guns.dm
+++ b/code/__DEFINES/modular_guns.dm
@@ -8,9 +8,9 @@
///The maximum improvement that can be applied to a weapon component.
#define IMPROVEMENT_CAP 100
///The maximum increase an individual variable can recieve over it's initial value.
-#define INCREASE_CAP 2
+#define INCREASE_CAP 1.5
///The maximum decrease an individual variable can recieve under it's initial value.
-#define DECREASE_CAP 0.2
+#define DECREASE_CAP 0.5
///All improvements are multiplied by this value, tweak down if they are too strong, up if they are too weak.
#define IMPROVEMENT_MULTIPLIER 1
diff --git a/code/modules/projectiles/guns/energy/modular.dm b/code/modules/projectiles/guns/energy/modular.dm
index fb2ed61252a..9d3c7701d3c 100644
--- a/code/modules/projectiles/guns/energy/modular.dm
+++ b/code/modules/projectiles/guns/energy/modular.dm
@@ -387,9 +387,12 @@
while(improvement_potential > 0 && damaged_components.len)
var/list/upgradable_components = list()
- for(var/obj/item/laser_components/component in damaged_components)
- if(component.total_improved < IMPROVEMENT_CAP)
- upgradable_components += component
+ for(var/obj/item/laser_components/component in damaged_components) //Only give it improvement potential if it's damaged.
+ if((component.total_improved + component.improvement_potential) < IMPROVEMENT_CAP) //Only give it improvement potential if it doesn't have enough to hit cap.
+ if(component.increasable_stats.len || component.decreaseable_stats.len) //Don't give it to components with nothing to improve.
+ upgradable_components += component
+ else
+ damaged_components.Remove(component) //If a component has reached the improvement cap, it can't be improved anymore.
if(!upgradable_components.len)
to_chat(user, SPAN_WARNING("There's nothing to improve on the components of this gun."))
@@ -527,10 +530,55 @@
return 1
/obj/item/gun/energy/laser/prototype/get_print_info()
- . = ..(FALSE)
+ . = ""
+
+ var/l_modified_damage = 1 / max(1, burst - 1)
+ var/l_modified_max_shots = 1
+ for(var/i in list(capacitor, focusing_lens, modulator) + gun_mods)
+ var/obj/item/laser_components/l_component = i
+ if(!l_component)
+ continue
+
+ if(l_component.damage != 0)
+ l_modified_damage *= l_component.damage
+ if(l_component.shots != 0)
+ l_modified_max_shots *= l_component.shots
+
+ var/obj/projectile/P = new projectile_type
+ . += "Max Shots: [round(l_modified_max_shots)]
"
+ . += "Recharge Type: [self_recharge ? "self recharging" : "not self recharging"]
"
+ if(self_recharge)
+ . += "Recharge Time: [initial(recharge_time)]
"
+ . += "
Primary Projectile
"
+ . += "Damage: [round(min(60, l_modified_damage), 1)]
"
+ . += "Damage Type: [initial(P.damage_type)]
"
+ . += "Blocked by Armor Type: [initial(P.check_armor)]
"
+ . += "Stuns: [initial(P.stun) ? "true" : "false"]
"
+ if(initial(P.shrapnel_type))
+ var/obj/shrapnel = new P.shrapnel_type
+ . += "Shrapnel Type: [shrapnel.name]
"
+ . += "Armor Penetration: [initial(P.armor_penetration)]%
"
+ . += "Burst: [burst]
"
+ . += "Reliability: [reliability]
"
+
+ if(secondary_projectile_type)
+ var/obj/projectile/P_second = new secondary_projectile_type
+ . += "
Secondary Projectile
"
+ . += "Damage: [initial(P_second.damage)]
"
+ . += "Damage Type: [initial(P_second.damage_type)]
"
+ . += "Blocked by Armor Type: [initial(P_second.check_armor)]
"
+ . += "Stuns: [initial(P_second.stun) ? "true" : "false"]
"
+ if(initial(P_second.shrapnel_type))
+ var/obj/shrapnel_second = new P_second.shrapnel_type
+ . += "Shrapnel Type: [shrapnel_second.name]
"
+ . += "Armor Penetration: [initial(P_second.armor_penetration)]%
"
+
+ . += "
"
for(var/i in list(capacitor, focusing_lens, modulator) + gun_mods)
var/obj/item/laser_components/l_component = i
+ if(!l_component)
+ continue
. += "
Component Name: [initial(l_component.name)]
"
var/l_repair_name = initial(l_component.repair_item.name) ? initial(l_component.repair_item.name) : "nothing"
diff --git a/code/modules/projectiles/modular/laser_base.dm b/code/modules/projectiles/modular/laser_base.dm
index ac7f1810f8e..f960a7cbf5c 100644
--- a/code/modules/projectiles/modular/laser_base.dm
+++ b/code/modules/projectiles/modular/laser_base.dm
@@ -42,7 +42,13 @@
condition = reliability
/obj/item/laser_components/proc/handle_improvement(var/skill_level, var/mob/user)
- while (improvement_potential > 0)
+
+ if (total_improved >= IMPROVEMENT_CAP)
+ to_chat(user, SPAN_NOTICE("You don't see any way to improve \the [src] any further."))
+ improvement_potential = 0
+ return
+
+ while (improvement_potential > 0 && total_improved < IMPROVEMENT_CAP)
var/improvement = min(abs(improvement_potential / 100), 0.2) //Caps improvement from a single repair to 20%. This spreads the effect out across multiple stats
var/stat_direction = 1
@@ -66,8 +72,20 @@
break //No stats to improve, it shouldn't be possible to have improvement potential and no stats to improve, but just in case.
if (stat_name in src.vars)
+ var/initial_value = initial(src.vars[stat_name])
improvement_potential -= improvement * 100 //Decreases improvement potential before any skill modifiers.
+ if (initial_value < 0) //If the stat begins negative, such as base_malus for heat vents, handle comparisons by sign.
+ if (stat_direction > 0 && src.vars[stat_name] >= (initial_value * DECREASE_CAP))
+ continue
+ if (stat_direction < 0 && src.vars[stat_name] <= (initial_value * INCREASE_CAP))
+ continue
+ else
+ if (src.vars[stat_name] >= (initial_value * INCREASE_CAP) && stat_direction > 0) //It is possible to waste improvement potential by hitting the cap on a stat, this is fine, it should be harder to improve a component that's already of high quality.
+ continue
+ if (src.vars[stat_name] <= (initial_value * DECREASE_CAP) && stat_direction < 0)
+ continue
+
switch(skill_level ? skill_level : 6)
if(-INFINITY to 2)
improvement *= (rand(-5, -1) / 10) //Always damage it.
@@ -80,21 +98,37 @@
if(6 to INFINITY)
improvement *= (rand(8, 12) / 10)
- if (src.vars[stat_name] > (initial(src.vars[stat_name]) * INCREASE_CAP) && stat_direction > 0) //It is possible to waste improvement potential by hitting the cap on a stat, this is fine, it should be harder to improve a component that's already of high quality.
- continue
- if (src.vars[stat_name] < (initial(src.vars[stat_name]) * DECREASE_CAP) && stat_direction < 0)
- continue
-
- src.vars[stat_name] += stat_direction * abs(initial(src.vars[stat_name]) * improvement) //Adds improvement % of the initial value to the stat.
+ src.vars[stat_name] += stat_direction * abs(initial_value * improvement) //Adds improvement % of the initial value to the stat.
if (improvement > 0)
- to_chat(user, SPAN_NOTICE("Your careful repairs to \the [src] [stat_direction > 0 ? "increase" : "decrease"] its [replacetext(stat_name, "_", " ")] by [improvement * 100] percent!"))
- total_improved += improvement
+ total_improved += improvement * 100
+ if (initial_value < 0)
+ if (stat_direction > 0 && src.vars[stat_name] >= initial_value * DECREASE_CAP)
+ to_chat(user, SPAN_NOTICE("Your repairs to \the [src] have improved its [replacetext(stat_name, "_", " ")] as far as you think is possible."))
+ else if (stat_direction < 0 && src.vars[stat_name] <= initial_value * INCREASE_CAP)
+ to_chat(user, SPAN_NOTICE("Your repairs to \the [src] have improved its [replacetext(stat_name, "_", " ")] as far as you think is possible."))
+ else
+ to_chat(user, SPAN_NOTICE("Your careful repairs to \the [src] [stat_direction > 0 ? "increase" : "decrease"] its [replacetext(stat_name, "_", " ")] by [improvement * 100] percent!"))
+ else
+ if(src.vars[stat_name] >= initial_value * INCREASE_CAP && stat_direction > 0)
+ to_chat(user, SPAN_NOTICE("Your repairs to \the [src] have improved its [replacetext(stat_name, "_", " ")] as far as you think is possible."))
+ else if(src.vars[stat_name] <= initial_value * DECREASE_CAP && stat_direction < 0)
+ to_chat(user, SPAN_NOTICE("Your repairs to \the [src] have improved its [replacetext(stat_name, "_", " ")] as far as you think is possible."))
+ else
+ to_chat(user, SPAN_NOTICE("Your careful repairs to \the [src] [stat_direction > 0 ? "increase" : "decrease"] its [replacetext(stat_name, "_", " ")] by [improvement * 100] percent!"))
+
else if (improvement == 0)
to_chat(user, SPAN_NOTICE("Your repairs to \the [src], don't seem to improve it, but at least you didn't make it worse."))
else
to_chat(user, SPAN_WARNING("Your repairs to \the [src] end up damaging it!"))
+ else
+ break //The stat to improve isn't on this component, something went wrong with the lists of stats or the component itself.
+
+ if (total_improved > IMPROVEMENT_CAP)
+ improvement_potential = 0
+ to_chat(user, SPAN_NOTICE("You have improved \the [src] as much as you can."))
+
/obj/item/laser_components/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
. = ..()
if(distance > 1)
@@ -150,9 +184,21 @@
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]."))
+
var/skill_level = (GET_SKILL_LEVEL(user, FIREARMS_SKILL_COMPONENT) + GET_SKILL_LEVEL(user, RESEARCH_SKILL_COMPONENT))
- if(do_after(user, rand(2 SECONDS, 6 SECONDS), src, DO_UNIQUE) && repair_module(attacking_item, skill_level, user))
+
+ if(attacking_item.tool_behaviour == TOOL_WELDER)
+ var/obj/item/weldingtool/WT = attacking_item
+ if(WT.isOn() && WT.use_tool(src, user, rand(2 SECONDS, (10 - skill_level) SECONDS), volume = 50) && WT.use(0, user) && repair_module(attacking_item, skill_level, user))
+ user.visible_message(
+ SPAN_WARNING("[user] begins repairing \the [src]."),
+ SPAN_NOTICE("You begin repairing \the [src]."),
+ "You hear a welding torch on metal."
+ )
+ else
+ to_chat(user, SPAN_WARNING("You fail to repair \the [src]."))
+
+ else if(do_after(user, rand(2 SECONDS, (10 - skill_level) SECONDS), src, DO_UNIQUE) && repair_module(attacking_item, skill_level, user)) //Used if the repair item is not a tool.
to_chat(user, SPAN_NOTICE("You repair \the [src]."))
else
to_chat(user, SPAN_WARNING("You fail to repair \the [src]."))
@@ -189,7 +235,7 @@
return
if(malus == base_malus)
return 0
- if(W.use(2))
+ if(W.use(1)) //Welders burn fuel while active
handle_improvement(skill_level, user)
malus = max(malus - 5, base_malus)
return 1
@@ -332,8 +378,10 @@
var/success = FALSE
if(!istype(A))
return ..()
- if(!ready_to_craft)
- to_chat(user, SPAN_WARNING("You cannot modify \the [src] by hand, you need to use a weapons analyzer."))
+
+ var/skill_level = (GET_SKILL_LEVEL(user, FIREARMS_SKILL_COMPONENT) + GET_SKILL_LEVEL(user, RESEARCH_SKILL_COMPONENT))
+ if(!ready_to_craft && skill_level < 5)
+ to_chat(user, SPAN_WARNING("You cannot modify \the [src] by hand at your current skill level, you need to use a weapons analyzer."))
return
if(ismodifier(A) && gun_mods.len < modifier_cap)
@@ -389,9 +437,7 @@
/obj/item/laser_assembly/proc/finish()
- var/obj/structure/machinery/r_n_d/weapons_analyzer/an = analyzer.resolve()
- if(!an)
- return FALSE
+ var/obj/structure/machinery/r_n_d/weapons_analyzer/an = analyzer ? analyzer.resolve() : null
var/obj/item/gun/energy/laser/prototype/A = new /obj/item/gun/energy/laser/prototype
A.icon_state = icon_state
@@ -410,8 +456,11 @@
mod.forceMove(A)
if(mod.gun_overlay)
A.underlays += mod.gun_overlay
- A.forceMove(an)
- an.item = A
+ if(an)
+ A.forceMove(an)
+ an.item = A
+ else
+ A.forceMove(get_turf(src))
A.updatetype()
A.try_recharge()
A.pin = null
diff --git a/code/modules/projectiles/modular/laser_components.dm b/code/modules/projectiles/modular/laser_components.dm
index f0483690043..3d22b02e776 100644
--- a/code/modules/projectiles/modular/laser_components.dm
+++ b/code/modules/projectiles/modular/laser_components.dm
@@ -303,7 +303,7 @@
accuracy = -1
icon_state = "rotating_lens"
increasable_stats = list()
- decreaseable_stats = list("fire_delay", "chargetime")
+ decreaseable_stats = list("burst_delay", "chargetime")
/obj/item/laser_components/modifier/scope
name = "telescopic sight"
diff --git a/code/modules/research/weaponsanalyzer.dm b/code/modules/research/weaponsanalyzer.dm
index 1f0421a5e15..8b30ceee471 100644
--- a/code/modules/research/weaponsanalyzer.dm
+++ b/code/modules/research/weaponsanalyzer.dm
@@ -23,6 +23,13 @@
var/mob/living/carbon/human/H = user
+ if(default_deconstruction_screwdriver(user, attacking_item))
+ return TRUE
+ if(default_deconstruction_crowbar(user, attacking_item))
+ return TRUE
+ if(default_part_replacement(user, attacking_item))
+ return TRUE
+
if(istype(attacking_item, /obj/item/gun))
check_swap(user, attacking_item)
item = attacking_item
@@ -55,7 +62,8 @@
addtimer(CALLBACK(src, PROC_REF(reset)), 15)
process = TRUE
update_icon()
-
+ else if(istype(attacking_item, /obj/item/combitool))
+ return
else if(attacking_item)
check_swap(user, attacking_item)
item = attacking_item
@@ -120,7 +128,7 @@
if(istype(item, /obj/item/laser_assembly))
var/obj/item/laser_assembly/A = item
A.update_icon()
- icon_state = process ? "[icon_state]_working" : "[icon_state]_on"
+ icon_state = process ? "[icon_state]_working" : "[icon_state]_on"
Icon_used = new /icon(item.icon, item.icon_state)
else if(item)
icon_state = "[icon_state]_on"
diff --git a/html/changelogs/Fenodyree-ModlaserFixes.yml b/html/changelogs/Fenodyree-ModlaserFixes.yml
new file mode 100644
index 00000000000..a908d9e4700
--- /dev/null
+++ b/html/changelogs/Fenodyree-ModlaserFixes.yml
@@ -0,0 +1,17 @@
+author: Fenodyree
+
+delete-after: True
+
+changes:
+ - bugfix: "Fixes modular lasers improvement cap."
+ - bugfix: "Fixes negative initial values being handled incorrectly."
+ - bugfix: "Fixes some repair edge cases."
+ - bugfix: "Fixes welding repairs not needing eye protection."
+ - bugfix: "Fixes gattling laser mod having the wrong improvable variables."
+ - bugfix: "Fixes the weapon analyzer printout calculating modlaser stats incorrectly."
+ - bugfix: "Fixes high skill users not being able to field repair modlasers."
+ - bugfix: "Fixes the weapon analyzer ripping your combitool out of your hand."
+ - bugfix: "Fixes the weapon analyzer not being deconstructable."
+ - balance: "Drops the per var improvement cap by 50%, multiplicative scaling is no joke."
+
+