Files
Aurora.3/code/modules/mob/mob_movement.dm
skull132 9b094ad0eb Merge branch 'upstream/development' into development
# Conflicts:
#	code/_helpers/time.dm
#	code/game/objects/items/devices/floor_painter.dm
#	code/game/objects/items/stacks/medical.dm
#	code/global.dm
#	code/modules/cargo/randomstock.dm
#	code/modules/mob/living/carbon/human/human_defense.dm
#	code/modules/mob/living/simple_animal/simple_animal.dm
#	code/modules/mob/mob_movement.dm
#	code/modules/paperwork/faxmachine.dm
2016-12-18 01:06:45 +02:00

529 lines
14 KiB
Plaintext

/mob/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
if(ismob(mover))
var/mob/moving_mob = mover
if ((other_mobs && moving_mob.other_mobs))
return 1
return (!mover.density || !density || lying)
else
return (!mover.density || !density || lying)
return
/mob/proc/setMoveCooldown(var/timeout)
if(client)
client.move_delay = max(world.time + timeout, client.move_delay)
/client/North()
..()
/client/South()
..()
/client/West()
..()
/client/East()
..()
/client/proc/client_dir(input, direction=-1)
return turn(input, direction*dir2angle(dir))
/client/Northeast()
diagonal_action(NORTHEAST)
/client/Northwest()
diagonal_action(NORTHWEST)
/client/Southeast()
diagonal_action(SOUTHEAST)
/client/Southwest()
diagonal_action(SOUTHWEST)
/client/proc/diagonal_action(direction)
switch(client_dir(direction, 1))
if(NORTHEAST)
swap_hand()
return
if(SOUTHEAST)
attack_self()
return
if(SOUTHWEST)
if(iscarbon(usr))
var/mob/living/carbon/C = usr
C.toggle_throw_mode()
else
usr << "\red This mob type cannot throw items."
return
if(NORTHWEST)
if(iscarbon(usr))
var/mob/living/carbon/C = usr
if(!C.get_active_hand())
usr << "\red You have nothing to drop in your hand."
return
drop_item()
else
usr << "\red This mob type cannot drop items."
return
//This gets called when you press the delete button.
/client/verb/delete_key_pressed()
set hidden = 1
if(!usr.pulling)
usr << "\blue You are not pulling anything."
return
usr.stop_pulling()
/client/verb/swap_hand()
set hidden = 1
if(istype(mob, /mob/living/carbon))
mob:swap_hand()
if(istype(mob,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = mob
R.cycle_modules()
return
/client/verb/attack_self()
set hidden = 1
if(mob)
mob.mode()
return
/client/verb/toggle_throw_mode()
set hidden = 1
if(!istype(mob, /mob/living/carbon))
return
if (!mob.stat && isturf(mob.loc) && !mob.restrained())
mob:toggle_throw_mode()
else
return
/client/verb/drop_item()
set hidden = 1
if(!isrobot(mob) && mob.stat == CONSCIOUS && isturf(mob.loc))
return mob.drop_item()
return
/client/Center()
/* No 3D movement in 2D spessman game. dir 16 is Z Up
if (isobj(mob.loc))
var/obj/O = mob.loc
if (mob.canmove)
return O.relaymove(mob, 16)
*/
return
//This proc should never be overridden elsewhere at /atom/movable to keep directions sane.
/atom/movable/Move(newloc, direct)
if (direct & (direct - 1))
if (direct & 1)
if (direct & 4)
if (step(src, NORTH))
step(src, EAST)
else
if (step(src, EAST))
step(src, NORTH)
else
if (direct & 8)
if (step(src, NORTH))
step(src, WEST)
else
if (step(src, WEST))
step(src, NORTH)
else
if (direct & 2)
if (direct & 4)
if (step(src, SOUTH))
step(src, EAST)
else
if (step(src, EAST))
step(src, SOUTH)
else
if (direct & 8)
if (step(src, SOUTH))
step(src, WEST)
else
if (step(src, WEST))
step(src, SOUTH)
else
var/atom/A = src.loc
var/olddir = dir //we can't override this without sacrificing the rest of movable/New()
. = ..()
if(direct != olddir)
dir = olddir
set_dir(direct)
src.move_speed = world.time - src.l_move_time
src.l_move_time = world.time
src.m_flag = 1
if ((A != src.loc && A && A.z == src.z))
src.last_move = get_dir(A, src.loc)
return
/client/proc/Move_object(direct)
if(mob && mob.control_object)
if(mob.control_object.density)
step(mob.control_object,direct)
if(!mob.control_object) return
mob.control_object.dir = direct
else
mob.control_object.forceMove(get_step(mob.control_object,direct))
return
/client/Move(n, direct)
if(!mob)
return // Moved here to avoid nullrefs below
if(mob.control_object) Move_object(direct)
if(mob.incorporeal_move && isobserver(mob))
Process_Incorpmove(direct)
return
if(moving) return 0
if(world.time < move_delay)
return
//This compensates for the inaccuracy of move ticks
//Whenever world.time overshoots the movedelay, due to it only ticking once per decisecond
//The overshoot value is subtracted from our next delay, farther down where move delay is set.
//This doesn't entirely remove the problem, but it keeps travel times accurate to within 0.1 seconds
//Over an infinite distance, and prevents the inaccuracy from compounding. Thus making it basically a non-issue
var/leftover = world.time - move_delay
if (leftover > 1)
leftover = 0
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.ghostize()
return
// handle possible Eye movement
if(mob.eyeobj)
return mob.EyeMove(n,direct)
if(mob.transforming) return//This is sota the goto stop mobs from moving var
if(isliving(mob))
var/mob/living/L = 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
//TODO: REMOVE This stupid zooming stuff
/*
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()
*/
if(Process_Grab()) return
if(!mob.canmove)
return
//if(istype(mob.loc, /turf/space) || (mob.flags & NOGRAV))
// if(!mob.Process_Spacemove(0)) return 0
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))
src << "\blue You're restrained! You can't move!"
return 0
else
M.stop_pulling()
if(mob.pinned.len)
src << "\blue You're pinned to a wall by [mob.pinned[1]]!"
return 0
move_delay = world.time - leftover//set move delay
if (mob.buckled)
if(istype(mob.buckled, /obj/vehicle))
//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
move_delay = world.time
//drunk driving
if(mob.confused && prob(20))
direct = pick(cardinal)
return mob.buckled.relaymove(mob,direct)
if(istype(mob.loc, /turf/space)) // Wheelchair driving!
return // No wheelchair driving in space
//TODO: Fuck wheelchairs.
//Toss away all this snowflake code here, and rewrite wheelchairs as a vehicle.
else if(istype(mob.buckled, /obj/structure/bed/chair/wheelchair))
var/min_move_delay = 0
if(ishuman(mob.buckled))
var/mob/living/carbon/human/driver = mob.buckled
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!
min_move_delay = driver.min_walk_delay
//drunk wheelchair driving
if(mob.confused && prob(20))
direct = pick(cardinal)
move_delay += max((mob.movement_delay() + config.walk_speed) * config.walk_delay_multiplier, min_move_delay)
return mob.buckled.relaymove(mob,direct)
var/tally = mob.movement_delay() + config.walk_speed
// Apply huuman specific modifiers.
if (ishuman(mob))
var/mob/living/carbon/human/H = mob
//If we're sprinting and able to continue sprinting, then apply the sprint bonus ontop of this
if (H.m_intent == "run" && H.species.handle_sprint_cost(H, tally)) //This will return false if we collapse from exhaustion
tally = (tally / (1 + H.sprint_speed_factor)) * config.run_delay_multiplier
else
tally = max(tally * config.walk_delay_multiplier, H.min_walk_delay) //clamp walking speed if its limited
else
tally *= config.walk_delay_multiplier
move_delay += tally
var/tickcomp = 0 //moved this out here so we can use it for vehicles
if(config.Tickcomp)
// move_delay -= 1.3 //~added to the tickcomp calculation below
tickcomp = ((1/(world.tick_lag))*1.3) - 1.3
move_delay = move_delay + tickcomp
if(istype(mob.machine, /obj/machinery))
if(mob.machine.relaymove(mob,direct))
return
//Wheelchair pushing goes here for now.
//TODO: Fuck wheelchairs.
if(istype(mob.pulledby, /obj/structure/bed/chair/wheelchair))
move_delay += 1
return mob.pulledby.relaymove(mob, direct)
//We are now going to move
moving = 1
//Something with pulling things
if(locate(/obj/item/weapon/grab, mob))
move_delay = max(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))
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
else if(mob.confused && prob(20))
step(mob, pick(cardinal))
else
. = mob.SelfMove(n, 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()
moving = 0
return .
return
/mob/proc/SelfMove(turf/n, direct)
return Move(n, direct)
///Process_Incorpmove
///Called by client/Move()
///Allows mobs to run though walls
/client/proc/Process_Incorpmove(direct)
var/turf/mobloc = get_turf(mob)
switch(mob.incorporeal_move)
if(1)
var/turf/T = get_step(mob, direct)
if(mob.check_holy(T))
mob << "<span class='warning'>You cannot get past holy grounds while you are in this plane of existence!</span>"
return
else
mob.forceMove(get_step(mob, direct))
mob.dir = direct
if(2)
if(prob(50))
var/locx
var/locy
switch(direct)
if(NORTH)
locx = mobloc.x
locy = (mobloc.y+2)
if(locy>world.maxy)
return
if(SOUTH)
locx = mobloc.x
locy = (mobloc.y-2)
if(locy<1)
return
if(EAST)
locy = mobloc.y
locx = (mobloc.x+2)
if(locx>world.maxx)
return
if(WEST)
locy = mobloc.y
locx = (mobloc.x-2)
if(locx<1)
return
else
return
mob.forceMove(locate(locx,locy,mobloc.z))
spawn(0)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, mob.loc))
spawn(0)
anim(T,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir)
limit--
if(limit<=0) break
else
spawn(0)
anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,mob.dir)
mob.forceMove(get_step(mob, direct))
mob.dir = direct
// Crossed is always a bit iffy
for(var/obj/S in mob.loc)
if(istype(S,/obj/effect/step_trigger) || istype(S,/obj/effect/beam))
S.Crossed(mob)
var/area/A = get_area_master(mob)
if(A)
A.Entered(mob)
if(isturf(mob.loc))
var/turf/T = mob.loc
T.Entered(mob)
mob.Post_Incorpmove()
return 1
/mob/proc/Post_Incorpmove()
return
///Process_Spacemove
///Called by /client/Move()
///For moving in space
///Return 1 for movement 0 for none
/mob/proc/Process_Spacemove(var/check_drift = 0)
if(!Check_Dense_Object()) //Nothing to push off of so end here
update_floating(0)
return 0
update_floating(1)
if(restrained()) //Check to see if we can do things
return 0
//Check to see if we slipped
if(prob(slip_chance(5)) && !buckled)
src << "<span class='warning'>You slipped!</span>"
src.inertia_dir = src.last_move
step(src, src.inertia_dir)
return 0
//If not then we can reset inertia and move
inertia_dir = 0
return 1
/mob/proc/Check_Dense_Object() //checks for anything to push off in the vicinity. also handles magboots on gravity-less floors tiles
var/shoegrip = Check_Shoegrip()
for(var/turf/simulated/T in trange(1,src)) //we only care for non-space turfs
if(T.density) //walls work
return 1
else
var/area/A = T.loc
if(A.has_gravity || shoegrip)
return 1
for(var/obj/O in orange(1, src))
if(istype(O, /obj/structure/lattice))
return 1
if(O && O.density && O.anchored)
return 1
return 0
/mob/proc/Check_Shoegrip()
return 0
/mob/proc/slip_chance(var/prob_slip = 5)
if(stat)
return 0
if(Check_Shoegrip())
return 0
return prob_slip