diff --git a/code/_onclick/autoclick.dm b/code/_onclick/autoclick.dm index 1ceeb182ed..7b6e2f108a 100644 --- a/code/_onclick/autoclick.dm +++ b/code/_onclick/autoclick.dm @@ -14,7 +14,7 @@ selected_target[1] = null /client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params) - if(selected_target[1] && over_object.IsAutoclickable()) + if(selected_target[1] && over_object && over_object.IsAutoclickable()) selected_target[1] = over_object selected_target[2] = params diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index ca51e20cc6..bb4bf455dc 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -332,3 +332,4 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/ SSticker.station_explosion_cinematic(1,"gang war", null) SSticker.mode.explosion_in_progress = 0 SSticker.force_ending = TRUE + diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm index 075309b9d3..0ff9ef4f2d 100644 --- a/code/game/gamemodes/gang/gang_datum.dm +++ b/code/game/gamemodes/gang/gang_datum.dm @@ -28,6 +28,7 @@ var/static/list/boss_items = list( /datum/gang_item/function/gang_ping, /datum/gang_item/function/recall, + /datum/gang_item/clothing/under, /datum/gang_item/clothing/suit, /datum/gang_item/clothing/hat, @@ -36,21 +37,29 @@ /datum/gang_item/clothing/mask, /datum/gang_item/clothing/hands, /datum/gang_item/clothing/belt, + /datum/gang_item/weapon/shuriken, /datum/gang_item/weapon/switchblade, + /datum/gang_item/weapon/improvised, + /datum/gang_item/weapon/ammo/improvised_ammo, + /datum/gang_item/weapon/surplus, + /datum/gang_item/weapon/ammo/surplus_ammo, /datum/gang_item/weapon/pistol, /datum/gang_item/weapon/ammo/pistol_ammo, /datum/gang_item/weapon/sniper, /datum/gang_item/weapon/ammo/sniper_ammo, + /datum/gang_item/weapon/machinegun, /datum/gang_item/weapon/uzi, /datum/gang_item/weapon/ammo/uzi_ammo, /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/spraycan, - /datum/gang_item/equipment/c4, + /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/emp, + /datum/gang_item/equipment/c4, /datum/gang_item/equipment/frag, - /datum/gang_item/equipment/implant_breaker, /datum/gang_item/equipment/stimpack, + /datum/gang_item/equipment/implant_breaker, + /datum/gang_item/equipment/wetwork_boots, /datum/gang_item/equipment/pen, /datum/gang_item/equipment/dominator ) @@ -66,21 +75,29 @@ /datum/gang_item/clothing/mask, /datum/gang_item/clothing/hands, /datum/gang_item/clothing/belt, - /datum/gang_item/weapon/shuriken, + + /datum/gang_item/weapon/shuriken, /datum/gang_item/weapon/switchblade, + /datum/gang_item/weapon/improvised, + /datum/gang_item/weapon/ammo/improvised_ammo, + /datum/gang_item/weapon/surplus, + /datum/gang_item/weapon/ammo/surplus_ammo, /datum/gang_item/weapon/pistol, /datum/gang_item/weapon/ammo/pistol_ammo, /datum/gang_item/weapon/sniper, /datum/gang_item/weapon/ammo/sniper_ammo, + /datum/gang_item/weapon/machinegun, /datum/gang_item/weapon/uzi, /datum/gang_item/weapon/ammo/uzi_ammo, /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/spraycan, - /datum/gang_item/equipment/c4, + /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/emp, + /datum/gang_item/equipment/c4, /datum/gang_item/equipment/frag, - /datum/gang_item/equipment/implant_breaker, /datum/gang_item/equipment/stimpack, + /datum/gang_item/equipment/implant_breaker, + /datum/gang_item/equipment/wetwork_boots, ) /datum/gang/New(loc,gangname) @@ -165,7 +182,6 @@ var/diff = domination_timer - world.time return diff / 10 - //////////////////////////////////////////// MESSAGING @@ -283,4 +299,4 @@ ganghud = new() /datum/gang/multiverse/income() - return \ No newline at end of file + return diff --git a/code/game/gamemodes/gang/gang_items.dm b/code/game/gamemodes/gang/gang_items.dm index b5237040f1..aec9b040cd 100644 --- a/code/game/gamemodes/gang/gang_items.dm +++ b/code/game/gamemodes/gang/gang_items.dm @@ -199,10 +199,34 @@ cost = 5 item_path = /obj/item/weapon/switchblade +/datum/gang_item/weapon/surplus + name = "Surplus Rifle" + id = "surplus" + cost = 8 + item_path = /obj/item/weapon/gun/ballistic/automatic/surplus + +/datum/gang_item/weapon/ammo/surplus_ammo + name = "Surplus Rifle Ammo" + id = "surplus_ammo" + cost = 5 + item_path = /obj/item/ammo_box/magazine/m10mm/rifle + +/datum/gang_item/weapon/improvised + name = "Sawn-Off Improvised Shotgun" + id = "sawn" + cost = 6 + item_path = /obj/item/weapon/gun/ballistic/revolver/doublebarrel/improvised/sawn + +/datum/gang_item/weapon/ammo/improvised_ammo + name = "Box of Buckshot" + id = "buckshot" + cost = 5 + item_path = /obj/item/weapon/storage/box/lethalshot + /datum/gang_item/weapon/pistol name = "10mm Pistol" id = "pistol" - cost = 25 + cost = 30 item_path = /obj/item/weapon/gun/ballistic/automatic/pistol /datum/gang_item/weapon/ammo/pistol_ammo @@ -223,12 +247,19 @@ cost = 15 item_path = /obj/item/ammo_box/magazine/sniper_rounds +/datum/gang_item/weapon/machinegun + name = "Mounted Machine Gun" + id = "MG" + cost = 50 + item_path = /obj/machinery/manned_turret + spawn_msg = "The mounted machine gun features enhanced responsiveness. Hold down on the trigger while firing to control where you're shooting." + /datum/gang_item/weapon/uzi name = "Uzi SMG" id = "uzi" cost = 60 item_path = /obj/item/weapon/gun/ballistic/automatic/mini_uzi - id = "uzi" + /datum/gang_item/weapon/ammo/uzi_ammo name = "Uzi Ammo" @@ -236,8 +267,6 @@ cost = 40 item_path = /obj/item/ammo_box/magazine/uzim9mm - - /////////////////// //EQUIPMENT /////////////////// @@ -274,13 +303,13 @@ /datum/gang_item/equipment/frag name = "Fragmentation Grenade" id = "frag nade" - cost = 10 + cost = 18 item_path = /obj/item/weapon/grenade/syndieminibomb/concussion/frag /datum/gang_item/equipment/stimpack name = "Black Market Stimulants" id = "stimpack" - cost = 15 + cost = 12 item_path = /obj/item/weapon/reagent_containers/syringe/stimulants /datum/gang_item/equipment/implant_breaker @@ -297,6 +326,18 @@ if(spawn_msg) to_chat(user, spawn_msg) +/datum/gang_item/equipment/wetwork_boots + name = "Wetwork boots" + id = "wetwork" + cost = 20 + item_path = /obj/item/clothing/shoes/combat/gang + +/obj/item/clothing/shoes/combat/gang + name = "Wetwork boots" + desc = "A gang's best hitmen are prepared for anything." + permeability_coefficient = 0.01 + flags = NOSLIP + /datum/gang_item/equipment/pen name = "Recruitment Pen" id = "pen" @@ -390,4 +431,4 @@ return ..() /datum/gang_item/equipment/dominator/spawn_item(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool) - new item_path(user.loc) \ No newline at end of file + new item_path(user.loc) diff --git a/code/game/gamemodes/gang/gang_pen.dm b/code/game/gamemodes/gang/gang_pen.dm index 01b8504e82..d60a3cb57b 100644 --- a/code/game/gamemodes/gang/gang_pen.dm +++ b/code/game/gamemodes/gang/gang_pen.dm @@ -66,4 +66,4 @@ cooldown = 0 icon_state = "pen" var/mob/M = get(src, /mob) - to_chat(M, "\icon[src] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.") \ No newline at end of file + to_chat(M, "\icon[src] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.") diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm index c9fcf3c074..ad2da7b502 100644 --- a/code/game/gamemodes/gang/recaller.dm +++ b/code/game/gamemodes/gang/recaller.dm @@ -240,6 +240,7 @@ /obj/item/device/gangtool/spare/lt promotable = 1 + ///////////// Internal tool used by gang regulars /////////// /obj/item/device/gangtool/soldier diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 6bab77fd6f..ae9d485447 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -1,9 +1,9 @@ #define TURRET_STUN 0 #define TURRET_LETHAL 1 -#define POPUP_ANIM_TIME 5 -#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad - +#define POPUP_ANIM_TIME 5 +#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad + /obj/machinery/porta_turret name = "turret" icon = 'icons/obj/turrets.dmi' @@ -87,9 +87,9 @@ if(has_cover) cover = new /obj/machinery/porta_turret_cover(loc) cover.parent_turret = src - underlays += image('icons/obj/turrets.dmi',icon_state = "basedark") + underlays += image('icons/obj/turrets.dmi',icon_state = "basedark") if(!has_cover) - INVOKE_ASYNC(src, .proc/popUp) + INVOKE_ASYNC(src, .proc/popUp) /obj/machinery/porta_turret/update_icon() cut_overlays() @@ -368,10 +368,10 @@ var/list/targets = list() var/turretview = view(scan_range, base) for(var/A in turretview) - var/atom/AA = A - if(AA.invisibility>SEE_INVISIBLE_LIVING) - continue - + var/atom/AA = A + if(AA.invisibility>SEE_INVISIBLE_LIVING) + continue + if(check_anomalies)//if it's set to check for simple animals if(istype(A, /mob/living/simple_animal)) var/mob/living/simple_animal/SA = A @@ -426,7 +426,7 @@ raising = 1 if(cover) flick("popup", cover) - sleep(POPUP_ANIM_TIME) + sleep(POPUP_ANIM_TIME) raising = 0 if(cover) cover.icon_state = "openTurretCover" @@ -442,7 +442,7 @@ raising = 1 if(cover) flick("popdown", cover) - sleep(POPDOWN_ANIM_TIME) + sleep(POPDOWN_ANIM_TIME) raising = 0 if(cover) cover.icon_state = "turretCover" @@ -792,7 +792,7 @@ /obj/item/wallframe/turret_control name = "turret control frame" desc = "Used for building turret control panels" - icon_state = "apc" + icon_state = "apc" result_path = /obj/machinery/turretid materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT) @@ -921,3 +921,170 @@ on = 0 spawn(100) on = 1 + +/////// MANNED TURRET //////// + +/obj/machinery/manned_turret + name = "machine gun turret" + desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets." + icon = 'icons/obj/turrets.dmi' + icon_state = "machinegun" + can_buckle = TRUE + density = TRUE + max_integrity = 100 + obj_integrity = 100 + buckle_lying = 0 + layer = ABOVE_MOB_LAYER + var/view_range = 10 + var/cooldown = 0 + var/projectile_type = /obj/item/projectile/bullet/weakbullet3 + var/rate_of_fire = 1 + var/number_of_shots = 40 + var/cooldown_duration = 90 + var/atom/target + var/turf/target_turf + var/warned = FALSE + +//BUCKLE HOOKS + +/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = 0) + playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) + for(var/obj/item/I in buckled_mob.held_items) + if(istype(I, /obj/item/gun_control)) + qdel(I) + if(istype(buckled_mob)) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + if(buckled_mob.client) + buckled_mob.client.change_view(world.view) + anchored = FALSE + . = ..() + +/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user) + if(user.incapacitated() || !istype(user)) + return + M.forceMove(get_turf(src)) + ..() + for(var/V in M.held_items) + var/obj/item/I = V + if(istype(I)) + if(M.dropItemToGround(I)) + var/obj/item/gun_control/TC = new /obj/item/gun_control(src) + M.put_in_hands(TC) + else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand + var/obj/item/gun_control/TC = new /obj/item/gun_control(src) + M.put_in_hands(TC) + M.pixel_y = 14 + layer = ABOVE_MOB_LAYER + setDir(SOUTH) + playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) + anchored = TRUE + if(user.client) + user.client.change_view(view_range) + +/obj/item/gun_control + name = "turret controls" + icon = 'icons/obj/weapons.dmi' + icon_state = "offhand" + w_class = WEIGHT_CLASS_HUGE + flags = ABSTRACT | NODROP + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF | NOBLUDGEON + var/obj/machinery/manned_turret/turret + +/obj/item/gun_control/New(obj/machinery/manned_turret/MT) + if(MT) + turret = MT + else + qdel(src) + +/obj/item/gun_control/CanItemAutoclick() + return 1 + +/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user) + ..() + var/obj/machinery/manned_turret/E = user.buckled + E.setDir(get_dir(E,targeted_atom)) + user.setDir(E.dir) + switch(E.dir) + if(NORTH) + E.layer = BELOW_MOB_LAYER + user.pixel_x = 0 + user.pixel_y = -14 + if(NORTHEAST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = -8 + user.pixel_y = -4 + if(EAST) + E.layer = ABOVE_MOB_LAYER + user.pixel_x = -14 + user.pixel_y = 0 + if(SOUTHEAST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = -8 + user.pixel_y = 4 + if(SOUTH) + E.layer = ABOVE_MOB_LAYER + user.pixel_x = 0 + user.pixel_y = 14 + if(SOUTHWEST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = 8 + user.pixel_y = 4 + if(WEST) + E.layer = ABOVE_MOB_LAYER + user.pixel_x = 14 + user.pixel_y = 0 + if(NORTHWEST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = 8 + user.pixel_y = -4 + E.checkfire(targeted_atom, user) + +/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user) + target = targeted_atom + if(target == user || target == get_turf(src)) + return + if(world.time < cooldown) + if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing + warned = TRUE + playsound(src, 'sound/weapons/sear.ogg', 100, 1) + return + else + cooldown = world.time + cooldown_duration + warned = FALSE + INVOKE_ASYNC(src, /obj/machinery/manned_turret/.proc/volley) + +/obj/machinery/manned_turret/proc/volley() + target_turf = get_turf(target) + for(var/i in 1 to number_of_shots) + addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper), i*rate_of_fire) + + +/obj/machinery/manned_turret/proc/fire_helper() + if(!src) + return + var/turf/targets_from = get_turf(src) + if(QDELETED(target)) + target = target_turf + var/obj/item/projectile/P = new projectile_type(targets_from) + P.current = targets_from + P.starting = targets_from + P.firer = src + P.original = target + playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1) + P.yo = target.y - targets_from.y + rand(-1,1) + P.xo = target.x - targets_from.x + rand(-1,1) + P.fire() + +/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics + name = "Infinity Gun" + view_range = 12 + projectile_type = /obj/item/projectile/bullet/weakbullet3 + + +/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user) + target = targeted_atom + if(target == user || target == get_turf(src)) + return + target_turf = get_turf(target) + fire_helper(target_turf) diff --git a/code/modules/projectiles/boxes_magazines/external_mag.dm b/code/modules/projectiles/boxes_magazines/external_mag.dm index 11112ec974..72cbc25f12 100644 --- a/code/modules/projectiles/boxes_magazines/external_mag.dm +++ b/code/modules/projectiles/boxes_magazines/external_mag.dm @@ -13,6 +13,21 @@ max_ammo = 8 multiple_sprites = 2 +/obj/item/ammo_box/magazine/m10mm/rifle + name = "rifle magazine (10mm)" + desc = "A well-worn magazine fitted for the surplus rifle." + icon_state = "75-8" + origin_tech = "combat=2" + ammo_type = /obj/item/ammo_casing/c10mm + caliber = "10mm" + max_ammo = 10 + +/obj/item/ammo_box/magazine/m10mm/rifle/update_icon() + if(ammo_count()) + icon_state = "75-8" + else + icon_state = "75-0" + /obj/item/ammo_box/magazine/m10mm/fire name = "pistol magazine (10mm incendiary)" desc = "A gun magazine. Loaded with rounds which ignite the target." diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 1ffdaf0d29..0235bbe84d 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -375,8 +375,29 @@ pin = /obj/item/device/firing_pin/implant/pindicate origin_tech = "combat=7;syndicate=6" +// Old Semi-Auto Rifle // +/obj/item/weapon/gun/ballistic/automatic/surplus + name = "Surplus Rifle" + desc = "One of countless obsolete ballistic rifles that still sees use as a cheap deterrent. Uses 10mm ammo and its bulky frame prevents one-hand firing." + origin_tech = "combat=3;materials=2" + icon_state = "surplus" + item_state = "moistnugget" + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/m10mm/rifle + fire_delay = 30 + burst_size = 1 + can_unsuppress = 1 + can_suppress = 1 + w_class = WEIGHT_CLASS_HUGE + slot_flags = SLOT_BACK + actions_types = list() +/obj/item/weapon/gun/ballistic/automatic/surplus/update_icon() + if(magazine) + icon_state = "surplus" + else + icon_state = "surplus-e" // Laser rifle (rechargeable magazine) // diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 6ce52748ec..ac3c56b88a 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -344,6 +344,15 @@ slung = 0 update_icon() +/obj/item/weapon/gun/ballistic/revolver/doublebarrel/improvised/sawn + name = "sawn-off improvised shotgun" + desc = "A single-shot shotgun, better not miss" + icon_state = "ishotgun" + item_state = "gun" + w_class = WEIGHT_CLASS_NORMAL + sawn_state = SAWN_OFF + slot_flags = SLOT_BELT + /obj/item/weapon/gun/ballistic/revolver/reverse //Fires directly at its user... unless the user is a clown, of course. clumsy_check = 0 diff --git a/icons/obj/turrets.dmi b/icons/obj/turrets.dmi index c4077b6601..b186c3f224 100644 Binary files a/icons/obj/turrets.dmi and b/icons/obj/turrets.dmi differ