diff --git a/code/_hooks/events.dm b/code/_hooks/events.dm
index b565c5157a4a..fdd597c41f60 100644
--- a/code/_hooks/events.dm
+++ b/code/_hooks/events.dm
@@ -26,6 +26,11 @@
// atom/movable/mover: the movable itself.
/event/moved
+// Called whenever an /atom/movable relay-moves.
+// Arguments:
+// atom/movable/mover: the movable itself.
+/event/relaymoved
+
// Called right before an /atom/movable attempts to move or change dir.
/event/before_move
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 726282d220a7..a0c6698e7844 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -508,7 +508,7 @@ its easier to just keep the beam vertical.
bug.removed(usr)
/atom/proc/relaymove()
- return
+ INVOKE_EVENT(src, /event/relaymoved, "mover" = src)
// Try to override a mob's eastface(), westface() etc. (CTRL+RIGHTARROW, CTRL+LEFTARROW). Return 1 if successful, which blocks the mob's own eastface() etc.
// Called first on the mob's loc (turf, locker, mech), then on whatever the mob is buckled to, if anything.
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 4124d52ce8b8..eb79c17b7cda 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -351,6 +351,7 @@
//////////////////////////////////
/obj/mecha/relaymove(mob/user,direction)
+ ..()
if(user != src.occupant) //While not "realistic", this piece is player friendly.
user.forceMove(get_turf(src))
to_chat(user, "You climb out from [src]")
diff --git a/code/game/objects/structures/vehicles/vehicle.dm b/code/game/objects/structures/vehicles/vehicle.dm
index 9c27110e3f77..49ce75264813 100644
--- a/code/game/objects/structures/vehicles/vehicle.dm
+++ b/code/game/objects/structures/vehicles/vehicle.dm
@@ -184,6 +184,7 @@
/obj/structure/bed/chair/vehicle/relaymove(var/mob/living/user, direction)
+ ..()
if(user.incapacitated())
unlock_atom(user)
return
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index ed50cb5a1a33..de0b597521c9 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -351,7 +351,6 @@
var/old_dir = mob.dir
mob.delayNextMove(move_delay)
- mob.last_move_intent = world.time + 10
mob.set_glide_size(DELAY2GLIDESIZE(move_delay)) //Since we're moving OUT OF OUR OWN VOLITION AND BY OURSELVES we can update our glide_size here!
INVOKE_EVENT(mob, /event/before_move)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 2479c5f97ee6..4ae0bbfa87af 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -54,7 +54,6 @@
var/tmp/lock_time = -100
var/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.
var/firerate = 1 // 0 for one bullet after tarrget moves and aim is lowered,
//1 for keep shooting until aim is lowered
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index fce54773f36b..fcd6f4f066f9 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -773,9 +773,11 @@ var/list/impact_master = list()
return //cannot shoot yourself
if(istype(A, /obj/item/projectile))
return
- if(istype(A, /mob/living))
- result = 2 //We hit someone, return 1!
- return
+ if(ismovable(A))
+ var/atom/movable/AM = A
+ if(isliving(AM) || (locate(/mob/living) in AM) || (locate(/mob/living) in AM.locked_atoms))
+ result = 2 //We hit someone, return 1!
+ return
result = 1
return
diff --git a/code/modules/projectiles/targeting.dm b/code/modules/projectiles/targeting.dm
index 2e97f1118a7a..cf6e9fdceaef 100644
--- a/code/modules/projectiles/targeting.dm
+++ b/code/modules/projectiles/targeting.dm
@@ -76,21 +76,35 @@
M.Targeted(src)
//HE MOVED, SHOOT HIM!
-/obj/item/weapon/gun/proc/TargetActed(var/mob/living/T)
- var/mob/living/M = loc
- if(M == T)
+/obj/item/weapon/gun/proc/TargetMoved(mob/living/mover)
+ TargetActed(mover) //alias just so events work
+
+/obj/item/weapon/gun/proc/TargetActed(mob/living/user,modifiers,atom/target)
+ if(world.time <= lock_time)
return
- if(!istype(M))
+ if(target && (isturf(target) || istype(target,/obj/abstract/screen))) // these are okay to click
return
- if(src != M.get_active_hand())
+ lock_time = world.time + 15
+ //if(last_moved_mob == user) //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.
+ //lock_time = world.time + 15 //just look at the logic of this... it did nothing!!! uncomment if you want this to work again too. be sure to add the variable back.
+ var/mob/living/M = loc
+ if(M == user || !istype(M))
+ return
+ if(!M.client || src != M.get_active_hand())
stop_aim()
return
- M.last_move_intent = world.time
+ if(M.client.target_can_click && target) // this var only gets filled in from the click event calls, so that's a way of knowing
+ return
+ if(M.client.target_can_move)
+ if(!M.client.target_can_run && !user.locked_to && user.m_intent != "run") // if the user is relaymoving i'm pretty sure that's NOT walking
+ return
+ else if(!target)
+ return
if(canbe_fired())
- var/firing_check = can_hit(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.
+ var/firing_check = can_hit(user,M) //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)
+ Fire(user,M, reflex = 1)
else if(!told_cant_shoot)
to_chat(M, "They can't be hit from here!")
told_cant_shoot = 1
@@ -99,10 +113,10 @@
else
click_empty(M)
- usr.dir = get_cardinal_dir(src, T)
+ M.dir = get_cardinal_dir(src, user)
if (!firerate) // If firerate is set to lower aim after one shot, untarget the target
- T.NotTargeted(src)
+ user.NotTargeted(src)
/proc/GunTrace(X1,Y1,X2,Y2,Z=1,exc_obj,PX1=16,PY1=16,PX2=16,PY2=16)
// to_chat(bluh, "Tracin' [X1],[Y1] to [X2],[Y2] on floor [Z].")
@@ -153,9 +167,6 @@
//Targeting management procs
/mob
var/list/targeted_by
- var/target_time = -100
- var/last_move_intent = -100
- var/last_target_click = -5
var/target_locked = null
/mob/living/proc/Targeted(var/obj/item/weapon/gun/I) //Self explanitory.
@@ -176,10 +187,6 @@
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).
- to_chat(src, "((Your character is being targeted. They have 2 seconds to stop any click or move actions. While targeted, they may \
- drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map objects (floors and walls are fine), their items \
- (other than a weapon to de-target), or moving will result in being fired upon. The aggressor may also fire manually, \
- so try not to get on their bad side.\black ))")
if(targeted_by.len == 1)
spawn(0)
@@ -199,34 +206,37 @@
else
I.lower_aim()
return
- if(m_intent == "run" && T.client.target_can_move == 1 && T.client.target_can_run == 0 && (ishuman(T)))
- to_chat(src, "Your captive is allowing you to walk. Make sure to change your move intent to walk before trying to move, or you will be fired upon.")//Self explanitory.
-
+ var/msg = ""
+ if(!T.client.target_can_click)
+ msg += "While targeted, they may drag and drop items in or into the map, speak, and click on interface buttons. \
+ Clicking on the map objects (floors and walls are fine), their items (other than a weapon to de-target) will result in being fired upon.\n"
+ if(!T.client.target_can_move)
+ msg += "Moving will result in being fired upon.\n"
+ else if(m_intent == "run" && !T.client.target_can_run && (ishuman(T))) //Self explanitory.
+ msg += "Your captive is allowing you to walk. \
+ Make sure to change your move intent to walk before trying to move, or you will be fired upon.\n"
+ to_chat(src, "Your character is being targeted. They have 2 seconds to stop any of the following actions: \n \
+ [msg]\n \
+ The aggressor may also fire manually, so try not to get on their bad side.")
+
//set_m_intent("walk") -there's a real fucked up exploit behind this, so it's been removed. Needs testing. -Angelite-
-
- //Processing the aiming. Should be probably in separate object with process() but lasy.
- while(targeted_by && T.client)
- if((last_move_intent > I.lock_time + 10) && !T.client.target_can_move) //If target moved when not allowed to
- 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)
+
+ if(!T.client.target_can_move || !T.client.target_can_run)
+ register_event(/event/moved, I, nameof(I::TargetMoved()))
+ register_event(/event/relaymoved, I, nameof(I::TargetMoved()))
+ if(!T.client.target_can_click)
+ register_event(/event/clickon, I, nameof(I::TargetActed()))
+ register_event(/event/logout, T, nameof(src::TargeterLogout()))
+
+/mob/living/proc/TargeterLogout(mob/living/user)
+ for(var/obj/item/weapon/gun/G in user)
+ NotTargeted(G)
+ unregister_event(/event/logout, user, nameof(src::TargeterLogout()))
/mob/living/proc/NotTargeted(var/obj/item/weapon/gun/I)
+ unregister_event(/event/moved, I, nameof(I::TargetMoved()))
+ unregister_event(/event/relaymoved, I, nameof(I::TargetMoved()))
+ unregister_event(/event/clickon, I, nameof(I::TargetActed()))
if(!I.silenced)
for(var/mob/living/M in viewers(src))
M << 'sound/weapons/TargetOff.ogg'