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'