[MIRROR] Deployable Component (Big Dakka Included) (#7380)
* Deployable Component (Big Dakka Included) (#60554) * Deployable Component (Big Dakka Included) Co-authored-by: Paxilmaniac <82386923+Paxilmaniac@users.noreply.github.com>
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Deployable - Bring your big guns with you, and smack em' down where you want.
|
||||
*
|
||||
* Allows items to spawn other items (usually objects) in front of the user after a short delay.
|
||||
* If attaching this to something:
|
||||
* Set deploy_time to a number in seconds for the deploy delay
|
||||
* Set thing_to_be_deployed to an obj path for the thing that gets spawned
|
||||
* Lastly, set delete_on_use to TRUE or FALSE if you want the object you're deploying with to get deleted when used
|
||||
*/
|
||||
|
||||
/datum/component/deployable
|
||||
/// The time it takes to deploy the object
|
||||
var/deploy_time = 5 SECONDS
|
||||
/// The object that gets spawned if deployed successfully
|
||||
var/obj/thing_to_be_deployed
|
||||
/// Used in getting the name of the deployed object
|
||||
var/deployed_name
|
||||
/// If the item used to deploy gets deleted on use or not
|
||||
var/delete_on_use = TRUE
|
||||
|
||||
/datum/component/deployable/Initialize(deploy_time, thing_to_be_deployed, delete_on_use)
|
||||
. = ..()
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.deploy_time = deploy_time
|
||||
src.thing_to_be_deployed = thing_to_be_deployed
|
||||
src.delete_on_use = delete_on_use
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_hand)
|
||||
|
||||
var/obj/item/typecast = thing_to_be_deployed
|
||||
deployed_name = initial(typecast.name)
|
||||
|
||||
/datum/component/deployable/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
examine_list += span_notice("[source.p_they()] look[source.p_s()] like [source.p_they()] can be deployed into \a [deployed_name].")
|
||||
|
||||
/datum/component/deployable/proc/on_attack_hand(datum/source, mob/user, location, direction)
|
||||
SIGNAL_HANDLER
|
||||
INVOKE_ASYNC(src, .proc/deploy, source, user, location, direction)
|
||||
|
||||
/datum/component/deployable/proc/deploy(obj/source, mob/user, location, direction) //If there's no user, location and direction are used
|
||||
var/obj/deployed_object //Used for spawning the deployed object
|
||||
var/turf/deploy_location //Where our deployed_object gets put
|
||||
var/new_direction //What direction do we want our deployed object in
|
||||
if(user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
|
||||
deploy_location = get_step(user, user.dir) //Gets spawn location for thing_to_be_deployed if there is a user
|
||||
if(deploy_location.is_blocked_turf(TRUE))
|
||||
source.balloon_alert(user, "insufficient room to deploy here.")
|
||||
return
|
||||
new_direction = user.dir //Gets the direction for thing_to_be_deployed if there is a user
|
||||
source.balloon_alert(user, "deploying...")
|
||||
playsound(source, 'sound/items/ratchet.ogg', 50, TRUE)
|
||||
if(!do_after(user, deploy_time))
|
||||
return
|
||||
else //If there is for some reason no user, then the location and direction are set here
|
||||
deploy_location = location
|
||||
new_direction = direction
|
||||
|
||||
deployed_object = new thing_to_be_deployed(deploy_location)
|
||||
deployed_object.setDir(new_direction)
|
||||
|
||||
//Sets the integrity of the new deployed machine to that of the object it came from
|
||||
deployed_object.modify_max_integrity(source.max_integrity)
|
||||
deployed_object.update_icon_state()
|
||||
|
||||
if(delete_on_use)
|
||||
qdel(source)
|
||||
@@ -196,6 +196,18 @@
|
||||
/obj/item/grenade/barrier/ui_action_click(mob/user)
|
||||
toggle_mode(user)
|
||||
|
||||
/obj/item/deployable_turret_folded
|
||||
name = "folded heavy machine gun"
|
||||
desc = "A folded and unloaded heavy machine gun, ready to be deployed and used."
|
||||
icon = 'icons/obj/turrets.dmi'
|
||||
icon_state = "folded_hmg"
|
||||
max_integrity = 250
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
|
||||
/obj/item/deployable_turret_folded/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/deployable, 5 SECONDS, /obj/machinery/deployable_turret/hmg, delete_on_use = TRUE)
|
||||
|
||||
#undef SINGLE
|
||||
#undef VERTICAL
|
||||
|
||||
@@ -109,6 +109,15 @@
|
||||
new /obj/item/extinguisher/mini(src)
|
||||
new /obj/item/stack/cable_coil(src)
|
||||
|
||||
/obj/item/storage/belt/utility/full/powertools/rcd/PopulateContents()
|
||||
new /obj/item/screwdriver/power(src)
|
||||
new /obj/item/crowbar/power(src)
|
||||
new /obj/item/weldingtool/experimental(src)
|
||||
new /obj/item/multitool(src)
|
||||
new /obj/item/construction/rcd/loaded/upgraded(src)
|
||||
new /obj/item/extinguisher/mini(src)
|
||||
new /obj/item/stack/cable_coil(src)
|
||||
|
||||
/obj/item/storage/belt/utility/full/engi/PopulateContents()
|
||||
new /obj/item/screwdriver(src)
|
||||
new /obj/item/wrench(src)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/////// MANNED TURRET ////////
|
||||
/// DEPLOYABLE TURRET (FORMERLY MANNED TURRET)
|
||||
//All of this file is five year old shitcode, and I'm too scared to touch more than I have to
|
||||
|
||||
/obj/machinery/manned_turret
|
||||
/obj/machinery/deployable_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'
|
||||
@@ -13,23 +14,53 @@
|
||||
layer = ABOVE_MOB_LAYER
|
||||
var/view_range = 2.5
|
||||
var/cooldown = 0
|
||||
/// The projectile that the turret fires
|
||||
var/projectile_type = /obj/projectile/bullet/manned_turret
|
||||
/// Delay between shots in a burst
|
||||
var/rate_of_fire = 1
|
||||
/// Number of shots fired from one click
|
||||
var/number_of_shots = 40
|
||||
var/cooldown_duration = 90
|
||||
/// How long it takes for the gun to allow firing after a burst
|
||||
var/cooldown_duration = 9 SECONDS
|
||||
var/atom/target
|
||||
var/turf/target_turf
|
||||
var/warned = FALSE
|
||||
var/list/calculated_projectile_vars
|
||||
/// Sound to play at the end of a burst
|
||||
var/overheatsound = 'sound/weapons/sear.ogg'
|
||||
/// Sound to play when firing
|
||||
var/firesound = 'sound/weapons/gun/smg/shot.ogg'
|
||||
/// If using a wrench on the turret will start undeploying it
|
||||
var/can_be_undeployed = FALSE
|
||||
/// What gets spawned if the object is undeployed
|
||||
var/obj/spawned_on_undeploy
|
||||
/// How long it takes for a wrench user to undeploy the object
|
||||
var/undeploy_time = 3 SECONDS
|
||||
|
||||
/obj/machinery/manned_turret/Destroy()
|
||||
/obj/machinery/deployable_turret/Destroy()
|
||||
target = null
|
||||
target_turf = null
|
||||
..()
|
||||
|
||||
/// Undeploying, for when you want to move your big dakka around
|
||||
/obj/machinery/deployable_turret/wrench_act(mob/living/user, obj/item/wrench/used_wrench)
|
||||
. = ..()
|
||||
if(!can_be_undeployed)
|
||||
return
|
||||
if(!ishuman(user))
|
||||
return
|
||||
used_wrench.play_tool_sound(user)
|
||||
user.balloon_alert(user, "undeploying...")
|
||||
if(!do_after(user, undeploy_time))
|
||||
return
|
||||
var/obj/undeployed_object = new spawned_on_undeploy(src)
|
||||
//Keeps the health the same even if you redeploy the gun
|
||||
undeployed_object.modify_max_integrity(max_integrity)
|
||||
qdel(src)
|
||||
|
||||
//BUCKLE HOOKS
|
||||
|
||||
/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = FALSE)
|
||||
/obj/machinery/deployable_turret/unbuckle_mob(mob/living/buckled_mob,force = FALSE)
|
||||
playsound(src,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
||||
for(var/obj/item/I in buckled_mob.held_items)
|
||||
if(istype(I, /obj/item/gun_control))
|
||||
@@ -43,7 +74,7 @@
|
||||
. = ..()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
|
||||
/obj/machinery/deployable_turret/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
|
||||
if(user.incapacitated() || !istype(user))
|
||||
return
|
||||
M.forceMove(get_turf(src))
|
||||
@@ -68,25 +99,26 @@
|
||||
M.client.view_size.setTo(view_range)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/machinery/manned_turret/process()
|
||||
/obj/machinery/deployable_turret/process()
|
||||
if (!update_positioning())
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/machinery/manned_turret/proc/update_positioning()
|
||||
/obj/machinery/deployable_turret/proc/update_positioning()
|
||||
if (!LAZYLEN(buckled_mobs))
|
||||
return FALSE
|
||||
var/mob/living/controller = buckled_mobs[1]
|
||||
if(!istype(controller))
|
||||
return FALSE
|
||||
var/client/C = controller.client
|
||||
if(C)
|
||||
var/atom/A = C.mouseObject
|
||||
var/turf/T = get_turf(A)
|
||||
if(istype(T)) //They're hovering over something in the map.
|
||||
direction_track(controller, T)
|
||||
calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(controller, C.mouseParams)
|
||||
var/client/controlling_client = controller.client
|
||||
if(controlling_client)
|
||||
var/modifiers = params2list(controlling_client.mouseParams)
|
||||
var/atom/target_atom = controlling_client.mouseObject
|
||||
var/turf/target_turf = get_turf(target_atom)
|
||||
if(istype(target_turf)) //They're hovering over something in the map.
|
||||
direction_track(controller, target_turf)
|
||||
calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(controller, modifiers)
|
||||
|
||||
/obj/machinery/manned_turret/proc/direction_track(mob/user, atom/targeted)
|
||||
/obj/machinery/deployable_turret/proc/direction_track(mob/user, atom/targeted)
|
||||
if(user.incapacitated())
|
||||
return
|
||||
setDir(get_dir(src,targeted))
|
||||
@@ -125,56 +157,63 @@
|
||||
user.pixel_x = 8
|
||||
user.pixel_y = -4
|
||||
|
||||
/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user)
|
||||
/obj/machinery/deployable_turret/proc/checkfire(atom/targeted_atom, mob/user)
|
||||
target = targeted_atom
|
||||
if(target == user || user.incapacitated() || 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, TRUE)
|
||||
playsound(src, overheatsound, 100, TRUE)
|
||||
return
|
||||
else
|
||||
cooldown = world.time + cooldown_duration
|
||||
warned = FALSE
|
||||
volley(user)
|
||||
|
||||
/obj/machinery/manned_turret/proc/volley(mob/user)
|
||||
/obj/machinery/deployable_turret/proc/volley(mob/user)
|
||||
target_turf = get_turf(target)
|
||||
for(var/i in 1 to number_of_shots)
|
||||
addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper, user), i*rate_of_fire)
|
||||
addtimer(CALLBACK(src, /obj/machinery/deployable_turret/.proc/fire_helper, user), i*rate_of_fire)
|
||||
|
||||
/obj/machinery/manned_turret/proc/fire_helper(mob/user)
|
||||
/obj/machinery/deployable_turret/proc/fire_helper(mob/user)
|
||||
if(user.incapacitated() || !(user in buckled_mobs))
|
||||
return
|
||||
update_positioning() //REFRESH MOUSE TRACKING!!
|
||||
var/turf/targets_from = get_turf(src)
|
||||
if(QDELETED(target))
|
||||
target = target_turf
|
||||
var/obj/projectile/P = new projectile_type(targets_from)
|
||||
P.starting = targets_from
|
||||
P.firer = user
|
||||
P.original = target
|
||||
playsound(src, 'sound/weapons/gun/smg/shot.ogg', 75, TRUE)
|
||||
P.xo = target.x - targets_from.x
|
||||
P.yo = target.y - targets_from.y
|
||||
P.Angle = calculated_projectile_vars[1] + rand(-9, 9)
|
||||
P.p_x = calculated_projectile_vars[2]
|
||||
P.p_y = calculated_projectile_vars[3]
|
||||
P.fire()
|
||||
var/obj/projectile/projectile_to_fire = new projectile_type
|
||||
playsound(src, firesound, 75, TRUE)
|
||||
projectile_to_fire.preparePixelProjectile(target, targets_from)
|
||||
projectile_to_fire.fire()
|
||||
|
||||
/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics
|
||||
/obj/machinery/deployable_turret/ultimate // Admin-only proof of concept for autoclicker automatics
|
||||
name = "Infinity Gun"
|
||||
view_range = 12
|
||||
projectile_type = /obj/projectile/bullet/manned_turret
|
||||
|
||||
/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user)
|
||||
/obj/machinery/deployable_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(user)
|
||||
|
||||
/obj/machinery/deployable_turret/hmg
|
||||
name = "heavy machine gun turret"
|
||||
desc = "A heavy calibre machine gun commonly used by Nanotrasen forces, famed for it's ability to give people on the recieving end more holes than normal."
|
||||
icon_state = "hmg"
|
||||
max_integrity = 250
|
||||
projectile_type = /obj/projectile/bullet/manned_turret/hmg
|
||||
anchored = TRUE
|
||||
number_of_shots = 3
|
||||
cooldown_duration = 2 SECONDS
|
||||
rate_of_fire = 2
|
||||
firesound = 'sound/weapons/gun/hmg/hmg.ogg'
|
||||
overheatsound = 'sound/weapons/gun/smg/smgrack.ogg'
|
||||
can_be_undeployed = TRUE
|
||||
spawned_on_undeploy = /obj/item/deployable_turret_folded
|
||||
|
||||
/obj/item/gun_control
|
||||
name = "turret controls"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
@@ -182,7 +221,7 @@
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
item_flags = ABSTRACT | NOBLUDGEON | DROPDEL
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/obj/machinery/manned_turret/turret
|
||||
var/obj/machinery/deployable_turret/turret
|
||||
|
||||
/obj/item/gun_control/Initialize()
|
||||
. = ..()
|
||||
@@ -210,7 +249,8 @@
|
||||
|
||||
/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params)
|
||||
. = ..()
|
||||
var/obj/machinery/manned_turret/E = user.buckled
|
||||
E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, params)
|
||||
var/modifiers = params2list(params)
|
||||
var/obj/machinery/deployable_turret/E = user.buckled
|
||||
E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, modifiers)
|
||||
E.direction_track(user, targeted_atom)
|
||||
E.checkfire(targeted_atom, user)
|
||||
@@ -619,16 +619,10 @@
|
||||
suit_store = /obj/item/gun/ballistic/shotgun/lethal
|
||||
mask = /obj/item/clothing/mask/cigarette/robustgold
|
||||
head = /obj/item/clothing/head/helmet/marine/engineer
|
||||
back = /obj/item/storage/backpack/ert/engineer
|
||||
backpack_contents = list(
|
||||
/obj/item/construction/rcd/loaded/upgraded = 1,
|
||||
/obj/item/pipe_dispenser = 1,
|
||||
/obj/item/storage/box/lethalshot = 1,
|
||||
/obj/item/grenade/c4 = 3,
|
||||
)
|
||||
back = /obj/item/deployable_turret_folded
|
||||
uniform = /obj/item/clothing/under/syndicate/camo
|
||||
belt = /obj/item/storage/belt/utility/full/powertools
|
||||
glasses = /obj/item/clothing/glasses/welding
|
||||
belt = /obj/item/storage/belt/utility/full/powertools/rcd
|
||||
glasses = /obj/item/clothing/glasses/hud/diagnostic/sunglasses
|
||||
r_pocket = /obj/item/rcd_ammo/large
|
||||
|
||||
/datum/outfit/centcom/ert/marine/engineer/post_equip(mob/living/carbon/human/equipper, visualsOnly = FALSE)
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
/obj/projectile/bullet/manned_turret
|
||||
damage = 20
|
||||
|
||||
/obj/projectile/bullet/manned_turret/hmg
|
||||
icon_state = "redtrac"
|
||||
|
||||
/obj/projectile/bullet/syndicate_turret
|
||||
damage = 20
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 71 KiB |
@@ -553,6 +553,7 @@
|
||||
#include "code\datums\components\customizable_reagent_holder.dm"
|
||||
#include "code\datums\components\deadchat_control.dm"
|
||||
#include "code\datums\components\dejavu.dm"
|
||||
#include "code\datums\components\deployable.dm"
|
||||
#include "code\datums\components\earprotection.dm"
|
||||
#include "code\datums\components\edit_complainer.dm"
|
||||
#include "code\datums\components\egg_layer.dm"
|
||||
@@ -1436,6 +1437,7 @@
|
||||
#include "code\game\objects\structures\barsigns.dm"
|
||||
#include "code\game\objects\structures\bedsheet_bin.dm"
|
||||
#include "code\game\objects\structures\chess.dm"
|
||||
#include "code\game\objects\structures\deployable_turret.dm"
|
||||
#include "code\game\objects\structures\destructible_structures.dm"
|
||||
#include "code\game\objects\structures\displaycase.dm"
|
||||
#include "code\game\objects\structures\divine.dm"
|
||||
@@ -1467,7 +1469,6 @@
|
||||
#include "code\game\objects\structures\life_candle.dm"
|
||||
#include "code\game\objects\structures\loom.dm"
|
||||
#include "code\game\objects\structures\maintenance.dm"
|
||||
#include "code\game\objects\structures\manned_turret.dm"
|
||||
#include "code\game\objects\structures\memorial.dm"
|
||||
#include "code\game\objects\structures\mineral_doors.dm"
|
||||
#include "code\game\objects\structures\mirror.dm"
|
||||
|
||||