diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index c5c48dbbf2..f3ada6e48c 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -51,7 +51,7 @@ CtrlClickOn(A) return - if(control_disabled || !canClick()) + if(control_disabled || !checkClickCooldown()) return if(aiCamera.in_camera_mode) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index ea40e3dc0e..23269f5bab 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -38,10 +38,10 @@ * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed */ /mob/proc/ClickOn(var/atom/A, var/params) - if(world.time <= next_click) // Hard check, before anything else, to avoid crashing + if(!checkClickCooldown()) // Hard check, before anything else, to avoid crashing return - next_click = world.time + 1 + setClickCooldown(1) if(client && client.buildmode) build_click(src, client.buildmode, params, A) @@ -69,9 +69,6 @@ face_atom(A) // change direction to face what you clicked on - if(!canClick()) // in the year 2000... - return - if(istype(loc, /obj/mecha)) if(!locate(/turf) in list(A, A.loc)) // Prevents inventory from being drilled return @@ -156,12 +153,12 @@ return 1 /mob/proc/setClickCooldown(var/timeout) - next_move = max(world.time + timeout, next_move) + next_click = max(world.time + timeout, next_click) -/mob/proc/canClick() - if(config.no_click_cooldown || next_move <= world.time) - return 1 - return 0 +/mob/proc/checkClickCooldown() + if(next_click > world.time && !config.no_click_cooldown) + return FALSE + return TRUE // Default behavior: ignore double clicks, the second click that makes the doubleclick call already calls for a normal click /mob/proc/DblClickOn(var/atom/A, var/params) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index f8bce398a6..a9de2897e8 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -35,7 +35,7 @@ if(stat || lockdown || weakened || stunned || paralysis) return - if(!canClick()) + if(!checkClickCooldown()) return face_atom(A) // change direction to face what you clicked on diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index b5299cd77b..c123790b51 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -123,7 +123,7 @@ if(modifiers["shift"]) moved = 0 return 1 - if(usr.next_move >= world.time) // Is this needed ? + if(!usr.checkClickCooldown()) return owner.Trigger() return 1 diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 2c6408cf7f..e82d3ea5f6 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -54,7 +54,7 @@ /obj/screen/item_action/Click() if(!usr || !owner) return 1 - if(!usr.canClick()) + if(!usr.checkClickCooldown()) return if(usr.stat || usr.restrained() || usr.stunned || usr.lying) @@ -85,7 +85,7 @@ name = "storage" /obj/screen/storage/Click() - if(!usr.canClick()) + if(!usr.checkClickCooldown()) return 1 if(usr.stat || usr.paralysis || usr.stunned || usr.weakened) return 1 @@ -494,7 +494,7 @@ /obj/screen/inventory/Click() // At this point in client Click() code we have passed the 1/10 sec check and little else // We don't even know if it's a middle click - if(!usr.canClick()) + if(!usr.checkClickCooldown()) return 1 if(usr.stat || usr.paralysis || usr.stunned || usr.weakened) return 1 diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index a2d3f0c92b..88309b5074 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -31,7 +31,7 @@ if(client.buildmode) build_click(src, client.buildmode, params, A) return - if(!canClick()) return + if(!checkClickCooldown()) return setClickCooldown(4) // You are responsible for checking config.ghost_interaction when you override this function // Not all of them require checking, see below diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm index ed7a1c7e2f..3a70c8d36d 100644 --- a/code/_onclick/rig.dm +++ b/code/_onclick/rig.dm @@ -63,7 +63,7 @@ return loc == card /mob/living/proc/HardsuitClickOn(var/atom/A, var/alert_ai = 0) - if(!can_use_rig() || !canClick()) + if(!can_use_rig() || !checkClickCooldown()) return 0 var/obj/item/weapon/rig/rig = get_rig() if(istype(rig) && !rig.offline && rig.selected_module) diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 187b69e021..7308083ae6 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -59,22 +59,11 @@ var/damage = 0.0 var/range = 10.0 - -/obj/effect/list_container - name = "list container" - -/obj/effect/list_container/mobl - name = "mobl" - var/master = null - - var/list/container = list( ) - /obj/effect/projection name = "Projection" desc = "This looks like a projection of something." anchored = 1.0 - /obj/effect/shut_controller name = "shut controller" var/moving = null @@ -114,12 +103,5 @@ user.drop_item() src.throw_at(target, throw_range, throw_speed, user) -/obj/effect/stop - var/victim = null - icon_state = "empty" - name = "Geas" - desc = "You can't resist." - // name = "" - /obj/effect/spawner name = "object spawner" diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index b711274be6..4da0bc31b9 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,7 +1,8 @@ /atom/movable layer = OBJ_LAYER appearance_flags = TILE_BOUND|PIXEL_SCALE - var/last_move = null + glide_size = 8 + var/last_move = null //The direction the atom last moved var/anchored = 0 // var/elevation = 2 - not used anywhere var/moving_diagonally diff --git a/code/game/objects/items/weapons/implants/implantreagent_vr.dm b/code/game/objects/items/weapons/implants/implantreagent_vr.dm index ddaa6680c8..5642d1bfd6 100644 --- a/code/game/objects/items/weapons/implants/implantreagent_vr.dm +++ b/code/game/objects/items/weapons/implants/implantreagent_vr.dm @@ -70,7 +70,7 @@ do_reagent_implant(usr) /mob/living/carbon/human/proc/do_reagent_implant(var/mob/living/carbon/human/user = usr) - if(!isliving(user) || !user.canClick()) + if(!isliving(user) || !user.checkClickCooldown()) return if(user.incapacitated() || user.stat > CONSCIOUS) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 7c797fd72d..c74628a4ea 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -157,9 +157,7 @@ var/const/enterloopsanity = 100 if(ismob(A)) var/mob/M = A - if(!M.lastarea) - M.lastarea = get_area(M.loc) - if(M.lastarea.has_gravity == 0) + if(M.lastarea?.has_gravity == 0) inertial_drift(M) if(M.flying) //VORESTATION Edit Start. This overwrites the above is_space without touching it all that much. inertial_drift(M) diff --git a/code/modules/admin/verbs/smite.dm b/code/modules/admin/verbs/smite.dm index e8183e3665..1fd5120f55 100644 --- a/code/modules/admin/verbs/smite.dm +++ b/code/modules/admin/verbs/smite.dm @@ -56,18 +56,12 @@ return BSACooldown = 1 - spawn(50) - BSACooldown = 0 + VARSET_IN(global, BSACooldown, FALSE, 5 SECONDS) to_chat(target,"You've been hit by bluespace artillery!") log_and_message_admins("[key_name(target)] has been hit by Bluespace Artillery fired by [key_name(user ? user : usr)]") - var/obj/effect/stop/S - S = new /obj/effect/stop - S.victim = target - S.loc = target.loc - spawn(20) - qdel(S) + target.setMoveCooldown(2 SECONDS) var/turf/simulated/floor/T = get_turf(target) if(istype(T)) diff --git a/code/modules/admin/verbs/smite_vr.dm b/code/modules/admin/verbs/smite_vr.dm index fb52f18b50..cbf78c6f5a 100644 --- a/code/modules/admin/verbs/smite_vr.dm +++ b/code/modules/admin/verbs/smite_vr.dm @@ -228,7 +228,7 @@ var/redspace_abduction_z fake_autosave(L, user) return - target.move_delay = 99999999 + target.setMoveCooldown(10 SECONDS) to_chat(target, "Autosaving your progress, please wait...") target << 'sound/effects/ding.ogg' @@ -257,7 +257,6 @@ var/redspace_abduction_z spawn(10 SECONDS) if(target) - target.move_delay = 0 to_chat(target, "Autosave complete!") - if(target.client) - target.client.screen -= loader + if(target.client) + target.client.screen -= loader diff --git a/code/modules/ai/interfaces.dm b/code/modules/ai/interfaces.dm index 6cf085c52e..2755875df0 100644 --- a/code/modules/ai/interfaces.dm +++ b/code/modules/ai/interfaces.dm @@ -7,12 +7,12 @@ return FALSE /mob/living/simple_mob/IAttack(atom/A) - if(!canClick()) // Still on cooldown from a "click". + if(!checkClickCooldown()) // Still on cooldown from a "click". return ATTACK_ON_COOLDOWN return attack_target(A) // This will set click cooldown. /mob/living/carbon/human/IAttack(atom/A) - if(!canClick()) // Still on cooldown from a "click". + if(!checkClickCooldown()) // Still on cooldown from a "click". return FALSE return ClickOn(A) // Except this is an actual fake "click". @@ -20,7 +20,7 @@ return FALSE /mob/living/simple_mob/IRangedAttack(atom/A) - if(!canClick()) // Still on cooldown from a "click". + if(!checkClickCooldown()) // Still on cooldown from a "click". return ATTACK_ON_COOLDOWN return shoot_target(A) @@ -74,30 +74,27 @@ // Respects move cooldowns as if it had a client. // Also tries to avoid being superdumb with moving into certain tiles (unless that's desired). /mob/living/proc/IMove(turf/newloc, safety = TRUE) - if(check_move_cooldown()) -// if(!newdir) -// newdir = get_dir(get_turf(src), newloc) + if(!checkMoveCooldown()) + return MOVEMENT_ON_COOLDOWN - // Check to make sure moving to newloc won't actually kill us. e.g. we're a slime and trying to walk onto water. - if(istype(newloc)) - if(safety && !newloc.is_safe_to_enter(src)) - return MOVEMENT_FAILED - - // Move()ing to another tile successfully returns 32 because BYOND. Would rather deal with TRUE/FALSE-esque terms. - // Note that moving to the same tile will be 'successful'. - var/turf/old_T = get_turf(src) - - // An adjacency check to avoid mobs phasing diagonally past windows. - // This might be better in general movement code but I'm too scared to add it, and most things don't move diagonally anyways. - if(!old_T.Adjacent(newloc)) + // Check to make sure moving to newloc won't actually kill us. e.g. we're a slime and trying to walk onto water. + if(istype(newloc)) + if(safety && !newloc.is_safe_to_enter(src)) return MOVEMENT_FAILED - . = SelfMove(newloc) ? MOVEMENT_SUCCESSFUL : MOVEMENT_FAILED - if(. == MOVEMENT_SUCCESSFUL) - set_dir(get_dir(old_T, newloc)) - // Apply movement delay. - // Player movement has more factors but its all in the client and fixing that would be its own project. - setMoveCooldown(movement_delay()) - return + // Move()ing to another tile successfully returns 32 because BYOND. Would rather deal with TRUE/FALSE-esque terms. + // Note that moving to the same tile will be 'successful'. + var/turf/old_T = get_turf(src) - . = MOVEMENT_ON_COOLDOWN // To avoid superfast mobs that aren't meant to be superfast. Is actually -1. + // An adjacency check to avoid mobs phasing diagonally past windows. + // This might be better in general movement code but I'm too scared to add it, and most things don't move diagonally anyways. + if(!old_T.Adjacent(newloc)) + return MOVEMENT_FAILED + + . = SelfMove(newloc) ? MOVEMENT_SUCCESSFUL : MOVEMENT_FAILED + if(. == MOVEMENT_SUCCESSFUL) + set_dir(get_dir(old_T, newloc)) + // Apply movement delay. + // Player movement has more factors but its all in the client and fixing that would be its own project. + setMoveCooldown(movement_delay()) + return \ No newline at end of file diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index 527d9438fe..1d99f83b35 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -18,7 +18,6 @@ //OTHER// ///////// var/datum/preferences/prefs = null - //var/move_delay = 1 var/moving = null var/adminobs = null var/area = null diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index f830643e00..898a1fe826 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -996,14 +996,6 @@ if(wearer.transforming || !wearer.canmove) return - if(locate(/obj/effect/stop/, wearer.loc)) - for(var/obj/effect/stop/S in wearer.loc) - if(S.victim == wearer) - return - - if(!wearer.lastarea) - wearer.lastarea = get_area(wearer.loc) - if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.has_gravity == 0)) if(!wearer.Process_Spacemove(0)) return 0 diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm index 56a5ce2336..96b9ab36cb 100644 --- a/code/modules/media/mediamanager.dm +++ b/code/modules/media/mediamanager.dm @@ -40,7 +40,7 @@ if(!istype(M)) return ..() // Optimization, no need to call update_music() if both are null (or same instance, strange as that would be) - if(M.lastarea && M.lastarea.media_source == src.media_source) + if(M.lastarea?.media_source == src.media_source) return ..() if(M.client && M.client.media && !M.client.media.forced) M.update_music() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 381133a217..cb745aea2e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1398,7 +1398,7 @@ set desc = "Pop a joint back into place. Extremely painful." set src in view(1) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return usr.setClickCooldown(20) diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm index b78d7caf78..f55935ac9e 100644 --- a/code/modules/mob/living/carbon/human/species/station/alraune.dm +++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm @@ -417,7 +417,7 @@ set src in view(1) //do_reagent_implant(usr) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return if(usr.incapacitated() || usr.stat > CONSCIOUS) diff --git a/code/modules/mob/living/inventory.dm b/code/modules/mob/living/inventory.dm index 22db034374..24f36f8ac7 100644 --- a/code/modules/mob/living/inventory.dm +++ b/code/modules/mob/living/inventory.dm @@ -127,39 +127,27 @@ onclose(user, "mob[name]") return -/mob/living/ret_grab(obj/effect/list_container/mobl/L as obj, flag) - if ((!( istype(l_hand, /obj/item/weapon/grab) ) && !( istype(r_hand, /obj/item/weapon/grab) ))) - if (!( L )) - return null - else - return L.container - else - if (!( L )) - L = new /obj/effect/list_container/mobl( null ) - L.container += src - L.master = src - if (istype(l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = l_hand - if (!( L.container.Find(G.affecting) )) - L.container += G.affecting - if (G.affecting) - G.affecting.ret_grab(L, 1) - if (istype(r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = r_hand - if (!( L.container.Find(G.affecting) )) - L.container += G.affecting - if (G.affecting) - G.affecting.ret_grab(L, 1) - if (!( flag )) - if (L.master == src) - var/list/temp = list( ) - temp += L.container - //L = null - qdel(L) - return temp - else - return L.container - return +/mob/living/ret_grab(var/list/L, var/mobchain_limit = 5) + // We're the first! + if(!L) + L = list() + + // Lefty grab! + if (istype(l_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = l_hand + L |= G.affecting + if(mobchain_limit-- > 0) + G.affecting?.ret_grab(L, mobchain_limit) // Recurse! They can update the list. It's the same instance as ours. + + // Righty grab! + if (istype(r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = r_hand + L |= G.affecting + if(mobchain_limit-- > 0) + G.affecting?.ret_grab(L, mobchain_limit) // Same as lefty! + + // On all but the one not called by us, this will just be ignored. Oh well! + return L /mob/living/mode() set name = "Activate Held Object" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 48facacd98..41b52d37ea 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -895,7 +895,7 @@ default behaviour is: set name = "Resist" set category = "IC" - if(!incapacitated(INCAPACITATION_KNOCKOUT) && canClick()) + if(!incapacitated(INCAPACITATION_KNOCKOUT) && checkClickCooldown()) setClickCooldown(20) resist_grab() if(!weakened) @@ -1299,9 +1299,7 @@ default behaviour is: //actually throw it! src.visible_message("[src] has thrown [item].") - if(!src.lastarea) - src.lastarea = get_area(src.loc) - if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0)) + if((istype(src.loc, /turf/space)) || (src.lastarea?.has_gravity == 0)) src.inertia_dir = get_dir(target, src) step(src, inertia_dir) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm index 3c74e3784f..26c15f9c17 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm @@ -22,7 +22,7 @@ //No longer in use, as mice create a holder/micro object instead /obj/item/weapon/holder/mouse/attack_self(var/mob/U) for(var/mob/living/simple_mob/M in src.contents) - if((I_HELP) && U.canClick()) //a little snowflakey, but makes it use the same cooldown as interacting with non-inventory objects + if((I_HELP) && U.checkClickCooldown()) //a little snowflakey, but makes it use the same cooldown as interacting with non-inventory objects U.setClickCooldown(U.get_attack_speed()) //if there's a cleaner way in baycode, I'll change this U.visible_message("[U] [M.response_help] \the [M].") diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 91292a4a4a..095dd63e74 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -45,6 +45,7 @@ dead_mob_list += src else living_mob_list += src + lastarea = get_area(src) hook_vr("mob_new",list(src)) //VOREStation Code update_transform() // Some mobs may start bigger or smaller than normal. return ..() @@ -744,12 +745,12 @@ /mob/proc/facedir(var/ndir) - if(!canface() || (client && (client.moving || (world.time < move_delay)))) + if(!canface() || (client && (client.moving || !checkMoveCooldown()))) return 0 set_dir(ndir) if(buckled && buckled.buckle_movable) buckled.set_dir(ndir) - move_delay += movement_delay() + setMoveCooldown(movement_delay()) return 1 @@ -912,7 +913,7 @@ mob/proc/yank_out_object() set desc = "Remove an embedded item at the cost of bleeding and pain." set src in view(1) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return usr.setClickCooldown(20) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 27029f7e08..9091e338ab 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -7,8 +7,7 @@ var/datum/mind/mind var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak - var/move_delay = null // For movement speed delays. - var/next_move = null // For click delay, despite the misleading name. + var/next_move = null // world.time when mob is next allowed to self-move. //Not in use yet var/obj/effect/organstructure/organStructure = null diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 1505516631..0946990243 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -239,7 +239,7 @@ return if(state == GRAB_UPGRADING) return - if(!assailant.canClick()) + if(!assailant.checkClickCooldown()) return if(world.time < (last_action + UPGRADE_COOLDOWN)) return diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index d2fe2ecbd9..1100bd0385 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -1,8 +1,8 @@ /mob/proc/setMoveCooldown(var/timeout) - move_delay = max(world.time + timeout, move_delay) + next_move = max(world.time + timeout, next_move) -/mob/proc/check_move_cooldown() - if(world.time < src.move_delay) +/mob/proc/checkMoveCooldown() + if(world.time < next_move) return FALSE // Need to wait more. return TRUE @@ -108,206 +108,224 @@ mob.control_object.forceMove(get_step(mob.control_object,direct)) return - +// NB: This is called for 'self movement', not for being pulled or things like that, which COULD be the case for /mob/Move +// But to be honest, A LOT OF THIS CODE should be in /mob/Move /client/Move(n, direct) - //if(!mob) // Clients cannot have a null mob, as enforced by byond - // return // Moved here to avoid nullrefs below + // Prevents a double-datum lookup each time this is referenced + // May seem dumb, but it's faster to look up a var on my_mob than dereferencing mob on client, then dereferencing the var on that mob + // Having it in a var here means it's more available to look up things on. It won't speed up that second dereference, though. + var/mob/my_mob = mob - if(mob.control_object) Move_object(direct) + // Nothing to do in nullspace + if(!my_mob.loc) + return - if(mob.incorporeal_move && isobserver(mob)) + // Used many times below, faster reference. + var/atom/loc = my_mob.loc + + // We're controlling an object which is SOMEHOW DIFFERENT FROM AN EYE?? + if(my_mob.control_object) + Move_object(direct) + + // Ghosty mob movement + if(my_mob.incorporeal_move && isobserver(my_mob)) Process_Incorpmove(direct) return - if(moving) return 0 + // We're in the middle of another move we've already decided to do + if(moving) + return 0 - if(!mob.check_move_cooldown()) + // We're still cooling down from the last move + if(!my_mob.checkMoveCooldown()) return - if(locate(/obj/effect/stop/, mob.loc)) - for(var/obj/effect/stop/S in mob.loc) - if(S.victim == mob) - return - - if(mob.stat==DEAD && isliving(mob) && !mob.forbid_seeing_deadchat) - mob.ghostize() + // If dead and we try to move in our mob, it leaves our body + if(my_mob.stat == DEAD && isliving(my_mob) && !my_mob.forbid_seeing_deadchat) + my_mob.ghostize() return - // handle possible Eye movement - if(mob.eyeobj) - return mob.EyeMove(n,direct) + // If we have an eyeobj, it moves instead + if(my_mob.eyeobj) + return my_mob.EyeMove(n,direct) - if(mob.transforming) return//This is sota the goto stop mobs from moving var + // This is sota the goto stop mobs from moving var (for some reason) + if(my_mob.transforming) + return - if(isliving(mob)) - var/mob/living/L = mob + if(isliving(my_mob)) + var/mob/living/L = my_mob if(L.incorporeal_move)//Move though walls Process_Incorpmove(direct) return - if(mob.client) - if(mob.client.view != world.view) // If mob moves while zoomed in with device, unzoom them. - for(var/obj/item/item in mob.contents) - if(item.zoom) - item.zoom() - break - /* - if(locate(/obj/item/weapon/gun/energy/sniperrifle, mob.contents)) // If mob moves while zoomed in with sniper rifle, unzoom them. - var/obj/item/weapon/gun/energy/sniperrifle/s = locate() in mob - if(s.zoom) - s.zoom() - if(locate(/obj/item/device/binoculars, mob.contents)) // If mob moves while zoomed in with binoculars, unzoom them. - var/obj/item/device/binoculars/b = locate() in mob - if(b.zoom) - b.zoom() - */ + /* TODO observer unzoom + if(view != world.view) // If mob moves while zoomed in with device, unzoom them. + for(var/obj/item/item in mob.contents) + if(item.zoom) + item.zoom() + break + */ - if(Process_Grab()) return - - if(!mob.canmove) + if(Process_Grab()) return - //Relaymove could handle it - if(mob.machine) - var/result = mob.machine.relaymove(mob, direct) + // Can't move + if(!my_mob.canmove) + return + + // Relaymove could handle it + if(my_mob.machine) + var/result = my_mob.machine.relaymove(my_mob, direct) if(result) return result - if(!mob.lastarea) - mob.lastarea = get_area(mob.loc) - - if((istype(mob.loc, /turf/space)) || (mob.lastarea.has_gravity == 0)) - if(!mob.Process_Spacemove(0)) return 0 - - if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved - var/atom/O = mob.loc - return O.relaymove(mob, direct) - - if(isturf(mob.loc)) - - if(mob.restrained())//Why being pulled while cuffed prevents you from moving - for(var/mob/M in range(mob, 1)) - if(M.pulling == mob) - if(!M.restrained() && M.stat == 0 && M.canmove && mob.Adjacent(M)) - to_chat(src, "You're restrained! You can't move!") - return 0 - else - M.stop_pulling() - - if(mob.pinned.len) - to_chat(src, "You're pinned to a wall by [mob.pinned[1]]!") + // Can't control ourselves when drifting + if(isspace(loc) || my_mob.lastarea?.has_gravity == 0) + if(!my_mob.Process_Spacemove(0)) return 0 - mob.move_delay = world.time//set move delay + // Inside an object, tell it we moved + if(isobj(loc) || ismob(loc)) + return loc.relaymove(my_mob, direct) - switch(mob.m_intent) - if("run") - if(mob.drowsyness > 0) - mob.move_delay += 6 - mob.move_delay += config.run_speed - if("walk") - mob.move_delay += config.walk_speed - mob.move_delay += mob.movement_delay(n, direct) + // Can't move unless you're in the world somewhere + if(!isturf(loc)) + return - if(istype(mob.buckled, /obj/vehicle) || istype(mob.buckled, /mob)) //VOREStation Edit: taur riding. I think. - //manually set move_delay for vehicles so we don't inherit any mob movement penalties - //specific vehicle move delays are set in code\modules\vehicles\vehicle.dm - mob.move_delay = world.time - //drunk driving - if(mob.confused && prob(20)) //vehicles tend to keep moving in the same direction - direct = turn(direct, pick(90, -90)) - if(istype(mob.buckled, /mob)) //VOREStation Edit to prevent mob riding speed exploit. - var/mob/M = mob.buckled - if(M.move_delay > mob.move_delay - 10) - return - return mob.buckled.relaymove(mob,direct) - - if(mob.pulledby || mob.buckled) // Wheelchair driving! - if(istype(mob.loc, /turf/space)) - return // No wheelchair driving in space - if(istype(mob.pulledby, /obj/structure/bed/chair/wheelchair)) - return mob.pulledby.relaymove(mob, direct) - else if(istype(mob.buckled, /obj/structure/bed/chair/wheelchair)) - if(ishuman(mob)) - var/mob/living/carbon/human/driver = mob - var/obj/item/organ/external/l_hand = driver.get_organ("l_hand") - var/obj/item/organ/external/r_hand = driver.get_organ("r_hand") - if((!l_hand || l_hand.is_stump()) && (!r_hand || r_hand.is_stump())) - return // No hands to drive your chair? Tough luck! - //drunk wheelchair driving - else if(mob.confused) - switch(mob.m_intent) - if("run") - if(prob(50)) direct = turn(direct, pick(90, -90)) - if("walk") - if(prob(25)) direct = turn(direct, pick(90, -90)) - mob.move_delay += 2 - return mob.buckled.relaymove(mob,direct) - - //We are now going to move - moving = 1 - //Something with pulling things - if(locate(/obj/item/weapon/grab, mob)) - mob.move_delay = max(mob.move_delay, world.time + 7) - var/list/L = mob.ret_grab() - if(istype(L, /list)) - if(L.len == 2) - L -= mob - var/mob/M = L[1] - if(M) - if ((get_dist(mob, M) <= 1 || M.loc == mob.loc)) - var/turf/T = mob.loc - . = ..() - if (isturf(M.loc)) - var/diag = get_dir(mob, M) - if ((diag - 1) & diag) - else - diag = null - if ((get_dist(mob, M) > 1 || diag)) - step(M, get_dir(M.loc, T)) + // Why being pulled while cuffed prevents you from moving + if(my_mob.restrained()) + for(var/mob/M in range(my_mob, 1)) + if(M.pulling == my_mob) + if(!M.restrained() && M.stat == 0 && M.canmove && my_mob.Adjacent(M)) + to_chat(src, "You're restrained! You can't move!") + return 0 else - for(var/mob/M in L) - M.other_mobs = 1 - if(mob != M) - M.animate_movement = 3 - for(var/mob/M in L) - spawn( 0 ) - step(M, direct) - return - spawn( 1 ) - M.other_mobs = null - M.animate_movement = 2 - return + M.stop_pulling() - else - if(mob.confused) - switch(mob.m_intent) + if(my_mob.pinned.len) + to_chat(src, "You're pinned to a wall by [my_mob.pinned[1]]!") + return 0 + + if(istype(my_mob.buckled, /obj/vehicle) || ismob(my_mob.buckled)) + //manually set move_delay for vehicles so we don't inherit any mob movement penalties + //specific vehicle move delays are set in code\modules\vehicles\vehicle.dm + my_mob.next_move = world.time + //drunk driving + if(my_mob.confused && prob(20)) //vehicles tend to keep moving in the same direction + direct = turn(direct, pick(90, -90)) + if(ismob(my_mob.buckled)) + var/mob/M = my_mob.buckled + if(M.next_move > my_mob.next_move) // Don't let piggyback riders move their mob IN ADDITION TO the mob moving + return + return my_mob.buckled.relaymove(my_mob,direct) + + if(my_mob.pulledby || my_mob.buckled) // Wheelchair driving! + if(isspace(loc)) + return // No wheelchair driving in space + if(istype(my_mob.pulledby, /obj/structure/bed/chair/wheelchair)) + return my_mob.pulledby.relaymove(my_mob, direct) + else if(istype(my_mob.buckled, /obj/structure/bed/chair/wheelchair)) + if(ishuman(my_mob)) + var/mob/living/carbon/human/driver = my_mob + var/obj/item/organ/external/l_hand = driver.get_organ("l_hand") + var/obj/item/organ/external/r_hand = driver.get_organ("r_hand") + if((!l_hand || l_hand.is_stump()) && (!r_hand || r_hand.is_stump())) + return // No hands to drive your chair? Tough luck! + //drunk wheelchair driving + else if(my_mob.confused) + switch(my_mob.m_intent) if("run") - if(prob(75)) + if(prob(50)) direct = turn(direct, pick(90, -90)) - n = get_step(mob, direct) if("walk") if(prob(25)) direct = turn(direct, pick(90, -90)) - n = get_step(mob, direct) - . = mob.SelfMove(n, direct) + my_mob.setMoveCooldown(2) + return my_mob.buckled.relaymove(my_mob,direct) - for (var/obj/item/weapon/grab/G in mob) - if (G.state == GRAB_NECK) - mob.set_dir(reverse_dir[direct]) - G.adjust_position() - for (var/obj/item/weapon/grab/G in mob.grabbed_by) - G.adjust_position() + // We are now going to move + moving = 1 + var/total_delay = 0 + var/pre_move_loc = loc - moving = 0 + // Start tally'ing when we can next move + // Grabs slow you down + if(locate(/obj/item/weapon/grab) in my_mob) + total_delay += 7 + + // Movespeed delay based on movement mode + switch(my_mob.m_intent) + if("run") + if(my_mob.drowsyness > 0) + total_delay += 6 + total_delay += config.run_speed + if("walk") + total_delay += config.walk_speed + + // A billion other things can slow you down, ask the mob + total_delay += my_mob.movement_delay(n, direct) - return . + // Confused direction randomization + if(my_mob.confused) + switch(my_mob.m_intent) + if("run") + if(prob(75)) + direct = turn(direct, pick(90, -90)) + n = get_step(my_mob, direct) + if("walk") + if(prob(25)) + direct = turn(direct, pick(90, -90)) + n = get_step(my_mob, direct) + + total_delay = TICKS2DS(-round(-(DS2TICKS(total_delay)))) //Rounded to the next tick in equivalent ds + var/glide_size = WORLD_ICON_SIZE/DS2TICKS(total_delay) //Down to whatever decimal + my_mob.setMoveCooldown(max(total_delay, 1)) + . = my_mob.SelfMove(n, direct, glide_size) - return + // If we have a grab + var/list/grablist = my_mob.ret_grab() + if(grablist.len) + grablist -= my_mob // Just in case we're in a circular grab chain + + // It's just us and another person + if(grablist.len == 1) + var/mob/M = grablist[1] + if(!my_mob.Adjacent(M)) //Oh no, we moved away + M.glide_size = glide_size + step(M, get_dir(M, pre_move_loc)) //Have them step towards where we were + + // It's a grab chain + else + for(var/mob/M in grablist) + my_mob.other_mobs = 1 + M.other_mobs = 1 //Has something to do with people being able or unable to pass a chain of mobs + M.animate_movement = 3 + + //Ugly! + spawn(0) //Step + M.glide_size = glide_size + step(M, direct) + spawn(1) //Unstep + M.other_mobs = null + M.animate_movement = 2 + spawn(1) //Unset + my_mob.other_mobs = null -/mob/proc/SelfMove(turf/n, direct) + // Update all the grabs! + for (var/obj/item/weapon/grab/G in my_mob) + if (G.state == GRAB_NECK) + mob.set_dir(reverse_dir[direct]) + G.adjust_position() + for (var/obj/item/weapon/grab/G in my_mob.grabbed_by) + G.adjust_position() + + // We're not in the middle of a move anymore + moving = 0 + +/mob/proc/SelfMove(turf/n, direct, glide_size = 8) + src.glide_size = glide_size return Move(n, direct) - ///Process_Incorpmove ///Called by client/Move() ///Allows mobs to run though walls diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index e98522ac00..314186936b 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -511,8 +511,6 @@ if(!new_character) new_character = new(T) - new_character.lastarea = get_area(T) - if(ticker.random_players) new_character.gender = pick(MALE, FEMALE) client.prefs.real_name = random_name(new_character.gender) diff --git a/code/modules/projectiles/targeting/targeting_triggers.dm b/code/modules/projectiles/targeting/targeting_triggers.dm index 3563727fc1..1b8f3fcadd 100644 --- a/code/modules/projectiles/targeting/targeting_triggers.dm +++ b/code/modules/projectiles/targeting/targeting_triggers.dm @@ -17,7 +17,7 @@ return if(perm && (target_permissions & perm)) return - if(!owner.canClick()) + if(!owner.checkClickCooldown()) return owner.setClickCooldown(5) // Spam prevention, essentially. if(owner.a_intent == I_HELP && owner.is_preference_enabled(/datum/client_preference/safefiring)) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 15fde8b613..e73eff48f3 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -327,7 +327,7 @@ if(!istype(tasted)) return - if(!canClick() || incapacitated(INCAPACITATION_ALL)) + if(!checkClickCooldown() || incapacitated(INCAPACITATION_ALL)) return setClickCooldown(DEFAULT_ATTACK_COOLDOWN) diff --git a/code/modules/vore/fluffstuff/custom_items_vr.dm b/code/modules/vore/fluffstuff/custom_items_vr.dm index 0f8e6d3b5d..e978bcf366 100644 --- a/code/modules/vore/fluffstuff/custom_items_vr.dm +++ b/code/modules/vore/fluffstuff/custom_items_vr.dm @@ -891,7 +891,7 @@ set src in view(1) //do_reagent_implant(usr) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return if(usr.incapacitated() || usr.stat > CONSCIOUS) @@ -960,7 +960,7 @@ set src in view(1) //do_reagent_implant(usr) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return if(usr.incapacitated() || usr.stat > CONSCIOUS) @@ -1029,7 +1029,7 @@ set src in view(1) //do_reagent_implant(usr) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return if(usr.incapacitated() || usr.stat > CONSCIOUS) @@ -1114,7 +1114,7 @@ set src in view(1) //do_reagent_implant(usr) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return if(usr.incapacitated() || usr.stat > CONSCIOUS) @@ -1474,7 +1474,7 @@ set src in view(1) //do_reagent_implant(usr) - if(!isliving(usr) || !usr.canClick()) + if(!isliving(usr) || !usr.checkClickCooldown()) return if(usr.incapacitated() || usr.stat > CONSCIOUS) diff --git a/code/modules/vore/resizing/holder_micro_vr.dm b/code/modules/vore/resizing/holder_micro_vr.dm index 3a4b291940..aa22fdd55b 100644 --- a/code/modules/vore/resizing/holder_micro_vr.dm +++ b/code/modules/vore/resizing/holder_micro_vr.dm @@ -26,12 +26,12 @@ /obj/item/weapon/holder/micro/attack_self(mob/living/carbon/user) //reworked so it works w/ nonhumans for(var/L in contents) - if(ishuman(L) && user.canClick()) // These canClicks() are repeated here to make sure users can't avoid the click delay + if(ishuman(L) && user.checkClickCooldown()) // These canClicks() are repeated here to make sure users can't avoid the click delay var/mob/living/carbon/human/H = L H.help_shake_act(user) user.setClickCooldown(user.get_attack_speed()) //uses the same cooldown as regular attack_hand return - if(isanimal(L) && user.canClick()) + if(isanimal(L) && user.checkClickCooldown()) var/mob/living/simple_mob/S = L user.visible_message("[user] [S.response_help] \the [S].") user.setClickCooldown(user.get_attack_speed())