diff --git a/aurora.dme b/aurora.dme
index 072ce7b4..558067c9 100644
--- a/aurora.dme
+++ b/aurora.dme
@@ -1231,6 +1231,7 @@
#include "code\modules\projectiles\guns\energy\erifles.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
#include "code\modules\projectiles\guns\energy\lawgiver.dm"
+#include "code\modules\projectiles\guns\energy\modular.dm"
#include "code\modules\projectiles\guns\energy\nuclear.dm"
#include "code\modules\projectiles\guns\energy\pulse.dm"
#include "code\modules\projectiles\guns\energy\special.dm"
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index c1146fe5..e630823d 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1321,6 +1321,10 @@
var/obj/item/weapon/gun/energy/rifle/sniperrifle/s = locate() in src
if(s.zoom)
s.zoom()
+ if(locate(/obj/item/weapon/gun/energy/laser/modular, contents))
+ var/obj/item/weapon/gun/energy/laser/modular/s = locate() in src
+ if(s.zoom)
+ s.zoom()
else
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index cba6b0f6..407ef126 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1019,7 +1019,7 @@
/*
/mob/living/silicon/robot/proc/updatefire()
return
-*
+*/
//Call when target overlay should be added/removed
/mob/living/silicon/robot/update_targeted()
if(!targeted_by && target_locked)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index f005c06e..95b412f7 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -192,6 +192,11 @@
var/obj/item/weapon/gun/energy/rifle/sniperrifle/s = locate() in mob
if(s.zoom)
s.zoom()
+ if(locate(/obj/item/weapon/gun/energy/laser/modular, mob.contents)) // If mob moves while zoomed in with modular rifle, unzoom them.
+ var/obj/item/weapon/gun/energy/laser/modular/s = locate() in mob
+ if(s.zoom)
+ s.zoom()
+
if(Process_Grab()) return
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 5fa82687..ea46b882 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -44,6 +44,9 @@
var/force_unwielded = 0 //Force modification, because striking someone with a rifle held in two hands -hurts-
var/force_wielded = 0
+ var/accuracy = -30 //goes into projectile.dm to provide individual offsets for each gun. negative to increase base accuracy
+ var/rangedrop = 5 //how much accuracy the average gun loses for every tile
+
proc/can_wield() //Override in order to make a weapon two handed, remember to add toggle_wield(mob/user as mob) in the weapon somewhere
return 0 //Override /Fire(..) to force the weapon to be two handed
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index 6d1a5deb..2535afc7 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -21,7 +21,7 @@
isHandgun()
return 1
-obj/item/weapon/gun/energy/laser/retro
+/obj/item/weapon/gun/energy/laser/retro
name ="retro laser"
icon_state = "retro"
desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws."
diff --git a/code/modules/projectiles/guns/energy/modular.dm b/code/modules/projectiles/guns/energy/modular.dm
new file mode 100644
index 00000000..4912e167
--- /dev/null
+++ b/code/modules/projectiles/guns/energy/modular.dm
@@ -0,0 +1,374 @@
+/obj/item/weapon/gun/energy/laser/modular/
+ name = "basic protolaser"
+ desc = "A basic, modular laser rifle."
+ icon_state = "laser"
+ item_state = "laser"
+ fire_sound = 'sound/weapons/Laser.ogg'
+ slot_flags = SLOT_BACK
+ w_class = 4
+ m_amt = 2000
+ origin_tech = "combat=3;magnets=2"
+ projectile_type = "/obj/item/projectile/beam/reallyweak"
+ fire_delay = 16
+ cell_type = "/obj/item/weapon/cell"
+
+ var/canzoom = 0
+ var/zoom = 0
+ var/open = 0
+
+ var/upgradepointtotal = 16 //KNOWN BUG: Crashes if you try to VV it with a lot of stuff inside. By a lot, I mean 'everything.' At least in all my tests.
+ var/upgradepoints = 0
+
+ //Changeable part mods//
+
+ var/obj/item/weapon/stock_parts/micro_laser/lasertype
+ var/obj/item/weapon/stock_parts/manipulator/delaymod
+ var/obj/item/weapon/stock_parts/scanning_module/targetmod
+ var/obj/item/weapon/stock_parts/console_screen/screen
+ var/obj/item/weapon/stock_parts/capacitor/powermod
+// var/obj/item/weapon/stock_parts/matter_bin/heatsink //i have no idea what this is for yet so.
+
+ var/hasscreen = 0 // for scoping.
+
+
+/obj/item/weapon/gun/energy/laser/modular/pistol // small modular laser pistol.
+ name = "basic protopistol"
+ desc = "A basic, modular laser pistol."
+
+ w_class = 2
+ upgradepointtotal = 10
+
+/obj/item/weapon/gun/energy/laser/modular/pistol/advanced //better version of the pistol
+ name = "advanced protopistol"
+ desc = "A protopistol with an improved frame, capable of holding more upgrades."
+
+ w_class = 2
+ upgradepointtotal = 16
+
+/obj/item/weapon/gun/energy/laser/modular/advanced //better version of the rifle.
+ name = "advanced protolaser"
+ desc = "A protolaser with an improved frame, capable of holding more upgrades."
+
+ upgradepointtotal = 22
+
+/obj/item/weapon/gun/energy/laser/modular/advanced/bluespace //for admins. maybe r&d with cell nerf if feeling generous
+ name = "bluespace protolaser"
+ desc = "A highly-advanced laser, capable of holding all your upgrades. Powered by bluespace."
+
+ upgradepointtotal = 35 //enough for everything
+ cell_type = "/obj/item/weapon/cell/infinite"
+
+/obj/item/weapon/gun/energy/laser/modular/pistol/bluespace //for admins
+ name = "bluespace protopistol"
+ desc = "A highly-advanced pistol, capable of holding all your upgrades. Powered by bluespace."
+
+ w_class = 2
+ upgradepointtotal = 35 //enough for all of the things
+ cell_type = "/obj/item/weapon/cell/infinite"
+
+/obj/item/weapon/gun/energy/laser/modular/attackby(obj/item/W, mob/user) //the modding stuffs
+
+ if (istype(W, /obj/item/weapon/screwdriver))
+ if(open == 1)
+ user << "You secure the parts and close the [src]."
+ open = 0
+ checkparts() //applies the upgrades.
+ else if(open == 0)
+ user << "You open the gun and remove the parts from [src]."
+ open = 1
+ upgradepoints = 0 //you open the gun and everything falls out. reset this stuff here.
+ hasscreen = 0
+ canzoom = 0
+ /*
+ Have it reset all the gun's stats here. Do it after the gun has stats. Gun does not have stats yet
+ */
+ if(lasertype) //if lasertype exists ie is not null
+ lasertype.loc = get_turf(src.loc)
+ lasertype = null // drop to floor and set to null
+ if(delaymod)
+ delaymod.loc = get_turf(src.loc)
+ delaymod = null
+ if(targetmod)
+ targetmod.loc = get_turf(src.loc)
+ targetmod = null
+ if(powermod)
+ powermod.loc = get_turf(src.loc)
+ powermod = null
+ if(screen)
+ screen.loc = get_turf(src.loc)
+ screen = null
+/* if(heatsink)
+ heatsink.loc = get_turf(src.loc)
+ heatsink = null */
+/* if(cell_type)
+ cell_type.loc = get_turf(src.loc)
+ cell_type = null
+*/
+ checkparts() //resets all values since everything popped out.
+
+ if (open == 1)
+ if (istype(W, /obj/item/weapon/stock_parts/micro_laser))
+ if (!lasertype)
+ lasertype = W
+ if(lasertype.rating == 1)
+ if(assignpoints(3, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [lasertype.name] in [src]."
+ else
+ lasertype = null
+ return
+ else if(lasertype.rating == 2)
+ if(assignpoints(5, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [lasertype.name] in [src]."
+ else
+ lasertype = null
+ return
+ else if(lasertype.rating == 3)
+ if(assignpoints(8, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [lasertype.name] in [src]."
+ else
+ lasertype = null
+ return
+
+ else if (lasertype)
+ user << "There's already a laser inside!"
+
+ else if (istype(W, /obj/item/weapon/stock_parts/manipulator))
+ if (!delaymod)
+ delaymod = W
+ user.drop_item()
+ W.loc = src
+ user << "You install a [delaymod.name] in [src]."
+ if(delaymod.rating == 1)
+ if(assignpoints(2, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [delaymod.name] in [src]."
+ else
+ delaymod = null
+ return
+ else if(delaymod.rating == 2)
+ if(assignpoints(6, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [delaymod.name] in [src]."
+ else
+ delaymod = null
+ return
+ else if(delaymod.rating == 3)
+ if(assignpoints(12, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [delaymod.name] in [src]."
+ else
+ delaymod = null
+ return
+
+ else if (delaymod)
+ user << "There's already a manipulator inside!"
+
+ else if (istype(W, /obj/item/weapon/stock_parts/scanning_module))
+ if (!targetmod)
+ targetmod = W
+ if(targetmod.rating == 1)
+ if(assignpoints(2, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [targetmod.name] in [src]."
+ else
+ targetmod = null
+ return
+ else if(targetmod.rating == 2)
+ if(assignpoints(4, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [targetmod.name] in [src]."
+ else
+ targetmod = null
+ return
+
+ else if(targetmod.rating == 3)
+ if(assignpoints(6, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [targetmod.name] in [src]."
+ else
+ targetmod = null
+ return
+
+ else if (targetmod)
+ user << "There's already a scanning module inside!"
+
+ else if (istype(W, /obj/item/weapon/stock_parts/console_screen))
+ if (!screen)
+ screen = W
+ if(assignpoints(3, user))
+ user.drop_item()
+ W.loc = src
+ hasscreen = 1
+ user << "You install a screen in [src]."
+ else
+ screen = null
+ return
+
+
+ else if (screen)
+ user << "There's already a screen inside!"
+ else if (istype(W, /obj/item/weapon/stock_parts/capacitor))
+ if (!powermod)
+ powermod = W
+ if(powermod.rating == 1)
+ if(assignpoints(1, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [powermod.name] in [src]."
+ else
+ powermod = null
+ return
+
+ else if(powermod.rating == 2)
+ if(assignpoints(3, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [powermod.name] in [src]."
+ else
+ powermod = null
+ return
+
+ else if(powermod.rating == 3)
+ if(assignpoints(6, user))
+ user.drop_item()
+ W.loc = src
+ user << "You install a [powermod.name] in [src]."
+ else
+ powermod = null
+ return
+
+
+ else if (powermod)
+ user << "There's already a capacitor inside!"
+
+/* else if (istype(W, /obj/item/weapon/stock_parts/matter_bin))
+ if (!heatsink)
+ user.drop_item()
+ W.loc = src
+ heatsink = W
+ user << "You install a [heatsink.name] in [src]."
+ if(heatsink.rating == 1)
+ upgradepoints += 2
+ else if(heatsink.rating == 2)
+ upgradepoints += 5
+ else if(heatsink.rating == 3)
+ upgradepoints += 10
+
+ else if (heatsink)
+ user << "There's already a heatsink inside!"
+*/
+/obj/item/weapon/gun/energy/laser/modular/proc/checkparts() //updates parts and values
+
+ if(!lasertype)
+ projectile_type = "/obj/item/projectile/beam/reallyweak"
+ charge_cost = 150
+ else if(lasertype.rating == 1)
+ projectile_type = "/obj/item/projectile/beam/green" // preferably a green laser. expecting standard 40 damage.
+ charge_cost = 200
+ else if(lasertype.rating == 2)
+ projectile_type = "/obj/item/projectile/beam/blue" //powerful. eight shots with highest-end power equipment.
+ charge_cost = 500
+ else if(lasertype.rating == 3)
+ projectile_type = "/obj/item/projectile/beam/violet" //extremely high-powered. you get four shots -with- top-tier powermods. less without.
+ charge_cost = 1000
+
+ if(!delaymod)
+ fire_delay = 16
+ else if(delaymod.rating == 1)
+ fire_delay = 8
+ else if(delaymod.rating == 2)
+ fire_delay = 4
+ else if(delaymod.rating == 3)
+ fire_delay = 2
+
+ if(!targetmod) // TBD after projectile accuracy. extreme placeholder values.
+// miss_modifier = 0
+ canzoom = 0
+ else if(targetmod.rating == 1)
+// miss_modifier = -30
+ canzoom = 0
+ else if(targetmod.rating == 2)
+// miss_modifier = -60
+ canzoom = 1 //advanced and up scanning modules let you zoom in.
+ else if(targetmod.rating == 3)
+// miss_modifier = -90
+ canzoom = 1
+ if(!powermod)
+ charge_cost = 1.5*charge_cost
+ else if(powermod.rating == 1)
+ charge_cost = charge_cost
+ else if(powermod.rating == 2)
+ charge_cost = charge_cost/2
+ else if(powermod.rating == 3)
+ charge_cost = charge_cost/4
+
+/* if(!heatsink)
+
+ else if(heatsink.rating == 1)
+
+ else if(heatsink.rating == 2)
+
+ else if(heatsink.rating == 3)*/
+
+/obj/item/weapon/gun/energy/laser/modular/proc/assignpoints(var/newpoints, var/mob/user as mob)
+ if((upgradepointtotal) >= (upgradepoints + newpoints))
+ upgradepoints += newpoints
+ user << "You have used [upgradepoints]/[upgradepointtotal] upgrade points. This upgrade costs [newpoints] points."
+ return 1
+ else
+ user << "The frame cannot handle this many upgrades!"
+ user << "You have used [upgradepoints]/[upgradepointtotal] upgrade points. This upgrade costs [newpoints] points."
+ return 0
+
+/obj/item/weapon/gun/energy/laser/modular/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+ if(open == 1)
+ user << "Secure the gun with a screwdriver first!"
+ return
+ ..()
+
+/obj/item/weapon/gun/energy/laser/modular/dropped(mob/user)
+ user.client.view = world.view
+
+/obj/item/weapon/gun/energy/laser/modular/verb/zoom()
+ set category = "Object"
+ set name = "Use Scan-Screen"
+ set popup_menu = 0
+
+ if(usr.stat || !(istype(usr,/mob/living/carbon/human)))
+ usr << "You are unable to focus on the screen."
+ return
+ if(!zoom && global_hud.darkMask[1] in usr.client.screen)
+ usr << "Your welding equipment makes it hard to see the screen."
+ return
+ if(!zoom && usr.get_active_hand() != src)
+ usr << "You are too distracted to watch the screen, perhaps if it was in your active hand this might work better"
+ return
+ if((hasscreen == 0) || (canzoom == 0))
+ usr << "This gun lacks the parts for components for zooming."
+ return
+
+ if(usr.client.view == world.view)
+ if(!usr.hud_used.hud_shown)
+ usr.button_pressed_F12(1) // If the user has already limited their HUD this avoids them having a HUD when they zoom in
+ usr.button_pressed_F12(1)
+ usr.client.view = 12
+ zoom = 1
+ else
+ usr.client.view = world.view
+ if(!usr.hud_used.hud_shown)
+ usr.button_pressed_F12(1)
+ zoom = 0
+ usr << "Zoom mode [zoom?"en":"dis"]abled."
+ return
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 8e19a9d1..7aee9719 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -93,7 +93,7 @@
var/obj/item/weapon/gun/daddy = shot_from //Kinda balanced by fact you need like 2 seconds to aim
if (daddy.target && original in daddy.target) //As opposed to no-delay pew pew
miss_modifier += -30
- def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier + 5*distance)
+ def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier + 10*distance) // add +daddy.missmod vars to gun and this. snowflake accuracy
if(!def_zone)
visible_message("\blue \The [src] misses [M] narrowly!")
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 23abaaef..236517f3 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -188,4 +188,42 @@ var/list/beam_master = list()
damage = 30
damage_type = BURN
flag = "laser"
- eyeblur = 4
\ No newline at end of file
+ eyeblur = 4
+
+//modular laser projectiles
+
+/obj/item/projectile/beam/reallyweak
+ name = "unfocused laser"
+ icon_state = "laser"
+ damage = 20
+
+/obj/item/projectile/beam/green
+ name = "green laser"
+ icon_state = "lasergreen"
+ damage = 40
+ agony = 25 //these extra values and below are all timed so they knock you out only on the killing/critting blow. more for coolness than effect.
+
+/obj/item/projectile/beam/blue
+ name = "blue laser"
+ icon_state = "laserblue"
+ damage = 60
+ irradiate = 40
+ agony = 40
+
+
+/obj/item/projectile/beam/violet
+ name = "violet laser"
+ icon_state = "laserviolet"
+ damage = 80
+ irradiate = 50
+ agony = 50
+
+/obj/item/projectile/beam/violet/on_hit(var/atom/target, var/blocked = 0)
+ if(istype(target, /mob/living/carbon))
+ var/mob/living/carbon/M = target
+ M.adjust_fire_stacks(1)
+ M.IgniteMob()
+ else if(istype(target, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/M = target
+ M.adjust_fire_stacks(1)
+ M.IgniteMob()
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 933a5021..2b21cc6b 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -43,7 +43,10 @@
var/mob/living/carbon/M = target
M.adjust_fire_stacks(1)
M.IgniteMob()
-
+ else if(istype(target, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/M = target
+ M.adjust_fire_stacks(1)
+ M.IgniteMob()
/obj/item/projectile/bullet/incendiary/shell
name = "incendiary shell"
damage_type = BURN
diff --git a/code/setup.dm b/code/setup.dm
index c0259f40..ee89e314 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -62,9 +62,9 @@
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
#define MAX_HIGH_PRESSURE_DAMAGE 4 //This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :(
-#define LOW_PRESSURE_DAMAGE 6 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
-//low pressure damage bumped to 6 because current ZAS means cold does not proc half the time. You can waltz in space and be totally fine.
-#define PRESSURE_SUIT_REDUCTION_COEFFICIENT 0.8 //This is how much (percentual) a suit with the flag STOPSPRESSUREDMAGE reduces pressure.
+#define LOW_PRESSURE_DAMAGE 4 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
+//low pressure damage bumped to 4 because current ZAS means cold does not proc half the time. 6 was too much.
+#define PRESSURE_SUIT_REDUCTION_COEFFICIENT 0.6 //This is how much (percentual) a suit with the flag STOPSPRESSUREDMAGE reduces pressure. orig. .8 but we had spacewalkers without helmets.
#define PRESSURE_HEAD_REDUCTION_COEFFICIENT 0.4 //This is how much (percentual) a helmet/hat with the flag STOPSPRESSUREDMAGE reduces pressure.
// Doors!
diff --git a/data/investigate/gravity.html b/data/investigate/gravity.html
index ef0b20af..cbf8cd75 100644
--- a/data/investigate/gravity.html
+++ b/data/investigate/gravity.html
@@ -1,2 +1,2 @@
-21:21 [0x20077ce] (92,152,1) || the gravitational generator has regained power.
-21:21 [0x20077ce] (92,152,1) || the gravitational generator is now charging.
+22:48 [0x200779e] (92,152,1) || the gravitational generator has regained power.
+22:48 [0x200779e] (92,152,1) || the gravitational generator is now charging.
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index da413aa5..495db1b1 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ