/obj/item/weapon/gun name = "gun" desc = "Its a gun. It's pretty terrible, though." icon = 'gun.dmi' icon_state = "detective" item_state = "gun" flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY slot_flags = SLOT_BELT m_amt = 2000 w_class = 3.0 throwforce = 5 throw_speed = 4 throw_range = 5 force = 5.0 origin_tech = "combat=1" var/fire_sound = 'Gunshot.ogg' var/tmp/obj/item/projectile/in_chamber = null var/caliber = "" var/silenced = 0 var/recoil = 0 var/ejectshell = 1 var/tmp/list/mob/living/target //List of who yer targeting. var/tmp/lock_time = -100 var/tmp/mouthshoot = 0 ///To stop people from suiciding twice... >.> var/automatic = 0 //Used to determine if you can target multiple people. var/tmp/mob/living/last_moved_mob //Used to fire faster at more than one person. var/tmp/told_cant_shoot = 0 //So that it doesn't spam them with the fact they cannot hit them. proc/load_into_chamber() return 0 //Removing the lock and the buttons. dropped(mob/user as mob) if(target) for(var/mob/living/M in target) if(M) M.NotTargeted(src) //Untargeting people. del(target) del(user.item_use_icon) //Removing the control icons. del(user.gun_move_icon) del(user.gun_run_icon) return ..() proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver. return 1 emp_act(severity) for(var/obj/O in contents) O.emp_act(severity) //Handling lowering yer gun. attack_self() if(target) for(var/mob/living/M in target) if(M) M.NotTargeted(src) del(target) usr.visible_message("\blue \The [usr] lowers \the [src]...") return 0 return 1 //Suiciding. attack(mob/living/M as mob, mob/living/user as mob, def_zone) if (M == user && user.zone_sel.selecting == "mouth" && load_into_chamber() && !mouthshoot) //Suicide handling. mouthshoot = 1 M.visible_message("\red \The [user] sticks their gun in their mouth, ready to pull the trigger...") if(!do_after(user, 40)) M.visible_message("\blue \The [user] decided life was worth living") mouthshoot = 0 return if(istype(src.in_chamber, /obj/item/projectile/bullet) && !istype(src.in_chamber, /obj/item/projectile/bullet/stunshot) && !istype(src.in_chamber, /obj/item/ammo_casing/shotgun/beanbag)) M.apply_damage(75, BRUTE, "head", used_weapon = "Suicide attempt with a projectile weapon.") M.apply_damage(85, BRUTE, "chest") M.visible_message("\red \The [user] pulls the trigger.") else if(istype(src.in_chamber, /obj/item/projectile/bullet/stunshot) || istype(src.in_chamber, /obj/item/projectile/energy/electrode)) M.apply_damage(10, BURN, "head", used_weapon = "Suicide attempt with a stun round.") M.visible_message("\red \The [user] pulls the trigger, but luckily it was a stun round.") else if(istype(src.in_chamber, /obj/item/ammo_casing/shotgun/beanbag)) M.apply_damage(20, BRUTE, "head", used_weapon = "Suicide attempt with a beanbag.") M.visible_message("\red \The [user] pulls the trigger, but luckily it was a stun round.") else if(istype(src.in_chamber, /obj/item/projectile/beam) || istype(src.in_chamber, /obj/item/projectile/energy)) M.apply_damage(75, BURN, "head", used_weapon = "Suicide attempt with an energy weapon") M.apply_damage(85, BURN, "chest") M.visible_message("\red \The [user] pulls the trigger.") else M.apply_damage(75, BRUTE, "head", used_weapon = "Suicide attempt with a gun") M.apply_damage(85, BRUTE, "chest") M.visible_message("\red \The [user] pulls the trigger. Ow.") del(in_chamber) mouthshoot = 0 return else if(user.a_intent == "hurt" && load_into_chamber() && (istype(src.in_chamber, /obj/item/projectile/beam) || istype(src.in_chamber, /obj/item/projectile/energy)\ || istype(src.in_chamber, /obj/item/projectile/bullet)) && !istype(in_chamber,/obj/item/projectile/energy/electrode)) //Point blank shooting. //Lets shoot them, then. user.visible_message("\red \The [user] fires \the [src] point blank at [M]!") if(silenced) playsound(user, fire_sound, 10, 1) else playsound(user, fire_sound, 50, 1) M.apply_damage(30+in_chamber.damage, BRUTE, user.zone_sel.selecting, used_weapon = "Point Blank Shot") //So we'll put him an inch from death. M.attack_log += text("\[[]\] []/[] shot []/[] point blank with a []", time_stamp(), user, user.ckey, M, M.ckey, src) user.attack_log += text("\[[]\] []/[] shot []/[] point blank with a []", time_stamp(), user, user.ckey, M, M.ckey, src) log_admin("ATTACK: [user] ([user.ckey]) shot [M] ([M.ckey]) point blank with [src].") message_admins("ATTACK: [user] ([user.ckey]) shot [M] ([M.ckey]) point blank with [src].") del(in_chamber) update_icon() return else if(user.a_intent != "hurt" && load_into_chamber() && istype(in_chamber,/obj/item/projectile/energy/electrode)) //Point blank tasering. if (M.canstun == 0 || M.canweaken == 0) user.visible_message("\red \The [M] has been stunned with the taser gun by \the [user] to no effect!") del(in_chamber) update_icon() return if (prob(50)) if (M.paralysis < 60 && (!(HULK in M.mutations)) ) M.paralysis = 60 else if (M.weakened < 60 && (!(HULK in M.mutations)) ) M.weakened = 60 if (M.stuttering < 60 && (!(HULK in M.mutations)) ) M.stuttering = 60 if(silenced) playsound(user, fire_sound, 10, 1) else playsound(user, fire_sound, 50, 1) user.visible_message("\red \The [M] has been stunned with the taser gun by \the [user]!") M.attack_log += text("\[[]\] []/[] stunned []/[] with a []", time_stamp(), user, user.ckey, M, M.ckey, src) user.attack_log += text("\[[]\] []/[] stunned []/[] with a []", time_stamp(), user, user.ckey, M, M.ckey, src) log_admin("ATTACK: [user] ([user.ckey]) stunned [M] ([M.ckey]) with [src].") message_admins("ATTACK: [user] ([user.ckey]) stunned [M] ([M.ckey]) with [src].") del(in_chamber) update_icon() return else if(target && M in target) //Yer targeting them, and 1 tile away. FIRE! if(!load_into_chamber()) //No ammo, hit them! return ..() else PreFire(M,user) ///Otherwise, shoot! return else return ..() //Pistolwhippin' //POWPOW!... Used to be afterattack. proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)//TODO: go over this if(istype(user, /mob/living)) var/mob/living/M = user if ((CLUMSY in M.mutations) && prob(50)) ///Who ever came up with this... M << "\red \the [src] blows up in your face." M.take_organ_damage(0,20) M.drop_item() del(src) return if (!user.IsAdvancedToolUser()) user << "\red You don't have the dexterity to do this!" return add_fingerprint(user) var/turf/curloc = user.loc var/turf/targloc = get_turf(target) if (!istype(targloc) || !istype(curloc)) return if(!special_check(user)) return if(!load_into_chamber()) user.visible_message("*click click*", "\red *click*") for(var/mob/K in viewers(usr)) K << 'empty.ogg' return if(!in_chamber) return in_chamber.firer = user in_chamber.def_zone = user.zone_sel.selecting if(targloc == curloc) user.bullet_act(in_chamber) del(in_chamber) update_icon() return if(recoil) spawn() shake_camera(user, recoil + 1, recoil) if(silenced) playsound(user, fire_sound, 10, 1) else playsound(user, fire_sound, 50, 1) if(reflex) user.visible_message("\red \The [user] fires \the [src] by reflex!", "\red You reflex fire \the [src]!", "\blue You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") else user.visible_message("\red \The [user] fires \the [src]!", "\red You fire \the [src]!", "\blue You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") in_chamber.original = targloc in_chamber.loc = get_turf(user) in_chamber.starting = get_turf(user) user.next_move = world.time + 4 in_chamber.silenced = silenced in_chamber.current = curloc in_chamber.yo = targloc.y - curloc.y in_chamber.xo = targloc.x - curloc.x if(params) var/list/mouse_control = params2list(params) if(mouse_control["icon-x"]) in_chamber.p_x = text2num(mouse_control["icon-x"]) if(mouse_control["icon-y"]) in_chamber.p_y = text2num(mouse_control["icon-y"]) spawn() if(in_chamber) in_chamber.fired() sleep(1) in_chamber = null update_icon() return //Aiming at the target mob. proc/Aim(var/mob/M) if(!target || !(M in target)) lock_time = world.time if(target && !automatic) //If they're targeting someone and they have a non automatic weapon. //usr.ClearRequest("Aim") for(var/mob/living/L in target) if(L) L.NotTargeted(src) del(target) usr.visible_message("\red [usr] turns \the [src] on [M]!") else usr.visible_message("\red [usr] aims \a [src] at [M]!") for(var/mob/K in viewers(usr)) K << 'TargetOn.ogg' M.Targeted(src) //HE MOVED, SHOOT HIM! proc/TargetActed(var/mob/living/T) var/mob/living/M = loc if(M == T) return if(!istype(M) || src != M.equipped()) for(var/mob/living/N in target) if(N) N.NotTargeted(src) del(target) return M.last_move_intent = world.time if(load_into_chamber()) var/firing_check = in_chamber.check_fire(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing. if(firing_check > 0) if(firing_check == 1) Fire(T,usr, reflex = 1) else if(!told_cant_shoot) M << "\red They can't be hit from here!" told_cant_shoot = 1 spawn(30) told_cant_shoot = 0 else usr.visible_message("*click click*", "\red *click*") for(var/mob/K in viewers(usr)) K << 'empty.ogg' var/dir_to_fire = sd_get_approx_dir(M,T) if(dir_to_fire != M.dir) M.dir = dir_to_fire afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params) if(flag) return //we're placing gun on a table or in backpack if(istype(target, /obj/machinery/recharger) && istype(src, /obj/item/weapon/gun/energy)) return//Shouldnt flag take care of this? if(user && user.client && user.client.gun_mode) PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at. else Fire(A,user,params) //Otherwise, fire normally. //Compute how to fire..... proc/PreFire(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, params) //GraphicTrace(usr.x,usr.y,A.x,A.y,usr.z) if(lock_time > world.time - 2) return //Lets not spam it. if(!ismob(A)) //Didn't click someone, check if there is anyone along that guntrace // var/mob/M = locate() in range(0,A) // if(M && !ismob(A)) // if(M.type == /mob) // return FindTarget(M,user,params) var/mob/M = GunTrace(usr.x,usr.y,A.x,A.y,usr.z,usr) //Find dat mob. if(M && ismob(M) && isliving(M) && M in view(user)) if(!(M.client && M.client.admin_invis)) Aim(M) //Aha! Aim at them! return else if(!ismob(M) || (ismob(M) && !(M in view(user)))) //Nope! They weren't there! Fire(A,user,params) //Fire like normal, then. if(ismob(A) && isliving(A) && !(A in target)) Aim(A) //Clicked a mob, aim at them. else if(lock_time < world.time + 10) Fire(A,user,params) //Bang! else if(!target) Fire(A,user,params) //Boom! //else //var/item/gun/G = usr.OHand //if(!G) //Fire(A,0) //else if(istype(G)) //G.Fire(A,3) //Fire(A,2) //else //Fire(A) var/dir_to_fire = sd_get_approx_dir(usr,A) //Turn them to face their target. if(dir_to_fire != usr.dir) usr.dir = dir_to_fire //Yay, math! #define SIGN(X) ((X<0)?-1:1) proc/GunTrace(X1,Y1,X2,Y2,Z=1,exc_obj,PX1=16,PY1=16,PX2=16,PY2=16) //bluh << "Tracin' [X1],[Y1] to [X2],[Y2] on floor [Z]." var/turf/T var/mob/M if(X1==X2) if(Y1==Y2) return 0 //Light cannot be blocked on same tile else var/s = SIGN(Y2-Y1) Y1+=s while(1) T = locate(X1,Y1,Z) if(!T) return 0 M = locate() in T if(M) return M M = locate() in orange(1,T)-exc_obj if(M) return M Y1+=s else var m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1)) b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles signX = SIGN(X2-X1) signY = SIGN(Y2-Y1) if(X1= 5) //Otherwise, they can just aim at one person. if(ismob(I.loc)) I.loc << "You can only target 5 people at once!" return else return if(!targeted_by) targeted_by = list() targeted_by += I I.lock_time = world.time + 20 //Target has 2 second to realize they're targeted and stop (or target the opponent). src << "((\red Your character is being targeted. They have 2 seconds to stop any click or move actions. \black While targeted, they may \ drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map, their items \ (other than a weapon to de-target), or moving will result in being fired upon. \red The aggressor may also fire manually, \ so try not to get on their bad side.\black ))" if(targeted_by.len == 1) spawn(0) target_locked = new /obj/effect/target_locked(src) //Add the overlay overlays += target_locked spawn(0) //Make it show the 2 states properly if(target_locked) target_locked.icon_state = "locking" update_clothing() // update_clothing clears overlays, so this might break stuff sleep(20) if(target_locked) target_locked.icon_state = "locked" update_clothing() var/mob/T = I.loc //Adding the buttons to the controler person if(T) T.item_use_icon = new /obj/screen/gun/item(null) T.gun_move_icon = new /obj/screen/gun/move(null) if(T.client) T.client.screen += T.item_use_icon T.client.screen += T.gun_move_icon if(m_intent == "run" && T.client && T.client.target_can_move == 1 && T.client.target_can_run == 0) src << "\red Your move intent is now set to walk, as your targeter permits it." //Self explanitory. m_intent = "walk" hud_used.move_intent.icon_state = "walking" while(targeted_by && T.client) if(last_move_intent > I.lock_time + 10 && !T.client.target_can_move) //If the target moved while targeted I.TargetActed(src) if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better. I.lock_time = world.time + 5 I.lock_time = world.time + 5 I.last_moved_mob = src else if(last_move_intent > I.lock_time + 10 && !T.client.target_can_run && m_intent == "run") //If the target ran while targeted I.TargetActed(src) if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better. I.lock_time = world.time + 5 I.lock_time = world.time + 5 I.last_moved_mob = src if(last_target_click > I.lock_time + 10 && !T.client.target_can_click) //If the target clicked the map to pick something up/shoot/etc I.TargetActed(src) if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better. I.lock_time = world.time + 5 I.lock_time = world.time + 5 I.last_moved_mob = src sleep(1) NotTargeted(var/obj/item/weapon/gun/I) if(!I.silenced) for(var/mob/M in viewers(src)) M << 'TargetOff.ogg' del(target_locked) //Remove the overlay targeted_by -= I I.target.Remove(src) //De-target them if(!I.target.len) del(I.target) var/mob/T = I.loc //Remove the targeting icons if(T && ismob(T) && !I.target) del(T.item_use_icon) del(T.gun_move_icon) del(T.gun_run_icon) if(!targeted_by.len) del targeted_by spawn(1) update_clothing() //Finally, update the image. /* Captive(var/obj/item/weapon/gun/I) Sound(src,'CounterAttack.ogg') if(!targeted_by) targeted_by = list() targeted_by += I I.target = src // Stun("Captive") I.lock_time = world.time + 10 //Target has 1 second to realize they're targeted and stop (or target the opponent). src << "(Your character is being held captive. They have 1 second to stop any click or move actions. While held, they may \ drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map or their items \ (other than a weapon to de-target) will result in being attacked. The aggressor may also attack manually, \ so try not to get on their bad side.)" if(targeted_by.len == 1) var/mob/T = I.loc while(targeted_by) sleep(1) if(last_target_click > I.lock_time + 10 && !T.target_can_click) //If the target clicked the map to pick something up/shoot/etc I.TargetActed() NotCaptive(var/obj/item/weapon/gun/I,silent) if(!silent) Sound(src,'SwordSheath.ogg') // UnStun("Captive") targeted_by -= I I.target = null if(!targeted_by.len) del targeted_by*/ //Used to overlay the awesome stuff /obj/effect // target_locking // icon = 'icons/effects/Targeted.dmi' // icon_state = "locking" // layer = 99 target_locked icon = 'icons/effects/Targeted.dmi' icon_state = "locked" layer = 17.9 // captured // icon = 'Captured.dmi' // layer = 99 //If you move out of range, it isn't going to still stay locked on you any more. client/var target_can_move = 0 target_can_run = 0 target_can_click = 0 gun_mode = 0 mob/Move() . = ..() for(var/obj/item/weapon/gun/G in targeted_by) //Handle moving out of the gunner's view. var/mob/M = G.loc if(!(M in view(src))) //ClearRequest("Aim") NotTargeted(G) for(var/obj/item/weapon/gun/G in src) //Handle the gunner loosing sight of their target/s if(G.target) for(var/mob/living/M in G.target) if(M && !(M in view(src))) //ClearRequest("Aim") M.NotTargeted(G) client/verb //These are called by the on-screen buttons, adjusting what the victim can and cannot do. AllowTargetMove() set hidden=1 spawn(1) target_can_move = !target_can_move if(!target_can_move) // winset(usr,"default.target_can_move","is-flat=true;border=sunken") usr << "Target may now walk." usr.gun_run_icon = new /obj/screen/gun/run(null) screen += usr.gun_run_icon if(usr.gun_move_icon) usr.gun_move_icon.dir = 1 usr.gun_move_icon.name = "Disallow Walking" else // winset(usr,"default.target_can_move","is-flat=false;border=none") usr << "Target may no longer move." target_can_run = 0 del(usr.gun_run_icon) if(usr.gun_move_icon) usr.gun_move_icon.dir = 2 usr.gun_move_icon.name = "Allow Walking" for(var/obj/item/weapon/gun/G in usr) G.lock_time = world.time + 5 if(G.target) for(var/mob/living/M in G.target) if(!target_can_move) M << "Your character may now walk at the discretion of their targeter." if(!target_can_run) M << "\red Your move intent is now set to walk, as your targeter permits it." M.m_intent = "walk" if(M.hud_used.move_intent) M.hud_used.move_intent.icon_state = "walking" else M << "\red Your character will now be shot if they move." AllowTargetRun() set hidden=1 spawn(1) target_can_run = !target_can_run if(!target_can_run) // winset(usr,"default.target_can_move","is-flat=true;border=sunken") usr << "Target may now run." if(usr.gun_run_icon) usr.gun_run_icon.dir = 1 usr.gun_run_icon.name = "Disallow Running" else // winset(usr,"default.target_can_move","is-flat=false;border=none") usr << "Target may no longer run." if(usr.gun_run_icon) usr.gun_run_icon.dir = 2 usr.gun_run_icon.name = "Allow Running" for(var/obj/item/weapon/gun/G in src) G.lock_time = world.time + 5 if(G.target) for(var/mob/living/M in G.target) if(!target_can_run) M << "Your character may now run at the discretion of their targeter." else M << "\red Your character will now be shot if they run." AllowTargetClick() set hidden=1 spawn(1) target_can_click = !target_can_click if(!target_can_click) // winset(usr,"default.target_can_click","is-flat=true;border=sunken") usr << "Target may now use items." if(usr.item_use_icon) usr.item_use_icon.dir = 1 usr.item_use_icon.name = "Disallow Item Use" else // winset(usr,"default.target_can_click","is-flat=false;border=none") usr << "Target may no longer use items." if(usr.item_use_icon) usr.item_use_icon.dir = 2 usr.item_use_icon.name = "Allow Item Use" for(var/obj/item/weapon/gun/G in src) G.lock_time = world.time + 5 if(G.target) for(var/mob/living/M in G.target) if(!target_can_click) M << "Your character may now use items at the discretion of their targeter." else M << "\red Your character will now be shot if they use items." ToggleGunMode() set hidden = 1 spawn(1) gun_mode = !gun_mode if(!gun_mode) // winset(usr,"default.target_can_click","is-flat=true;border=sunken") usr << "You will now take people captive." if(usr.gun_setting_icon) usr.gun_setting_icon.dir = 2 else // winset(usr,"default.target_can_click","is-flat=false;border=none") usr << "You will now shoot where you target." if(usr.gun_setting_icon) usr.gun_setting_icon.dir = 1