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." + +