diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f4487cea6c9..3f3c81cc625 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -51,6 +51,7 @@ attack_verb = list("struck", "hit", "bashed") zoomdevicename = "scope" + var/automatic = 0 var/burst = 1 var/fire_delay = 6 //delay after shooting before the gun can be used again var/burst_delay = 2 //delay between shots, if firing in bursts @@ -68,7 +69,8 @@ var/requires_two_hands var/wielded_icon = "gun_wielded" var/one_handed_penalty = 0 // Penalty applied if someone fires a two-handed gun with one hand. - + var/obj/screen/auto_target/auto_target + var/shooting = 0 var/next_fire_time = 0 var/sel_mode = 1 //index of the currently selected mode @@ -87,7 +89,6 @@ var/obj/item/dnalockingchip/attached_lock var/last_shot = 0 //records the last shot fired - /obj/item/weapon/gun/New() ..() for(var/i in 1 to firemodes.len) @@ -177,8 +178,23 @@ if(user && user.a_intent == I_HELP && user.is_preference_enabled(/datum/client_preference/safefiring)) //regardless of what happens, refuse to shoot if help intent is on user << "You refrain from firing your [src] as your intent is set to help." - else - Fire(A,user,params) //Otherwise, fire normally. + return + + if(automatic == 1)//Are we are going to be using automatic shooting + //We check to make sure they can fire + if(!special_check(user)) + return + if(auto_target)//If they already have one then update it + auto_target.loc = get_turf(A) + auto_target.delay_del = 1//And reset the del so its like they got a new one and doesnt instantly vanish + to_chat(user, "You ready \the [src]! Click and drag the target around to shoot.") + else//Otherwise just make a new one + auto_target = new/obj/screen/auto_target(get_turf(A), src) + visible_message("\[user] readies the [src]!") + playsound(src, 'sound/weapons/TargetOn.ogg', 50, 1) + to_chat(user, "You ready \the [src]! Click and drag the target around to shoot.") + return + Fire(A,user,params) //Otherwise, fire normally. /obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone) if (A == user && user.zone_sel.selecting == O_MOUTH && !mouthshoot) @@ -278,8 +294,8 @@ return var/shoot_time = (burst - 1)* burst_delay - user.setClickCooldown(shoot_time) //no clicking on things while shooting - user.setMoveCooldown(shoot_time) //no moving while shooting either + //user.setClickCooldown(shoot_time) //no clicking on things while shooting //These are currently disabled to allow for the automatic system to function without causing near-permanant paralysis. + //user.setMoveCooldown(shoot_time) //no moving while shooting either next_fire_time = world.time + shoot_time var/held_acc_mod = 0 @@ -291,7 +307,23 @@ //actually attempt to shoot var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed. + shooting = 1 + if(automatic == 1 && auto_target && auto_target.active)//When we are going to shoot and have an auto_target AND its active meaning we clicked on it we tell it to burstfire 1000 rounds + burst = 1000//Yes its not EXACTLY full auto but when are we shooting more than 1000 normally and it can easily be made higher + for(var/i in 1 to burst) + if(!reflex && automatic)//If we are shooting automatic then check our target, however if we are shooting reflex we dont use automatic + //extra sanity checking. + if(user.paralysis >= 1) + return + if(user.get_active_hand() != src) + break + if(!auto_target) break//Stopped shooting + else if(auto_target.loc) + target = auto_target.loc + //Lastly just update our dir if needed + if(user.dir != get_dir(user, auto_target)) + user.face_atom(auto_target) var/obj/projectile = consume_next_projectile(user) if(!projectile) handle_click_empty(user) @@ -316,7 +348,7 @@ pointblank = 0 last_shot = world.time - + shooting = 0 // We do this down here, so we don't get the message if we fire an empty gun. if(requires_two_hands) if(user.item_is_in_hands(src) && user.hands_are_full()) diff --git a/code/modules/projectiles/guns/automagical.dm b/code/modules/projectiles/guns/automagical.dm new file mode 100644 index 00000000000..e4b19092a7e --- /dev/null +++ b/code/modules/projectiles/guns/automagical.dm @@ -0,0 +1,70 @@ +//True automagic gun modes. Dakka dakka. +//A significant portion of this code was donated by Mport from SS:CM + +//This is used by guns shooting in automatic mode +/obj/screen/auto_target + name = "targeter" + icon = null//We dont want people to see this guy + density = 0 + anchored = 1 + var/obj/item/weapon/gun/gun + var/active = 0//Just tells us that it was clicked on so we should start shooting + var/delay_del = 0//Delays the del if we retarget without shooting + +/obj/screen/auto_target/New(loc, var/obj/item/weapon/gun/G) + ..() + gun = G + var/image/I = image('icons/effects/Targeted.dmi', src, "locked") + I.override = 1 + usr << I + //autodel() //Currently doesn't really work right. + return + +/obj/screen/auto_target/CanPass()//Everything should ignore this guy and just pass by + return 1 + + //Used to get rid of this if they target but dont actually shoot or stop shooting (no ammo) yet are still dragging us around +/obj/screen/auto_target/proc/autodel() + set waitfor=0 + if(active == 1) + return + sleep(20) + if(!src) return//Might not really be needed + if(delay_del)//This says we want to wait another X seconds before trying to del + delay_del = 0 + autodel() + return + if(gun.shooting == 0) + del(src) + else + autodel()//Yes in theory this could hit the inf loop + return + + //When the player clicks on the target it will disable the autodel and tell the gun to shoot +/obj/screen/auto_target/MouseDown(location,control,params) + active += 1//Tell the autodel that we are actually using this now + if(gun.shooting == 0)//If we are not shooting start shooting, we need this here or they have to drag to a new turf before it starts shooting, felt weird + gun.Fire(loc, usr, params) + return + + //Called when they drag the object somewhere else + //If its not already shooting (should be though due to the above, but this does let it click at you when it runs dry) then start shooting, +/obj/screen/auto_target/MouseDrag(over_object,src_location,over_location,src_control,over_control,params) + if(gun.shooting == 0)//If we are not shooting start shooting + gun.Fire(loc, usr, params) + if(over_location != loc)//This updates the loc to our new location when we drag it to a new turf + loc = over_location + if((usr.get_active_hand() != gun)) + del(src) + + //This gets rid of us when they let go of the click, but only after they actually drag the target to a new turf which is why the below also has to exist +/obj/screen/auto_target/MouseDrop(over_object,src_location,over_location,src_control,over_control,params) + del(src) + return + //This is needed so if they just MouseDown and then let go it will stop shooting, otherwise we stick around till they run out of bullets +/obj/screen/auto_target/MouseUp(object,location,control,params) + del(src) + return + +//This pseudo code is being left in place to serve as references to the modifications to gun.dm, the Fire() proc, and the afterattack() proc. -k22 +//Code donated by Mport. diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 70138487e37..beb44e1a3e9 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -209,5 +209,5 @@ obj/item/weapon/gun/energy/staff/focus firemodes = list( list(mode_name="single shot", burst = 1, burst_accuracy = list(5), dispersion = list(0), charge_cost = 24), list(mode_name="five shot burst", burst = 5, burst_accuracy = list(5,5,5,5,5), dispersion = list(1,1,1,1,1)), - list(mode_name="ten shot burst", burst = 10, burst_accuracy = list(5,5,5,5,5,5,5,5,5,5), dispersion = list(2,2,2,2,2,2,2,2,2,2)), - ) + list(mode_name="ten shot burst", burst = 10, burst_accuracy = list(5,5,5,5,5,5,5,5,5,5), dispersion = list(2,2,2,2,2,2,2,2,2,2)) + ) \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 19b92db3b7b..75f92135716 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -191,9 +191,10 @@ one_handed_penalty = 6 firemodes = list( - list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null), - list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)), - list(mode_name="short bursts", burst=5, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)) + list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null, automatic = 0), + list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0), automatic = 0), + list(mode_name="short bursts", burst=5, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2), automatic = 0), + list(mode_name="automatic", burst=1, fire_delay=-1, move_delay=null, burst_accuracy=null, dispersion=null, automatic = 1), ) var/cover_open = 0 @@ -370,4 +371,4 @@ icon_state = "bullpup" else item_state = "bullpup-empty" - if(!ignore_inhands) update_held_icon() \ No newline at end of file + if(!ignore_inhands) update_held_icon() diff --git a/polaris.dme b/polaris.dme index 81502edfc1e..2eb2b728254 100644 --- a/polaris.dme +++ b/polaris.dme @@ -2060,6 +2060,7 @@ #include "code\modules\projectiles\ammunition\magazines.dm" #include "code\modules\projectiles\ammunition\magnetic.dm" #include "code\modules\projectiles\ammunition\rounds.dm" +#include "code\modules\projectiles\guns\automagical.dm" #include "code\modules\projectiles\guns\energy.dm" #include "code\modules\projectiles\guns\launcher.dm" #include "code\modules\projectiles\guns\modular_guns.dm"