diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index df34c74b3ee..e719912f3bf 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -281,6 +281,7 @@ datum/objective/steal "the nuclear authentication disk" = /obj/item/weapon/disk/nuclear, "an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof, "the reactive teleport armor" = /obj/item/clothing/suit/armor/reactive, + "a laser pointer" = /obj/item/device/laser_pointer, /* Nobody takes these seriously anyways -- Ikki "a captain's jumpsuit" = /obj/item/clothing/under/rank/captain, diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index e58de3f4eb7..cef085d72b7 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -292,6 +292,7 @@ H.equip_to_slot_or_del(new /obj/item/device/pda/librarian(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/weapon/barcodescanner(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/laser_pointer(H), slot_l_store) return 1 @@ -324,6 +325,7 @@ var/global/lawyer = 0//Checks for another lawyer H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/lawyer(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/laser_pointer(H), slot_l_store) if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) else diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index f6835c5184f..1a953fc0d8b 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -27,6 +27,7 @@ H.equip_to_slot_or_del(new /obj/item/device/pda/heads/rd(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/labcoat(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/weapon/clipboard(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/laser_pointer(H), slot_l_store) return 1 diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index f0ef6f1907b..6f6db8ad4ec 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -182,6 +182,9 @@ playsound(loc, "sparks", 50, 1) visible_message("\blue The camera has been sliced apart by [] with an energy blade!") del(src) + else if(istype(W, /obj/item/device/laser_pointer)) + var/obj/item/device/laser_pointer/L = W + L.laser_act(src, user) else ..() return diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm new file mode 100644 index 00000000000..3e98a0fe200 --- /dev/null +++ b/code/game/objects/items/devices/laserpointer.dm @@ -0,0 +1,183 @@ + +/obj/item/device/laser_pointer + name = "laser pointer" + desc = "Don't shine it in your eyes!" + icon = 'icons/obj/device.dmi' + icon_state = "pointer" + item_state = "pen" + var/pointer_icon_state + flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY + slot_flags = SLOT_BELT + m_amt = 500 + g_amt = 500 + w_class = 1.0 + origin_tech = "combat=1" + origin_tech = "magnets=2" + var/turf/pointer_loc + var/energy = 5 + var/max_energy = 5 + var/recharging = 0 + var/recharge_locked = 0 + +/obj/item/device/laser_pointer/red + pointer_icon_state = "red_laser" +/obj/item/device/laser_pointer/green + pointer_icon_state = "green_laser" +/obj/item/device/laser_pointer/blue + pointer_icon_state = "blue_laser" +/obj/item/device/laser_pointer/purple + pointer_icon_state = "purple_laser" + +/obj/item/device/laser_pointer/New() + ..() + if(!pointer_icon_state) + pointer_icon_state = pick("red_laser","green_laser","blue_laser","purple_laser") + +/obj/item/device/laser_pointer/attack(mob/living/M, mob/user) + laser_act(M, user) + +/obj/item/device/laser_pointer/afterattack(var/atom/target, var/mob/living/user, flag, params) + if(flag) //we're placing the object on a table or in backpack + return + laser_act(target, user) + +/obj/item/device/laser_pointer/proc/laser_act(var/atom/target, var/mob/living/user) + if( !(user in (viewers(7,target))) ) + return + if (!user.IsAdvancedToolUser()) + user << "You don't have the dexterity to do this!" + return + if(user.has_mutation(HULK)) + user << "Your meaty finger is too large for the button!" + return + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(C.is_mutantrace("adamantine")) + user << "Your metal fingers can't press the button!" + return + + add_fingerprint(user) + + //nothing happens if the battery is drained + if(recharge_locked) + user << "You point [src] at [target], but it's still charging." + return + + var/outmsg + var/turf/targloc = get_turf(target) + + //human/alien mobs + if(iscarbon(target)) + if(user.zone_sel.selecting == "eyes") + var/mob/living/carbon/C = target + + //20% chance to actually hit the eyes + if(prob(20)) + C.attack_log += text("\[[time_stamp()]\] Has had a laser pointer shone in their eyes by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Shone a laser pointer in the eyes of [C.name] ([C.ckey])") + log_attack("[user.name] ([user.ckey]) Shone a laser pointer in the eyes of [C.name] ([C.ckey])") + + //eye target check + outmsg = "You blind [C] by shining [src] in their eyes." + var/eye_prot = C.eyecheck() + if(C.blinded || eye_prot >= 2) + eye_prot = 4 + var/severity = 3 - eye_prot + if(prob(33)) + severity += 1 + else if(prob(50)) + severity -= 1 + severity = min(max(severity, 0), 4) + + switch(severity) + if(0) + //no effect + C << "A small, bright dot appears in your vision." + if(1) + //industrial grade eye protection + C.eye_stat += rand(0, 2) + C << "Something bright flashes in the corner of your vision!" + if(2) + //basic eye protection (sunglasses) + flick("flash", C.flash) + C.eye_stat += rand(1, 6) + C << "Your eyes were blinded!" + if(3) + //no eye protection + if(prob(2)) + C.Weaken(1) + flick("e_flash", C.flash) + C.eye_stat += rand(3, 7) + C << "Your eyes were blinded!" + if(4) + //the effect has been worsened by something + if(prob(5)) + C.Weaken(1) + flick("e_flash", C.flash) + C.eye_stat += rand(5, 10) + C << "Your eyes were blinded!" + else + outmsg = "You fail to blind [C] by shining [src] at their eyes." + + //robots and AI + else if(issilicon(target)) + var/mob/living/silicon/S = target + //20% chance to actually hit the sensors + if(prob(20)) + S.Weaken(rand(5,10)) + S << "Your sensors were overloaded by a laser!" + outmsg = "You overload [S] by shining [src] at their sensors." + + S.attack_log += text("\[[time_stamp()]\] Has had a laser pointer shone in their eyes by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Shone a laser pointer in the eyes of [S.name] ([S.ckey])") + log_attack("[user.name] ([user.ckey]) Shone a laser pointer in the eyes of [S.name] ([S.ckey])") + else + outmsg = "You fail to overload [S] by shining [src] at their sensors." + + //cameras + else if(istype(target, /obj/machinery/camera)) + var/obj/machinery/camera/C = target + if(prob(20)) + C.emp_act(1) + outmsg = "You hit the lens of [C] with [src], temporarily disabling the camera!" + + log_admin("\[[time_stamp()]\] [user.name] ([user.ckey]) EMPd a camera with a laser pointer") + user.attack_log += text("\[[time_stamp()]\] [user.name] ([user.ckey]) EMPd a camera with a laser pointer") + else + outmsg = "You missed the lens of [C] with [src]." + + //laser pointer image + icon_state = "pointer_[pointer_icon_state]" + var/list/showto = list() + for(var/mob/M in range(7,targloc)) + if(M.client) + showto.Add(M.client) + var/image/I = image('icons/obj/projectiles.dmi',targloc,pointer_icon_state,10) + I.pixel_x = target.pixel_x + rand(-5,5) + I.pixel_y = target.pixel_y + rand(-5,5) + + if(outmsg) + user << outmsg + else + user << "You point [src] at [target]." + + energy -= 1 + if(energy <= max_energy) + if(!recharging) + recharging = 1 + processing_objects.Add(src) + if(energy <= 0) + user << "You've overused the battery of [src], now it needs time to recharge!" + recharge_locked = 1 + + flick_overlay(I, showto, 10) + icon_state = "pointer" + +/obj/item/device/laser_pointer/process() + if(prob(20 - recharge_locked*5)) + energy += 1 + if(energy >= max_energy) + energy = max_energy + recharging = 0 + recharge_locked = 0 + ..() 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 dc515019ed4..63c020eb9e5 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -47,4 +47,5 @@ new /obj/item/clothing/mask/gas(src) new /obj/item/clothing/suit/armor/reactive(src) new /obj/item/device/flash(src) + new /obj/item/device/laser_pointer(src) return \ No newline at end of file diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 5fbeebf0eff..f1acede2711 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index e46afd477bd..2844889a4da 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 1e73f208e6f..3748c773430 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -436,6 +436,7 @@ #include "code\game\objects\items\devices\chameleonproj.dm" #include "code\game\objects\items\devices\flash.dm" #include "code\game\objects\items\devices\flashlight.dm" +#include "code\game\objects\items\devices\laserpointer.dm" #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm"