From 980c5cdee71f8b6ef42c260406eb80d5b267e0f3 Mon Sep 17 00:00:00 2001 From: cacogen <25089914+cacogen@users.noreply.github.com> Date: Sat, 26 Mar 2022 14:56:28 +1300 Subject: [PATCH] Can secondary attack (right-click) and fire guns with TK (#65473) --- code/_onclick/telekinesis.dm | 87 ++++++++++++++++--- code/datums/components/pellet_cloud.dm | 4 +- .../modules/projectiles/ammunition/_firing.dm | 27 ++++-- .../projectiles/ammunition/energy/portal.dm | 2 +- code/modules/projectiles/gun.dm | 19 ++-- .../projectiles/guns/energy/beam_rifle.dm | 2 +- 6 files changed, 111 insertions(+), 30 deletions(-) diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index e9f7b00ea7a..7b6d12d8626 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -73,6 +73,14 @@ if(attack_self(user)) return COMPONENT_CANCEL_ATTACK_CHAIN +/atom/proc/attack_self_secondary_tk(mob/user) + return + + +/obj/item/attack_self_secondary_tk(mob/user) + if(attack_self_secondary(user)) + return COMPONENT_CANCEL_ATTACK_CHAIN + /* TK Grab Item (the workhorse of old TK) @@ -162,20 +170,75 @@ update_appearance() return - if(!isturf(target) && isitem(focus) && target.Adjacent(focus)) - apply_focus_overlay() + if(isitem(focus)) var/obj/item/I = focus - . = I.melee_attack_chain(tk_user, target, params) //isn't copying the attack chain fun. we should do it more often. - if(check_if_focusable(focus)) - focus.do_attack_animation(target, null, focus) - else - . = TRUE apply_focus_overlay() - //Only items can be thrown 10 tiles everything else only 1 tile - focus.throw_at(target, focus.tk_throw_range, 1,user) - var/turf/start_turf = get_turf(focus) - var/turf/end_turf = get_turf(target) - user.log_message("has thrown [focus] from [AREACOORD(start_turf)] towards [AREACOORD(end_turf)] using Telekinesis", LOG_ATTACK) + if(target.Adjacent(focus)) + . = I.melee_attack_chain(tk_user, target, params) //isn't copying the attack chain fun. we should do it more often. + if(check_if_focusable(focus)) + focus.do_attack_animation(target, null, focus) + else if(isgun(I)) //I've only tested this with guns, and it took some doing to make it work + . = I.afterattack(target, tk_user, 0, params) + + user.changeNext_move(CLICK_CD_MELEE) + update_appearance() + +/obj/item/tk_grab/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + + if(!target || !user) + return + + if(!focus) + focus_object(target) + return TRUE + + if(!check_if_focusable(focus)) + return + + if(target == focus) + if(target.attack_self_secondary_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN) + . = TRUE + update_appearance() + return + + if(isitem(focus)) + var/obj/item/I = focus + apply_focus_overlay() + if(target.Adjacent(focus)) + . = I.melee_attack_chain(tk_user, target, click_parameters) //isn't copying the attack chain fun. we should do it more often. + if(check_if_focusable(focus)) + focus.do_attack_animation(target, null, focus) + else if(isgun(I)) //I've only tested this with guns, and it took some doing to make it work + . = I.afterattack_secondary(target, tk_user, 0, click_parameters) + + user.changeNext_move(CLICK_CD_MELEE) + update_appearance() + +/obj/item/tk_grab/on_thrown(mob/living/carbon/user, atom/target) + if(!target || !user) + return + + if(!focus) + return + + if(!check_if_focusable(focus)) + return + + if(target == focus) + if(target.attack_self_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN) + return + update_appearance() + return + + apply_focus_overlay() + //Only items can be thrown 10 tiles everything else only 1 tile + focus.throw_at(target, focus.tk_throw_range, 1,user) + var/turf/start_turf = get_turf(focus) + var/turf/end_turf = get_turf(target) + user.log_message("has thrown [focus] from [AREACOORD(start_turf)] towards [AREACOORD(end_turf)] using Telekinesis", LOG_ATTACK) user.changeNext_move(CLICK_CD_MELEE) update_appearance() diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index c3d01128f5d..fdde1edbeca 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -125,10 +125,10 @@ shell.loaded_projectile.wound_bonus = original_wb shell.loaded_projectile.bare_wound_bonus = original_bwb pellets += shell.loaded_projectile - var/turf/current_loc = get_turf(user) + var/turf/current_loc = get_turf(fired_from) if (!istype(target_loc) || !istype(current_loc) || !(shell.loaded_projectile)) return - INVOKE_ASYNC(shell, /obj/item/ammo_casing.proc/throw_proj, target, target_loc, shooter, params, spread) + INVOKE_ASYNC(shell, /obj/item/ammo_casing.proc/throw_proj, target, target_loc, shooter, params, spread, fired_from) if(i != num_pellets) shell.newshot() diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm index a83a8d060a0..ddd533c30d2 100644 --- a/code/modules/projectiles/ammunition/_firing.dm +++ b/code/modules/projectiles/ammunition/_firing.dm @@ -8,7 +8,7 @@ spread = round((rand() - 0.5) * distro) else //Smart spread spread = round(1 - 0.5) * distro - if(!throw_proj(target, targloc, user, params, spread)) + if(!throw_proj(target, targloc, user, params, spread, fired_from)) return FALSE else if(isnull(loaded_projectile)) @@ -21,11 +21,19 @@ next_delay = round(next_delay * 0.5) user.changeNext_move(next_delay) - - user.newtonian_move(get_dir(target, user)) + if(!tk_firing(user, fired_from)) + user.newtonian_move(get_dir(target, user)) + else if(ismovable(fired_from)) + var/atom/movable/firer = fired_from + if(!firer.newtonian_move(get_dir(target, fired_from), instant = TRUE)) + var/throwtarget = get_step(fired_from, get_dir(target, fired_from)) + firer.safe_throw_at(throwtarget, 1, 2) update_appearance() return TRUE +/obj/item/ammo_casing/proc/tk_firing(mob/living/user, atom/fired_from) + return fired_from.loc != user ? TRUE : FALSE + /obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", atom/fired_from) if (!loaded_projectile) return @@ -44,19 +52,22 @@ loaded_projectile.damage *= G.projectile_damage_multiplier loaded_projectile.stamina *= G.projectile_damage_multiplier + if(tk_firing(user, fired_from)) + loaded_projectile.ignore_source_check = TRUE + if(reagents && loaded_projectile.reagents) reagents.trans_to(loaded_projectile, reagents.total_volume, transfered_by = user) //For chemical darts/bullets qdel(reagents) -/obj/item/ammo_casing/proc/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread) - var/turf/curloc = get_turf(user) +/obj/item/ammo_casing/proc/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread, atom/fired_from) + var/turf/curloc = get_turf(fired_from) if (!istype(targloc) || !istype(curloc) || !loaded_projectile) return FALSE var/firing_dir if(loaded_projectile.firer) - firing_dir = loaded_projectile.firer.dir - if(!loaded_projectile.suppressed && firing_effect_type) + firing_dir = get_dir(fired_from, target) + if(!loaded_projectile.suppressed && firing_effect_type && !tk_firing(user, fired_from)) new firing_effect_type(get_turf(src), firing_dir) var/direct_target @@ -65,7 +76,7 @@ direct_target = target if(!direct_target) var/modifiers = params2list(params) - loaded_projectile.preparePixelProjectile(target, user, modifiers, spread) + loaded_projectile.preparePixelProjectile(target, fired_from, modifiers, spread) var/obj/projectile/loaded_projectile_cache = loaded_projectile loaded_projectile = null loaded_projectile_cache.fire(null, direct_target) diff --git a/code/modules/projectiles/ammunition/energy/portal.dm b/code/modules/projectiles/ammunition/energy/portal.dm index 768ba4bf0b3..8bdd697f1bf 100644 --- a/code/modules/projectiles/ammunition/energy/portal.dm +++ b/code/modules/projectiles/ammunition/energy/portal.dm @@ -15,7 +15,7 @@ . = ..() gun = WEAKREF(wh) -/obj/item/ammo_casing/energy/wormhole/throw_proj() +/obj/item/ammo_casing/energy/wormhole/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread, atom/fired_from) . = ..() if(istype(loaded_projectile, /obj/projectile/beam/wormhole)) var/obj/projectile/beam/wormhole/WH = loaded_projectile diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 12cee35c52c..83210d8fbb1 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -164,21 +164,28 @@ /obj/item/gun/proc/can_shoot() return TRUE +/obj/item/gun/proc/tk_firing(mob/living/user) + return loc != user ? TRUE : FALSE + /obj/item/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj) - to_chat(user, span_danger("*click*")) + visible_message(span_warning("*click*"), vision_distance = COMBAT_MESSAGE_RANGE) playsound(src, dry_fire_sound, 30, TRUE) /obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = 0, atom/pbtarget = null, message = 1) - if(recoil) + if(recoil && !tk_firing(user)) shake_camera(user, recoil + 1, recoil) if(suppressed) - playsound(user, suppressed_sound, suppressed_volume, vary_fire_sound, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_distance = 0) + playsound(src, suppressed_sound, suppressed_volume, vary_fire_sound, ignore_walls = FALSE, extrarange = SILENCED_SOUND_EXTRARANGE, falloff_distance = 0) else - playsound(user, fire_sound, fire_sound_volume, vary_fire_sound) + playsound(src, fire_sound, fire_sound_volume, vary_fire_sound) if(message) - if(pointblank) + if(tk_firing(user)) + visible_message(span_danger("[src] fires itself[pointblank ? " point blank at [pbtarget]!" : "!"]"), \ + blind_message = span_hear("You hear a gunshot!"), \ + vision_distance = COMBAT_MESSAGE_RANGE) + else if(pointblank) user.visible_message(span_danger("[user] fires [src] point blank at [pbtarget]!"), \ span_danger("You fire [src] point blank at [pbtarget]!"), \ span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE, pbtarget) @@ -187,7 +194,7 @@ var/mob/PBT = pbtarget var/atom/throw_target = get_edge_target_turf(PBT, user.dir) PBT.throw_at(throw_target, pb_knockback, 2) - else + else if(!tk_firing(user)) user.visible_message(span_danger("[user] fires [src]!"), \ span_danger("You fire [src]!"), \ span_hear("You hear a gunshot!"), COMBAT_MESSAGE_RANGE) diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm index fb6cf679fc5..1942417a1f2 100644 --- a/code/modules/projectiles/guns/energy/beam_rifle.dm +++ b/code/modules/projectiles/guns/energy/beam_rifle.dm @@ -382,7 +382,7 @@ HS_BB.do_pierce = do_pierce HS_BB.gun = host -/obj/item/ammo_casing/energy/beam_rifle/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread) +/obj/item/ammo_casing/energy/beam_rifle/throw_proj(atom/target, turf/targloc, mob/living/user, params, spread, atom/fired_from) var/turf/curloc = get_turf(user) if(!istype(curloc) || !loaded_projectile) return FALSE