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())