diff --git a/code/datums/repositories/radiation.dm b/code/datums/repositories/radiation.dm index 4755b982ec..5d06eccc77 100644 --- a/code/datums/repositories/radiation.dm +++ b/code/datums/repositories/radiation.dm @@ -116,7 +116,7 @@ var/global/repository/radiation/radiation_repository = new() else if(O.density) //So open doors don't get counted var/material/M = O.get_material() if(!M) continue - cached_rad_resistance += M.weight + cached_rad_resistance += M.radiation_resistance // Looks like storing the contents length is meant to be a basic check if the cache is stale due to items enter/exiting. Better than nothing so I'm leaving it as is. ~Leshana radiation_repository.resistance_cache[src] = (length(contents) + 1) diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index 0f76f6172e..d212851071 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -94,6 +94,13 @@ apply_colour = 1 no_variants = FALSE +/obj/item/stack/material/lead + name = "lead" + icon_state = "sheet-adamantine" + default_type = "lead" + apply_colour = 1 + no_variants = TRUE + /obj/item/stack/material/sandstone name = "sandstone brick" icon_state = "sheet-sandstone" diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index af5e1b7475..2fa2b1dbbe 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -99,6 +99,7 @@ var/list/name_to_material var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10. var/list/composite_material // If set, object matter var will be a list containing these values. var/luminescence + var/radiation_resistance = 20 // Radiation resistance, used in calculating how much radiation a material absorbs. Equivlent to weight, but does not affect weaponry. // Placeholder vars for the time being, todo properly integrate windows/light tiles/rods. var/created_window @@ -236,6 +237,7 @@ var/list/name_to_material weight = 22 stack_origin_tech = list(TECH_MATERIAL = 5) door_icon_base = "stone" + radiation_resistance = 80 //dense, so it's okay-ish as rad shielding. /material/diamond name = "diamond" @@ -261,6 +263,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 4) sheet_singular_name = "ingot" sheet_plural_name = "ingots" + radiation_resistance = 120 //gold is dense. /material/gold/bronze //placeholder for ashtrays name = "bronze" @@ -276,7 +279,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 3) sheet_singular_name = "ingot" sheet_plural_name = "ingots" - + radiation_resistance = 22 //R-UST port /material/supermatter name = "supermatter" @@ -337,6 +340,7 @@ var/list/name_to_material door_icon_base = "stone" sheet_singular_name = "brick" sheet_plural_name = "bricks" + radiation_resistance = 22 /material/stone/marble name = "marble" @@ -345,6 +349,7 @@ var/list/name_to_material hardness = 100 integrity = 201 //hack to stop kitchen benches being flippable, todo: refactor into weight system stack_type = /obj/item/stack/material/marble + radiation_resistance = 26 /material/steel name = DEFAULT_WALL_MATERIAL @@ -391,6 +396,7 @@ var/list/name_to_material conductivity = 13 // For the purposes of balance. stack_origin_tech = list(TECH_MATERIAL = 2) composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo + radiation_resistance = 60 //Plasteel is presumably dense and is the dominant material used in the engine. Still not great. // Very rare alloy that is reflective, should be used sparingly. /material/durasteel @@ -408,6 +414,7 @@ var/list/name_to_material reflectivity = 0.7 // Not a perfect mirror, but close. stack_origin_tech = list(TECH_MATERIAL = 8) composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug + radiation_resistance = 120 //it reflects XRAY LASERS. /material/plasteel/titanium name = "titanium" @@ -436,6 +443,7 @@ var/list/name_to_material window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2) created_window = /obj/structure/window/basic rod_product = /obj/item/stack/material/glass/reinforced + radiation_resistance = 15 /material/glass/build_windows(var/mob/living/user, var/obj/item/stack/used_stack) @@ -527,6 +535,7 @@ var/list/name_to_material created_window = /obj/structure/window/reinforced wire_product = null rod_product = null + radiation_resistance = 30 /material/glass/phoron name = "borosilicate glass" @@ -554,6 +563,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 2) composite_material = list() //todo rod_product = null + radiation_resistance = 30 /material/plastic name = "plastic" @@ -568,6 +578,7 @@ var/list/name_to_material conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator. melting_point = T0C+371 //assuming heat resistant plastic stack_origin_tech = list(TECH_MATERIAL = 3) + radiation_resistance = 12 /material/plastic/holographic name = "holoplastic" @@ -618,6 +629,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 2) sheet_singular_name = "ingot" sheet_plural_name = "ingots" + radiation_resistance = 27 /material/iron name = "iron" @@ -627,6 +639,17 @@ var/list/name_to_material conductivity = 10 sheet_singular_name = "ingot" sheet_plural_name = "ingots" + radiation_resistance = 22 + +/material/lead + name = "lead" + stack_type = /obj/item/stack/material/lead + icon_colour = "#273956" + weight = 35 + conductivity = 10 + sheet_singular_name = "ingot" + sheet_plural_name = "ingots" + radiation_resistance = 350 //actual radiation shielding, yay... // Adminspawn only, do not let anyone get this. /material/alienalloy @@ -640,6 +663,7 @@ var/list/name_to_material hardness = 500 weight = 500 protectiveness = 80 // 80% + radiation_resistance = 500 // Likewise. /material/alienalloy/elevatorium @@ -697,6 +721,7 @@ var/list/name_to_material destruction_desc = "splinters" sheet_singular_name = "plank" sheet_plural_name = "planks" + radiation_resistance = 18 /material/wood/log name = MAT_LOG @@ -739,7 +764,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 1) door_icon_base = "wood" destruction_desc = "crumples" - + radiation_resistance = 1 /material/snow name = MAT_SNOW stack_type = /obj/item/stack/material/snow @@ -756,7 +781,7 @@ var/list/name_to_material destruction_desc = "crumples" sheet_singular_name = "pile" sheet_plural_name = "pile" //Just a bigger pile - + radiation_resistance = 1 /material/cloth //todo name = "cloth" stack_origin_tech = list(TECH_MATERIAL = 2) diff --git a/code/modules/power/fusion/core/_core.dm b/code/modules/power/fusion/core/_core.dm index 760c46ea93..7f81b70ffd 100644 --- a/code/modules/power/fusion/core/_core.dm +++ b/code/modules/power/fusion/core/_core.dm @@ -77,7 +77,7 @@ var/list/fusion_cores = list() if(owned_field) icon_state = "core0" if(force_rupture || owned_field.plasma_temperature > 1000) - owned_field.Rupture() + owned_field.MRC() else owned_field.RadiateAll() qdel(owned_field) diff --git a/code/modules/power/fusion/core/core_field.dm b/code/modules/power/fusion/core/core_field.dm index 37351c53af..ef1c3716fa 100644 --- a/code/modules/power/fusion/core/core_field.dm +++ b/code/modules/power/fusion/core/core_field.dm @@ -1,6 +1,7 @@ #define FUSION_ENERGY_PER_K 20 #define FUSION_MAX_ENVIRO_HEAT 5000 //raise this if you want the reactor to dump more energy into the atmosphere -#define PLASMA_TEMP_RADIATION_DIVISIOR 15 //radiation divisior. plasma temp / divisor = radiation. +#define PLASMA_TEMP_RADIATION_DIVISIOR 20 //radiation divisior. plasma temp / divisor = radiation. + /obj/effect/fusion_em_field name = "electromagnetic field" @@ -19,6 +20,8 @@ var/tick_instability = 0 var/percent_unstable = 0 var/stable = 1 + var/id_tag + var/critical = 0 var/obj/machinery/power/fusion_core/owned_core var/list/dormant_reactant_quantities = list() @@ -31,7 +34,8 @@ /obj/structure/cable, /obj/machinery/atmospherics, /obj/machinery/air_sensor, - /mob/observer/dead + /mob/observer/dead, + /obj/machinery/power/hydromagnetic_trap ) var/light_min_range = 2 @@ -52,7 +56,7 @@ owned_core = new_owned_core if(!owned_core) qdel(src) - + id_tag = owned_core.id_tag //create the gimmicky things to handle field collisions var/obj/effect/fusion_particle_catcher/catcher @@ -194,37 +198,46 @@ if(percent_unstable >= 1) owned_core.Shutdown(force_rupture=1) else - if(percent_unstable > 0.5 && prob(percent_unstable*100)) + if(percent_unstable > 0.1 && prob(percent_unstable*100)) if(plasma_temperature < 2000) visible_message("\The [src] ripples uneasily, like a disturbed pond.") else var/flare var/fuel_loss var/rupture - if(percent_unstable < 0.2) + if(percent_unstable > 0.2) visible_message("\The [src] ripples uneasily, like a disturbed pond.") - fuel_loss = prob(5) - flare = prob(50) - else if(percent_unstable < 0.9) + flare = prob(25) + else if(percent_unstable > 0.5) visible_message("\The [src] undulates violently, shedding plumes of plasma!") flare = prob(50) fuel_loss = prob(20) rupture = prob(5) - else + else if(percent_unstable > 0.8) visible_message("\The [src] is wracked by a series of horrendous distortions, buckling and twisting like a living thing!") flare = 1 fuel_loss = prob(50) rupture = prob(25) if(rupture) - owned_core.Shutdown(force_rupture=1) + if(prob(80)) + MagneticQuench() + return + else if(prob(15)) + MRC() + return + else if(prob(5)) + QuantumFluxCascade() + return + else if(prob(5)) + BluespaceQuenchEvent() + return else var/lost_plasma = (plasma_temperature*percent_unstable) radiation += lost_plasma if(flare) - radiation += plasma_temperature/2 - plasma_temperature -= lost_plasma - + spawn(1) + emflare() if(fuel_loss) for(var/particle in dormant_reactant_quantities) var/lost_fuel = dormant_reactant_quantities[particle]*percent_unstable @@ -234,17 +247,19 @@ dormant_reactant_quantities.Remove(particle) Radiate() return - -/obj/effect/fusion_em_field/proc/Rupture() - visible_message("\The [src] shudders like a dying animal before flaring to eye-searing brightness and rupturing!") - set_light(15, 15, "#CCCCFF") - empulse(get_turf(src), ceil(plasma_temperature/1000), ceil(plasma_temperature/300)) - sleep(5) - global_announcer.autosay("WARNING: FIELD RUPTURE IMMINENT!", "Containment Monitor") - RadiateAll() - explosion(get_turf(owned_core),-1,-1,8,10) // Blow out all the windows. - return - +/*/obj/effect/fusion_em_field/proc/CheckCriticality() + if (plasma_temperature > 70000) + critical += 0.2 + else if (instability > 0.45) + critical += 0.6 + if(critical >= 25 && prob(percent_unstable*100)) + if (critical >= 90) + visible_message("\The [src] rumbles and quivers violently, threatening to break free!") + else if(critical >= 50) + visible_message("\The [src] rumbles and quivers energetically, the walls distorting slightly.") + else if(critical >= 25) + visible_message("\The [src] rumbles and quivers slightly, vibrating the deck.") +*/ /obj/effect/fusion_em_field/proc/ChangeFieldStrength(var/new_strength) var/calc_size = 1 if(new_strength <= 50) @@ -490,19 +505,19 @@ //All procs below this point are called in _core.dm, starting at line 41. //Stability monitoring. Gives radio annoucements if field stability is below 80% /obj/effect/fusion_em_field/proc/stability_monitor() - var/warnpoint = 0.10 + var/warnpoint = 0.10 //start warning at 10% instability var/warnmessage = "Warning! Field unstable! Instability at [percent_unstable * 100]%, plasma temperature at [plasma_temperature + 295]k." var/stablemessage = "Containment field returning to stable conditions." - if(percent_unstable >= warnpoint) + if(percent_unstable >= warnpoint) //we're unstable, start warning engineering global_announcer.autosay(warnmessage, "Field Stability Monitor", "Engineering") - stable = 0 - sleep(20 SECONDS) - return - if(percent_unstable < warnpoint && stable == 0) + stable = 0 //we know we're not stable, so let's not state the safe message. + sleep(20) + return + if(percent_unstable < warnpoint && stable == 0) //The field is stable again. Let's set our safe variable and state the safe message. global_announcer.autosay(stablemessage, "Field Stability Monitor", "Engineering") stable = 1 - return + return //Reaction radiation is fairly buggy and there's at least three procs dealing with radiation here, this is to ensure constant radiation output. /obj/effect/fusion_em_field/proc/radiation_scale() @@ -513,7 +528,8 @@ if(owned_core && owned_core.loc) var/datum/gas_mixture/environment = owned_core.loc.return_air() if(environment && environment.temperature < (T0C+FUSION_MAX_ENVIRO_HEAT)) - environment.add_thermal_energy(plasma_temperature*20000) + environment.add_thermal_energy(plasma_temperature*5000) + check_instability() //Temperature changes depending on color. /obj/effect/fusion_em_field/proc/temp_color() @@ -538,8 +554,121 @@ light_max_range = 5 light_max_power = 5 return +//moved the flare to a proc for various reasons. Called on line 225. +/obj/effect/fusion_em_field/proc/emflare() + radiation += plasma_temperature/2 + light_color = "#ff0000" + light_max_power = 30 + light_min_power = 30 + light_min_range = 30 + light_max_range = 30 + visible_message("\The [src] flares to eye-searing brightness!") + sleep(60) + temp_color() + //plasma_temperature -= lost_plasma + return +//Rupture() is no longer the end all be all. Fear the magnetic resonance cascade and quantum flux cascade +/obj/effect/fusion_em_field/proc/Rupture() + visible_message("\The [src] shudders like a dying animal before flaring to eye-searing brightness and rupturing!") + set_light(15, 15, "#CCCCFF") + empulse(get_turf(src), ceil(plasma_temperature/1000), ceil(plasma_temperature/300)) + global_announcer.autosay("WARNING: FIELD RUPTURE IMMINENT!", "Containment Monitor") + RadiateAll() + var/list/things_in_range = range(10, owned_core) + var/list/turfs_in_range = list() + var/turf/T + for (T in things_in_range) + turfs_in_range.Add(T) + + explosion(pick(things_in_range), -1, 5, 5, 5) + empulse(pick(things_in_range), ceil(plasma_temperature/1000), ceil(plasma_temperature/300)) + spawn(25) + explosion(pick(things_in_range), -1, 5, 5, 5) + spawn(25) + explosion(pick(things_in_range), -1, 5, 5, 5) + spawn(25) + explosion(pick(things_in_range), -1, 5, 5, 5) + spawn(10) + explosion(pick(things_in_range), -1, 5, 5, 5) + spawn(10) + explosion(pick(things_in_range), -1, 5, 5, 5) + spawn(10) + explosion(pick(things_in_range), -1, 5, 5, 5) + return + +/obj/effect/fusion_em_field/proc/MRC() //spews electromagnetic pulses in an area around the core. + visible_message("\The [src] glows an extremely bright pink and flares out of existance!") + global_announcer.autosay("Warning! Magnetic Resonance Cascade detected! Brace for electronic system distruption.", "Field Stability Monitor") + set_light(15, 15, "#ff00d8") + var/list/things_in_range = range(15, owned_core) + var/list/turfs_in_range = list() + var/turf/T + for (T in things_in_range) + turfs_in_range.Add(T) + for(var/loopcount = 1 to 10) + spawn(200) + empulse(pick(things_in_range), 10, 15) + Destroy() + return + +/obj/effect/fusion_em_field/proc/QuantumFluxCascade() //spews hot phoron and oxygen in a radius around the RUST. Will probably set fire to things + global_announcer.autosay("Warning! Quantum fluxuation detected! Flammable gas release expected.", "Field Stability Monitor") + var/list/things_in_range = range(15, owned_core) + var/list/turfs_in_range = list() + var/turf/T + for (T in things_in_range) + turfs_in_range.Add(T) + for(var/loopcount = 1 to 10) + var/turf/TT = get_turf(pick(turfs_in_range)) + if(istype(TT)) + var/datum/gas_mixture/plasma = new + plasma.adjust_gas("oxygen", (size*100), 0) + plasma.adjust_gas("phoron", (size*100), 0) + plasma.temperature = (plasma_temperature/2) + plasma.update_values() + TT.assume_air(plasma) + TT.hotspot_expose(plasma_temperature) + plasma = null + Destroy() + return + +/obj/effect/fusion_em_field/proc/MagneticQuench() //standard hard shutdown. dumps hot oxygen/phoron into the core's area and releases an EMP in the area around the core. + global_announcer.autosay("Warning! Magnetic Quench event detected, engaging hard shutdown.", "Field Stability Monitor") + empulse(owned_core, 10, 15) + var/turf/TT = get_turf(owned_core) + if(istype(TT)) + var/datum/gas_mixture/plasma = new + plasma.adjust_gas("oxygen", (size*100), 0) + plasma.adjust_gas("phoron", (size*100), 0) + plasma.temperature = (plasma_temperature/2) + plasma.update_values() + TT.assume_air(plasma) + TT.hotspot_expose(plasma_temperature) + plasma = null + Destroy() + owned_core.Shutdown() + return + +/obj/effect/fusion_em_field/proc/BluespaceQuenchEvent() //!!FUN!! causes a number of explosions in an area around the core. Will likely destory or heavily damage the reactor. + visible_message("\The [src] shudders like a dying animal before flaring to eye-searing brightness and rupturing!") + set_light(15, 15, "#CCCCFF") + empulse(get_turf(src), ceil(plasma_temperature/1000), ceil(plasma_temperature/300)) + global_announcer.autosay("WARNING: FIELD RUPTURE IMMINENT!", "Containment Monitor") + RadiateAll() + var/list/things_in_range = range(10, owned_core) + var/list/turfs_in_range = list() + var/turf/T + for (T in things_in_range) + turfs_in_range.Add(T) + for(var/loopcount = 1 to 10) + explosion(pick(things_in_range), -1, 5, 5, 5) + empulse(pick(things_in_range), ceil(plasma_temperature/1000), ceil(plasma_temperature/300)) + Destroy() + owned_core.Shutdown() + return + #undef FUSION_HEAT_CAP #undef FUSION_MAX_ENVIRO_HEAT #undef PLASMA_TEMP_RADIATION_DIVISIOR \ No newline at end of file diff --git a/code/modules/power/fusion/fusion_reactions.dm b/code/modules/power/fusion/fusion_reactions.dm index 38f73812f9..623f70bd6b 100644 --- a/code/modules/power/fusion/fusion_reactions.dm +++ b/code/modules/power/fusion/fusion_reactions.dm @@ -117,7 +117,7 @@ proc/get_fusion_reaction(var/p_react, var/s_react, var/m_energy) var/turf/origin = get_turf(holder) holder.Rupture() qdel(holder) - var/radiation_level = rand(100, 200) + var/radiation_level = 200 // Copied from the SM for proof of concept. //Not any more --Cirra //Use the whole z proc --Leshana radiation_repository.z_radiate(locate(1, 1, holder.z), radiation_level, 1) @@ -141,7 +141,6 @@ proc/get_fusion_reaction(var/p_react, var/s_react, var/m_energy) return 1 - // High end reactions. /decl/fusion_reaction/boron_hydrogen p_react = "boron" diff --git a/code/modules/power/fusion/fusion_reagents.dm b/code/modules/power/fusion/fusion_reagents.dm index 875bf63fee..80b1cbb336 100644 --- a/code/modules/power/fusion/fusion_reagents.dm +++ b/code/modules/power/fusion/fusion_reagents.dm @@ -5,4 +5,14 @@ description = "A colorless, odorless, tasteless and generally inert gas used in fusion reactors. Non-radioactive." id = "helium-3" reagent_state = GAS - color = "#808080" \ No newline at end of file + color = "#808080" + +/obj/structure/reagent_dispensers/he3 + name = "fueltank" + desc = "A fueltank." + icon = 'icons/obj/objects.dmi' + icon_state = "weldtank" + amount_per_transfer_from_this = 10 + New() + ..() + reagents.add_reagent("helium-3",1000) \ No newline at end of file diff --git a/code/modules/power/fusion/magpower.dm b/code/modules/power/fusion/magpower.dm new file mode 100644 index 0000000000..c6882c6eb3 --- /dev/null +++ b/code/modules/power/fusion/magpower.dm @@ -0,0 +1,54 @@ +#define ENERGY_PER_K 20 +#define MINIMUM_PLASMA_TEMPERATURE 10000 + +/obj/machinery/power/hydromagnetic_trap + name = "\improper hydromagnetic trap" + desc = "A device for extracting power from high-energy plasma in toroidal fields." + icon = 'icons/obj/machines/power/fusion.dmi' + icon_state = "mag_trap0" + anchored = 1 + var/list/things_in_range = list()//what is in a radius of us? + var/list/fields_in_range = list()//What EM fields are in that radius? + var/list/active_field = list()//Our active field. + var/active = 0 //are we even on? + var/id_tag //needed for !!rasins!! + +/obj/machinery/power/hydromagnetic_trap/process() + if(!powernet && anchored == 1) + return + spawn(1) + Active() + Search() + +/obj/machinery/power/hydromagnetic_trap/proc/Search()//let's not have +100 instances of the same field in active_field. + things_in_range = range(7, src) + var/obj/effect/fusion_em_field/FFF + for (FFF in things_in_range) + fields_in_range.Add(FFF) + for (FFF in fields_in_range) + if (active_field.len > 0) + return + else if (active_field.len == 0) + Link() + return + +/obj/machinery/power/hydromagnetic_trap/proc/Link() //discover our EM field + var/obj/effect/fusion_em_field/FFF + for(FFF in fields_in_range) + if (FFF.id_tag != id_tag) + return + active_field += FFF + active = 1 + return + +/obj/machinery/power/hydromagnetic_trap/proc/Active()//POWERRRRR + var/obj/effect/fusion_em_field/FF + if (active == 0) + return + for (FF in active_field) + if (FF.plasma_temperature >= MINIMUM_PLASMA_TEMPERATURE) + icon_state = "mag_trap1" + add_avail(ENERGY_PER_K * FF.plasma_temperature) + if (FF.plasma_temperature <= MINIMUM_PLASMA_TEMPERATURE) + icon_state = "mag_trap0" + return diff --git a/code/modules/projectiles/guns/modular_guns.dm b/code/modules/projectiles/guns/modular_guns.dm new file mode 100644 index 0000000000..8f81e971c4 --- /dev/null +++ b/code/modules/projectiles/guns/modular_guns.dm @@ -0,0 +1,174 @@ +//This will likely drive me insane, but fuck it. Let's give it a shot. -k22 +//This was heavily assisted by MoondancerPony +/obj/item/weapon/gun/energy/modular + name = "modular weapon" + desc = "You shouldn't be seeing this. Contact your local time-police station." + icon_state = "mod_pistol" + cell_type = /obj/item/weapon/cell/device/weapon + charge_cost = 120 + + var/max_components = 3 //How many components we can hold. + var/capacitor_rating = 0 //How good are the capacitors inside us? + var/laser_rating = 0 //How good are the lasers inside of us? + var/manipulator_rating = 0 //How good are the manipulators inside us? + var/assembled = 1 //Are we closed up? + var/max_burst_size = 5 //Don't let our maximum burst size get too high. + var/list/guncomponents = list() //Generate our list of components. + var/accepted_components = list( + /obj/item/weapon/stock_parts/capacitor/, + /obj/item/weapon/stock_parts/capacitor/adv, + /obj/item/weapon/stock_parts/capacitor/super, + /obj/item/weapon/stock_parts/micro_laser/, + /obj/item/weapon/stock_parts/micro_laser/high, + /obj/item/weapon/stock_parts/micro_laser/ultra, + /obj/item/weapon/stock_parts/manipulator/, + /obj/item/weapon/stock_parts/manipulator/nano, + /obj/item/weapon/stock_parts/manipulator/pico, + ) + //Excessively long because it won't accept subtypes for some reason! + + +/obj/item/weapon/gun/energy/modular/New() //Initialize our components. + ..() + guncomponents = list() + guncomponents += new /obj/item/weapon/stock_parts/capacitor + guncomponents += new /obj/item/weapon/stock_parts/micro_laser + guncomponents += new /obj/item/weapon/stock_parts/manipulator + CheckParts() + FireModeModify() + +/obj/item/weapon/gun/energy/modular/proc/CheckParts() //What parts do we have inside us, and how good are they? + capacitor_rating = 0 + laser_rating = 0 + manipulator_rating = 0 + for(var/obj/item/weapon/stock_parts/capacitor/CA in guncomponents) + capacitor_rating += CA.rating + for(var/obj/item/weapon/stock_parts/micro_laser/ML in guncomponents) + laser_rating += ML.rating + for(var/obj/item/weapon/stock_parts/manipulator/MA in guncomponents) + manipulator_rating += MA.rating + FireModeModify() + +/obj/item/weapon/gun/energy/modular/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/weapon/screwdriver)) + to_chat(user, "You [assembled ? "disassemble" : "assemble"] the gun.") + assembled = !assembled + playsound(src, O.usesound, 50, 1) + return + if(istype(O, /obj/item/weapon/crowbar)) + if(assembled == 1) + to_chat(user, "Disassemble the [src] first!") + return + for(var/obj/item/I in guncomponents) + to_chat(user, "You remove the gun's components.") + playsound(src, O.usesound, 50, 1) + I.forceMove(get_turf(src)) + guncomponents.Remove(I) + CheckParts() + return + //Someone's attacking us, and it's not anything we have a special case for (i.e. a tool) + ..() + if(assembled) // can't put anything in + return + if(!(O.type in accepted_components))//check if we can accept it + to_chat(user, "You can't add this to [src]!") + return + if(guncomponents.len >= max_components) //We have too many componenets and can't fit more. + to_chat(user, "You can't add any more components!") + return + if(istype(O, /obj/item/weapon/stock_parts/capacitor) && capacitor_rating == 5) + to_chat(user, "You can't add any more capacitors!") + return + user.drop_item() + guncomponents += O + O.forceMove(src) + to_chat(user, "You add a component to the [src]") + CheckParts() + + +/obj/item/weapon/gun/energy/modular/proc/FireModeModify() //Check our laser, manipulator, and capacitor ratings, adjust stun and lethal firemodes depending on laser / manipulator rating and burst size depending on capacitors. + //check our lethal and stun ratings depending on laser and manipulator rating. + var/burstmode = capacitor_rating + var/beammode + var/beammode_lethal + var/chargecost + var/chargecost_lethal + + if(laser_rating >= 15) + beammode_lethal = /obj/item/projectile/beam/sniper + beammode = /obj/item/projectile/beam/stun + chargecost = 300 + chargecost_lethal = 600 + else if(laser_rating >= 10) + beammode_lethal = /obj/item/projectile/beam/xray + beammode = /obj/item/projectile/beam/stun + chargecost = 300 + chargecost_lethal = 200 + else if(laser_rating == 8 && manipulator_rating == 5) //very specific set of combinations. No, you can't make a pulse rifle. Sorry research. + beammode_lethal = /obj/item/projectile/beam/heavylaser + beammode = /obj/item/projectile/beam/stun + chargecost = 300 + chargecost_lethal = 600 + else if(laser_rating >= 5) + beammode_lethal = /obj/item/projectile/beam/midlaser + beammode = /obj/item/projectile/beam/stun/med + chargecost = 180 + chargecost_lethal = 240 + else if(laser_rating < 5) + beammode_lethal = /obj/item/projectile/beam/weaklaser + beammode = /obj/item/projectile/beam/stun/weak + chargecost = 100 + chargecost_lethal = 200 + + firemodes = list( + new /datum/firemode(src, list(mode_name="stun", projectile_type=beammode, fire_sound='sound/weapons/Taser.ogg', charge_cost = chargecost)), + new /datum/firemode(src, list(mode_name="lethal", projectile_type=beammode_lethal, fire_sound='sound/weapons/Laser.ogg', charge_cost = chargecost_lethal)), + new /datum/firemode(src, list(mode_name="[burstmode] shot stun", projectile_type=beammode, fire_sound='sound/weapons/Taser.ogg', charge_cost = chargecost, burst = burstmode)), + new /datum/firemode(src, list(mode_name="[burstmode] shot lethal", projectile_type=beammode_lethal, fire_sound='sound/weapons/Laser.ogg', charge_cost = chargecost_lethal, burst = burstmode)), + ) + +/obj/item/weapon/gun/energy/modular/load_ammo(var/obj/item/C, mob/user) + if(istype(C, cell_type)) + if(self_recharge || battery_lock) + user << "[src] does not have a battery port." + return + var/obj/item/weapon/cell/P = C + if(power_supply) + user << "[src] already has a power cell." + else + user.visible_message("[user] is reloading [src].", "You start to insert [P] into [src].") + if(do_after(user, 10)) + user.remove_from_mob(P) + power_supply = P + P.loc = src + user.visible_message("[user] inserts [P] into [src].", "You insert [P] into [src].") + playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) + update_icon() + update_held_icon() + return + +/obj/item/weapon/gun/energy/modular/pistol + name = "modular pistol" + icon_state = "mod_pistol" + max_components = 6 + desc = "A bulky modular pistol frame. This only only accepts six parts." + origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 3) + burst_delay = 2 + +/obj/item/weapon/gun/energy/modular/carbine + name = "modular carbine" + icon_state = "mod_carbine" + max_components = 8 + desc = "A modular version of the standard laser carbine. This one can hold 8 components." + origin_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 3, TECH_MATERIAL = 3) + burst_delay = 2 + +/obj/item/weapon/gun/energy/modular/cannon + name = "modular cannon" + icon_state = "mod_cannon" + max_components = 14 + desc = "Say hello, to my little friend!" + one_handed_penalty = 4 //dual wielding = no. + cell_type = /obj/item/weapon/cell //We're bigger. We can use much larger power cells. + origin_tech = list(TECH_COMBAT = 6, TECH_MAGNET = 6, TECH_MATERIAL = 5, TECH_BLUESPACE = 4) //its a damn cannon capable of holding a huge amount of parts. + burst_delay = 4 //preventing extreme silliness. \ No newline at end of file diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi index d7a107da94..a9c1789bf4 100644 Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ diff --git a/icons/obj/machines/power/fusion.dmi b/icons/obj/machines/power/fusion.dmi index be236a145e..4d20f04fcd 100644 Binary files a/icons/obj/machines/power/fusion.dmi and b/icons/obj/machines/power/fusion.dmi differ diff --git a/polaris.dme b/polaris.dme index 5cc6b381fb..da4169efe1 100644 --- a/polaris.dme +++ b/polaris.dme @@ -2016,6 +2016,7 @@ #include "code\modules\power\fusion\fusion_particle_catcher.dm" #include "code\modules\power\fusion\fusion_reactions.dm" #include "code\modules\power\fusion\fusion_reagents.dm" +#include "code\modules\power\fusion\magpower.dm" #include "code\modules\power\fusion\core\_core.dm" #include "code\modules\power\fusion\core\core_control.dm" #include "code\modules\power\fusion\core\core_field.dm" @@ -2058,6 +2059,7 @@ #include "code\modules\projectiles\ammunition\rounds.dm" #include "code\modules\projectiles\guns\energy.dm" #include "code\modules\projectiles\guns\launcher.dm" +#include "code\modules\projectiles\guns\modular_guns.dm" #include "code\modules\projectiles\guns\projectile.dm" #include "code\modules\projectiles\guns\vox.dm" #include "code\modules\projectiles\guns\energy\laser.dm"