mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-18 18:46:24 +01:00
Merge pull request #7534 from VOREStation/aro-moverework
Rewrite client/Move() for smoother movement ingame
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -228,7 +228,7 @@ var/redspace_abduction_z
|
||||
fake_autosave(L, user)
|
||||
return
|
||||
|
||||
target.move_delay = 99999999
|
||||
target.setMoveCooldown(10 SECONDS)
|
||||
|
||||
to_chat(target, "<span class='notice' style='font: small-caps bold large monospace!important'>Autosaving your progress, please wait...</span>")
|
||||
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, "<span class='notice' style='font: small-caps bold large monospace!important'>Autosave complete!</span>")
|
||||
if(target.client)
|
||||
target.client.screen -= loader
|
||||
if(target.client)
|
||||
target.client.screen -= loader
|
||||
|
||||
@@ -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
|
||||
@@ -18,7 +18,6 @@
|
||||
//OTHER//
|
||||
/////////
|
||||
var/datum/preferences/prefs = null
|
||||
//var/move_delay = 1
|
||||
var/moving = null
|
||||
var/adminobs = null
|
||||
var/area = null
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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("<span class='warning'>[src] has thrown [item].</span>")
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -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("<span class='notice'>[U] [M.response_help] \the [M].</span>")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+181
-163
@@ -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, "<font color='blue'>You're restrained! You can't move!</font>")
|
||||
return 0
|
||||
else
|
||||
M.stop_pulling()
|
||||
|
||||
if(mob.pinned.len)
|
||||
to_chat(src, "<font color='blue'>You're pinned to a wall by [mob.pinned[1]]!</font>")
|
||||
// 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, "<font color='blue'>You're restrained! You can't move!</font>")
|
||||
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, "<font color='blue'>You're pinned to a wall by [my_mob.pinned[1]]!</font>")
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -327,7 +327,7 @@
|
||||
if(!istype(tasted))
|
||||
return
|
||||
|
||||
if(!canClick() || incapacitated(INCAPACITATION_ALL))
|
||||
if(!checkClickCooldown() || incapacitated(INCAPACITATION_ALL))
|
||||
return
|
||||
|
||||
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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("<span class='notice'>[user] [S.response_help] \the [S].</span>")
|
||||
user.setClickCooldown(user.get_attack_speed())
|
||||
|
||||
Reference in New Issue
Block a user