diff --git a/code/game/hud.dm b/code/game/hud.dm index 4d2e37532d9..9a29adc082b 100644 --- a/code/game/hud.dm +++ b/code/game/hud.dm @@ -45,6 +45,12 @@ #define ui_borg_module "13:26,2:7" #define ui_borg_panel "14:28,2:7" +//Gun buttons +#define ui_gun1 "13:26,2:5" +#define ui_gun2 "12:24,2:5" +#define ui_gun3 "11:22,2:5" +#define ui_gun_select "14:28,3:7" + //Upper-middle right (damage indicators) #define ui_toxin "14:28,13:27" #define ui_fire "14:28,12:25" diff --git a/code/modules/mob/living/carbon/human/hud.dm b/code/modules/mob/living/carbon/human/hud.dm index baaa63bd93d..86c08fbddc0 100644 --- a/code/modules/mob/living/carbon/human/hud.dm +++ b/code/modules/mob/living/carbon/human/hud.dm @@ -485,9 +485,11 @@ mymob.zone_sel.overlays = null mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.gun_setting_icon = new /obj/screen/gun/mode(null) + mymob.client.screen = null - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.nutrition_icon, mymob.pullin, mymob.blind, mymob.flash, mymob.damageoverlay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.nutrition_icon, mymob.pullin, mymob.blind, mymob.flash, mymob.damageoverlay, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) mymob.client.screen += src.adding + src.hotkeybuttons inventory_shown = 0; diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 16c740f6dc8..3cad3a2f64d 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -64,6 +64,7 @@ There are several things that need to be remembered: update_body() //Handles updating your mob's icon to reflect their gender/race/complexion etc update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and ...eyes were merged into update_body) + update_targeted() // Updates the target overlay when someone points a gun at you > All of these procs update our overlays_lying and overlays_standing, and then call update_icons() by default. If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call @@ -117,7 +118,8 @@ Please contact me on #coderbus IRC. ~Carn x #define L_HAND_LAYER 19 #define R_HAND_LAYER 20 #define TAIL_LAYER 21 //bs12 specific. this hack is probably gonna come back to haunt me -#define TOTAL_LAYERS 21 +#define TARGETED_LAYER 22 //BS12: Layer for the target overlay from weapon targeting system +#define TOTAL_LAYERS 22 ////////////////////////////////// /mob/living/carbon/human @@ -441,6 +443,30 @@ proc/get_damage_icon_part(damage_state, body_part) update_hair(0) if(update_icons) update_icons() +/mob/living/carbon/human/proc/update_targeted(var/update_icons=1) + // If someone's targeting you + if (targeted_by.len) + + //If the target is already there and finished locking (after two seconds), put in locked state and be done + if (overlays_standing[TARGETED_LAYER]) + var/target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locked") + overlays_lying[TARGETED_LAYER] = target_locked + overlays_standing[TARGETED_LAYER] = target_locked + return + + var/target_locking = new/image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locking") + + //Put in our overlay, since it isn't already there + overlays_lying[TARGETED_LAYER] = target_locking + overlays_standing[TARGETED_LAYER] = target_locking + + else + overlays_lying[TARGETED_LAYER] = null + overlays_standing[TARGETED_LAYER] = null + + if(update_icons) update_icons() + + /* --------------------------------------- */ //For legacy support. /mob/living/carbon/human/regenerate_icons() diff --git a/code/modules/mob/living/carbon/monkey/hud.dm b/code/modules/mob/living/carbon/monkey/hud.dm index bffdc9468ad..54b487ca680 100644 --- a/code/modules/mob/living/carbon/monkey/hud.dm +++ b/code/modules/mob/living/carbon/monkey/hud.dm @@ -220,9 +220,11 @@ mymob.zone_sel.overlays = null mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.gun_setting_icon = new /obj/screen/gun/mode(null) + mymob.client.screen = null - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) mymob.client.screen += src.adding + src.other return diff --git a/code/modules/mob/living/silicon/robot/hud.dm b/code/modules/mob/living/silicon/robot/hud.dm index 88ef5577055..0087c13e969 100644 --- a/code/modules/mob/living/silicon/robot/hud.dm +++ b/code/modules/mob/living/silicon/robot/hud.dm @@ -143,9 +143,11 @@ mymob.zone_sel.overlays = null mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + mymob.gun_setting_icon = new /obj/screen/gun/mode(null) + mymob.client.screen = null - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash) //, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon) //, mymob.rest, mymob.sleep, mymob.mach ) mymob.client.screen += src.adding + src.other return diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 068851304c6..d69fc758db0 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -28,6 +28,13 @@ var/obj/screen/pressure = null var/obj/screen/damageoverlay = null var/obj/screen/pain = null + var/obj/screen/gun/item/item_use_icon = null + var/obj/screen/gun/move/gun_move_icon = null + var/obj/screen/gun/run/gun_run_icon = null + var/obj/screen/gun/mode/gun_setting_icon = null + +// var/total_luminosity = 0 //This controls luminosity for mobs, when you pick up lights and such this is edited. If you want the mob to use lights it must update its lum in its life proc or such. Note clamp this value around 7 or such to prevent massive light lag. +// var/last_luminosity = 0 /*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob. A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such. diff --git a/code/modules/mob/screen.dm b/code/modules/mob/screen.dm index 3cc082d1798..53f705bead9 100644 --- a/code/modules/mob/screen.dm +++ b/code/modules/mob/screen.dm @@ -5,6 +5,7 @@ unacidable = 1 var/id = 0.0 var/obj/master + var/gun_click_time = -100 //I'm lazy. /obj/screen/inventory var/slot_id @@ -64,6 +65,33 @@ var/selecting = "chest" screen_loc = ui_zonesel +/obj/screen/gun + name = "gun" + icon = 'screen1.dmi' + master = null + dir = 2 + + move + name = "Allow Walking" + icon_state = "no_walk" + screen_loc = ui_gun2 + + run + name = "Allow Running" + icon_state = "no_run" + screen_loc = ui_gun3 + + item + name = "Allow Item Use" + icon_state = "no_item" + screen_loc = ui_gun1 + + mode + name = "Toggle Gun Mode" + icon_state = "gun" + screen_loc = ui_gun_select + dir = 1 + /obj/screen/zone_sel/MouseDown(location, control,params) // Changes because of 4.0 @@ -456,6 +484,64 @@ if("radar closed") usr:start_radar() + if("Allow Walking") + if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. + return + if(!istype(usr.equipped(),/obj/item/weapon/gun)) + usr << "You need your gun in your active hand to do that!" + return + usr.client.AllowTargetMove() + gun_click_time = world.time + + if("Disallow Walking") + if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. + return + if(!istype(usr.equipped(),/obj/item/weapon/gun)) + usr << "You need your gun in your active hand to do that!" + return + usr.client.AllowTargetMove() + gun_click_time = world.time + + if("Allow Running") + if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. + return + if(!istype(usr.equipped(),/obj/item/weapon/gun)) + usr << "You need your gun in your active hand to do that!" + return + usr.client.AllowTargetRun() + gun_click_time = world.time + + if("Disallow Running") + if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. + return + if(!istype(usr.equipped(),/obj/item/weapon/gun)) + usr << "You need your gun in your active hand to do that!" + return + usr.client.AllowTargetRun() + gun_click_time = world.time + + if("Allow Item Use") + if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. + return + if(!istype(usr.equipped(),/obj/item/weapon/gun)) + usr << "You need your gun in your active hand to do that!" + return + usr.client.AllowTargetClick() + gun_click_time = world.time + + + if("Disallow Item Use") + if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes. + return + if(!istype(usr.equipped(),/obj/item/weapon/gun)) + usr << "You need your gun in your active hand to do that!" + return + usr.client.AllowTargetClick() + gun_click_time = world.time + + if("Toggle Gun Mode") + usr.client.ToggleGunMode() + else DblClick() return diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 1dd3ca5114b..b642f088b32 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -22,7 +22,12 @@ var/recoil = 0 var/ejectshell = 1 var/clumsy_check = 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 @@ -34,6 +39,17 @@ 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 ..() special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver. return 1 @@ -43,10 +59,99 @@ 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 - afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)//TODO: go over this - 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? +//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' + + proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)//TODO: go over this //Exclude lasertag guns from the CLUMSY check. if(src.clumsy_check) @@ -77,8 +182,10 @@ if(!special_check(user)) return - if(!load_into_chamber()) - user << "\red *click*"; + if(!load_into_chamber()) //CHECK + user.visible_message("*click click*", "\red *click*") + for(var/mob/K in viewers(usr)) + K << 'empty.ogg' return if(!in_chamber) @@ -87,7 +194,6 @@ in_chamber.firer = user in_chamber.def_zone = user.zone_sel.selecting - if(targloc == curloc) user.bullet_act(in_chamber) del(in_chamber) @@ -102,7 +208,10 @@ playsound(user, fire_sound, 10, 1) else playsound(user, fire_sound, 50, 1) - user.visible_message("\red [user.name] fires the [src.name]!", "\red You fire the [src.name]!", "\blue You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!") + 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) @@ -122,13 +231,406 @@ spawn() if(in_chamber) - in_chamber.process() + in_chamber.process() //CHECK Might need to be 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' + // Stolen from sd_get_approx_dir, didn't want to reinclude + var/d=get_dir(M,T) + var/dir_to_fire = d + if(d&d-1) // diagonal + var/ax=abs(M.x-T.x) + var/ay=abs(M.y-T.y) + if(ax>=ay<<1) dir_to_fire = d&12 // keep east/west (4 and 8) + else if(ay>=ax<<1) dir_to_fire = d&3 // keep north/south (1 and 2) + 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)) TODO: Look into admin invisibility in post-merge code + 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) + // Stolen from sd_get_approx_dir, didn't want to reinclude + var/d=get_dir(usr,A) + var/dir_to_fire = d //Turn them to face their target. + if(d&d-1) // diagonal + var/ax=abs(usr.x-A.x) + var/ay=abs(usr.y-A.y) + if(ax>=ay<<1) dir_to_fire = d&12 // keep east/west (4 and 8) + else if(ay>=ax<<1) dir_to_fire = d&3 // keep north/south (1 and 2) + 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" + if (ispath(src,mob/living/carbon/human)) + src:update_icons() + sleep(20) + if(target_locked) + target_locked.icon_state = "locked" + if (ispath(src,mob/living/carbon/human)) + src:update_icons() + 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) + if (ispath(src,mob/living/carbon/human)) + src:update_icons() + +/* 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 /obj/item/weapon/gun/proc/isHandgun() - return 1 + return 1 \ No newline at end of file diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 067ef207acd..c78d9729aed 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -57,6 +57,17 @@ L.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, blocked) return 1 + proc/check_fire(var/mob/living/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not. + if(!istype(target) || !istype(user)) + return 0 + var/obj/item/projectile/test/in_chamber = new /obj/item/projectile/test(get_step_to(user,target)) //Making the test.... + in_chamber.target = target + in_chamber.flags = flags //Set the flags... + in_chamber.pass_flags = pass_flags //And the pass flags to that of the real projectile... + in_chamber.firer = user + var/output = in_chamber.fired() //Test it! + del(in_chamber) //No need for it anymore + return output //Send it back to the gun! Bump(atom/A as mob|obj|turf|area) if(A == firer) @@ -153,3 +164,61 @@ Bump(M) sleep(1) return + + proc/fired() + spawn while(src) + if((!( current ) || loc == current)) + current = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) + if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) + del(src) + return + step_towards(src, current) + sleep(1) + if(!bumped) + if(loc == original) + for(var/mob/living/M in original) + if(!(M in permutated)) + Bump(M) + sleep(1) + return + +/obj/item/projectile/test //Used to see if you can hit them. + invisibility = 101 //Nope! Can't see me! + yo = null + xo = null + var/target = null + var/result = 0 //To pass the message back to the gun. + + Bump(atom/A as mob|obj|turf|area) + if(A == firer) + loc = A.loc + return //cannot shoot yourself + if(istype(A, /obj/item/projectile)) + return + if(istype(A, /mob/living)) + result = 2 //We hit someone, return 1! + return + result = 1 + return + + fired() + var/turf/curloc = get_turf(src) + var/turf/targloc = get_turf(target) + if(!curloc || !targloc) + return 0 + yo = targloc.y - curloc.y + xo = targloc.x - curloc.x + target = targloc + while(src) //Loop on through! + if(result) + return (result - 1) + if((!( target ) || loc == target)) + target = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge + step_towards(src, target) + var/mob/living/M = locate() in get_turf(src) + if(istype(M)) //If there is someting living... + return 1 //Return 1 + else + M = locate() in get_step(src,target) + if(istype(M)) + return 1 diff --git a/icons/mob/screen1.dmi b/icons/mob/screen1.dmi index 6040e7107ce..48b8efcafc1 100644 Binary files a/icons/mob/screen1.dmi and b/icons/mob/screen1.dmi differ diff --git a/icons/mob/screen1_old.dmi b/icons/mob/screen1_old.dmi index 2994f9fd7b5..ebf104c8918 100644 Binary files a/icons/mob/screen1_old.dmi and b/icons/mob/screen1_old.dmi differ