mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-26 02:02:39 +00:00
518 lines
13 KiB
Plaintext
518 lines
13 KiB
Plaintext
/mob/CanPass(atom/movable/mover, turf/target, height=0)
|
|
if(height==0)
|
|
return 1
|
|
if(istype(mover, /obj/item/projectile))
|
|
return (!density || lying)
|
|
if(mover.throwing)
|
|
return (!density || lying || (mover.throwing.thrower == src))
|
|
if(mover.checkpass(PASSMOB))
|
|
return 1
|
|
if(buckled == mover)
|
|
return TRUE
|
|
if(ismob(mover))
|
|
var/mob/moving_mob = mover
|
|
if((other_mobs && moving_mob.other_mobs))
|
|
return TRUE
|
|
if(mover in buckled_mobs)
|
|
return TRUE
|
|
return (!mover.density || !density || lying)
|
|
|
|
|
|
/client/verb/toggle_throw_mode()
|
|
set hidden = 1
|
|
if(iscarbon(mob))
|
|
var/mob/living/carbon/C = mob
|
|
C.toggle_throw_mode()
|
|
else
|
|
to_chat(usr, "<span class='danger'>This mob type cannot throw items.</span>")
|
|
|
|
/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.setDir(direct)
|
|
else
|
|
mob.control_object.forceMove(get_step(mob.control_object, direct))
|
|
return
|
|
|
|
#define MOVEMENT_DELAY_BUFFER 0.75
|
|
#define MOVEMENT_DELAY_BUFFER_DELTA 1.25
|
|
/client/Move(n, direct)
|
|
if(world.time < move_delay)
|
|
return
|
|
else
|
|
next_move_dir_add = 0
|
|
next_move_dir_sub = 0
|
|
var/old_move_delay = move_delay
|
|
move_delay = world.time + world.tick_lag //this is here because Move() can now be called multiple times per tick
|
|
if(!mob || !mob.loc)
|
|
return 0
|
|
|
|
if(!n || !direct) // why did we never check this before?
|
|
return FALSE
|
|
|
|
if(mob.notransform)
|
|
return 0 //This is sota the goto stop mobs from moving var
|
|
|
|
if(mob.control_object)
|
|
return Move_object(direct)
|
|
|
|
if(!isliving(mob))
|
|
return mob.Move(n, direct)
|
|
|
|
if(mob.stat == DEAD)
|
|
mob.ghostize()
|
|
return 0
|
|
|
|
if(moving)
|
|
return 0
|
|
|
|
if(isliving(mob))
|
|
var/mob/living/L = mob
|
|
if(L.incorporeal_move)//Move though walls
|
|
Process_Incorpmove(direct)
|
|
return
|
|
|
|
if(mob.remote_control) //we're controlling something, our movement is relayed to it
|
|
return mob.remote_control.relaymove(mob, direct)
|
|
|
|
if(isAI(mob))
|
|
if(istype(mob.loc, /obj/item/aicard))
|
|
var/obj/O = mob.loc
|
|
return O.relaymove(mob, direct) // aicards have special relaymove stuff
|
|
return AIMove(n, direct, mob)
|
|
|
|
|
|
if(Process_Grab())
|
|
return
|
|
|
|
if(mob.buckled) //if we're buckled to something, tell it we moved.
|
|
return mob.buckled.relaymove(mob, direct)
|
|
|
|
if(!mob.canmove)
|
|
return
|
|
|
|
if(!mob.lastarea)
|
|
mob.lastarea = get_area(mob.loc)
|
|
|
|
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(!mob.Process_Spacemove(direct))
|
|
return 0
|
|
|
|
if(mob.restrained()) // Why being pulled while cuffed prevents you from moving
|
|
for(var/mob/M in orange(1, mob))
|
|
if(M.pulling == mob)
|
|
if(!M.incapacitated() && mob.Adjacent(M))
|
|
to_chat(src, "<span class='warning'>You're restrained! You can't move!</span>")
|
|
move_delay = world.time + 10
|
|
return 0
|
|
else
|
|
M.stop_pulling()
|
|
|
|
|
|
//We are now going to move
|
|
moving = 1
|
|
var/delay = mob.movement_delay()
|
|
if(old_move_delay + (delay * MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
|
|
move_delay = old_move_delay
|
|
else
|
|
move_delay = world.time
|
|
mob.last_movement = world.time
|
|
|
|
delay = TICKS2DS(-round(-(DS2TICKS(delay)))) //Rounded to the next tick in equivalent ds
|
|
|
|
if(locate(/obj/item/grab, mob))
|
|
delay += 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/prev_loc = mob.loc
|
|
. = mob.SelfMove(n, direct, delay)
|
|
if(M && isturf(M.loc)) // Mob may get deleted during parent call
|
|
var/diag = get_dir(mob, M)
|
|
if((diag - 1) & diag)
|
|
else
|
|
diag = null
|
|
if((get_dist(mob, M) > 1 || diag))
|
|
M.Move(prev_loc, get_dir(M.loc, prev_loc), delay)
|
|
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)
|
|
M.Move(get_step(M,direct), direct, delay)
|
|
spawn(1)
|
|
M.other_mobs = null
|
|
M.animate_movement = 2
|
|
|
|
else if(mob.confused)
|
|
var/newdir = 0
|
|
if(mob.confused > 40)
|
|
newdir = pick(GLOB.alldirs)
|
|
else if(prob(mob.confused * 1.5))
|
|
newdir = angle2dir(dir2angle(direct) + pick(90, -90))
|
|
else if(prob(mob.confused * 3))
|
|
newdir = angle2dir(dir2angle(direct) + pick(45, -45))
|
|
if(newdir)
|
|
direct = newdir
|
|
n = get_step(mob, direct)
|
|
|
|
var/prev_pulling_loc = null
|
|
if(mob.pulling)
|
|
prev_pulling_loc = mob.pulling.loc
|
|
|
|
. = mob.SelfMove(n, direct, delay) // The actual movement
|
|
|
|
if(prev_pulling_loc && mob.pulling?.face_while_pulling && (mob.pulling.loc != prev_pulling_loc))
|
|
mob.setDir(get_dir(mob, mob.pulling)) // Face welding tanks and stuff when pulling
|
|
else
|
|
mob.setDir(direct)
|
|
|
|
if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
|
|
delay = mob.movement_delay() * 2 //Will prevent mob diagonal moves from smoothing accurately, sadly
|
|
|
|
move_delay += delay
|
|
|
|
for(var/obj/item/grab/G in mob)
|
|
if(G.state == GRAB_NECK)
|
|
mob.setDir(angle2dir((dir2angle(direct) + 202.5) % 365))
|
|
G.adjust_position()
|
|
for(var/obj/item/grab/G in mob.grabbed_by)
|
|
G.adjust_position()
|
|
|
|
moving = 0
|
|
if(mob && .)
|
|
if(mob.throwing)
|
|
mob.throwing.finalize(FALSE)
|
|
|
|
for(var/obj/O in mob)
|
|
O.on_mob_move(direct, mob)
|
|
|
|
|
|
/mob/proc/SelfMove(turf/n, direct, movetime)
|
|
return Move(n, direct, movetime)
|
|
|
|
///Process_Grab()
|
|
///Called by client/Move()
|
|
///Checks to see if you are being grabbed and if so attemps to break it
|
|
/client/proc/Process_Grab()
|
|
if(mob.grabbed_by.len)
|
|
if(mob.incapacitated(FALSE, TRUE, TRUE)) // Can't break out of grabs if you're incapacitated
|
|
return TRUE
|
|
var/list/grabbing = list()
|
|
|
|
if(istype(mob.l_hand, /obj/item/grab))
|
|
var/obj/item/grab/G = mob.l_hand
|
|
grabbing += G.affecting
|
|
|
|
if(istype(mob.r_hand, /obj/item/grab))
|
|
var/obj/item/grab/G = mob.r_hand
|
|
grabbing += G.affecting
|
|
|
|
for(var/X in mob.grabbed_by)
|
|
var/obj/item/grab/G = X
|
|
switch(G.state)
|
|
|
|
if(GRAB_PASSIVE)
|
|
if(!grabbing.Find(G.assailant)) //moving always breaks a passive grab unless we are also grabbing our grabber.
|
|
qdel(G)
|
|
|
|
if(GRAB_AGGRESSIVE)
|
|
move_delay = world.time + 10
|
|
if(!prob(25))
|
|
return TRUE
|
|
mob.visible_message("<span class='danger'>[mob] has broken free of [G.assailant]'s grip!</span>")
|
|
qdel(G)
|
|
|
|
if(GRAB_NECK)
|
|
move_delay = world.time + 10
|
|
if(!prob(5))
|
|
return TRUE
|
|
mob.visible_message("<span class='danger'>[mob] has broken free of [G.assailant]'s headlock!</span>")
|
|
qdel(G)
|
|
return FALSE
|
|
|
|
|
|
///Process_Incorpmove
|
|
///Called by client/Move()
|
|
///Allows mobs to run though walls
|
|
/client/proc/Process_Incorpmove(direct)
|
|
var/turf/mobloc = get_turf(mob)
|
|
if(!isliving(mob))
|
|
return
|
|
var/mob/living/L = mob
|
|
switch(L.incorporeal_move)
|
|
if(1)
|
|
L.forceMove(get_step(L, direct))
|
|
L.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
|
|
L.forceMove(locate(locx,locy,mobloc.z))
|
|
spawn(0)
|
|
var/limit = 2//For only two trailing shadows.
|
|
for(var/turf/T in getline(mobloc, L.loc))
|
|
new /obj/effect/temp_visual/dir_setting/ninja/shadow(T, L.dir)
|
|
limit--
|
|
if(limit<=0)
|
|
break
|
|
else
|
|
new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
|
|
L.forceMove(get_step(L, direct))
|
|
L.dir = direct
|
|
if(3) //Incorporeal move, but blocked by holy-watered tiles
|
|
var/turf/simulated/floor/stepTurf = get_step(L, direct)
|
|
if(stepTurf.flags & NOJAUNT)
|
|
to_chat(L, "<span class='warning'>Holy energies block your path.</span>")
|
|
L.notransform = 1
|
|
spawn(2)
|
|
L.notransform = 0
|
|
else
|
|
L.forceMove(get_step(L, direct))
|
|
L.dir = direct
|
|
return 1
|
|
|
|
|
|
///Process_Spacemove
|
|
///Called by /client/Move()
|
|
///For moving in space
|
|
///Return 1 for movement 0 for none
|
|
/mob/Process_Spacemove(movement_dir = 0)
|
|
if(..())
|
|
return 1
|
|
var/atom/movable/backup = get_spacemove_backup()
|
|
if(backup)
|
|
if(istype(backup) && movement_dir && !backup.anchored)
|
|
var/opposite_dir = turn(movement_dir, 180)
|
|
if(backup.newtonian_move(opposite_dir)) //You're pushing off something movable, so it moves
|
|
to_chat(src, "<span class='notice'>You push off of [backup] to propel yourself.</span>")
|
|
return 1
|
|
return 0
|
|
|
|
/mob/get_spacemove_backup()
|
|
for(var/A in orange(1, get_turf(src)))
|
|
if(isarea(A))
|
|
continue
|
|
else if(isturf(A))
|
|
var/turf/turf = A
|
|
if(istype(turf, /turf/space))
|
|
continue
|
|
if(!turf.density && !mob_negates_gravity())
|
|
continue
|
|
return A
|
|
else
|
|
var/atom/movable/AM = A
|
|
if(AM == buckled) //Kind of unnecessary but let's just be sure
|
|
continue
|
|
if(!AM.CanPass(src) || AM.density)
|
|
if(AM.anchored)
|
|
return AM
|
|
if(pulling == AM)
|
|
continue
|
|
. = AM
|
|
|
|
|
|
/mob/proc/mob_has_gravity(turf/T)
|
|
return has_gravity(src, T)
|
|
|
|
/mob/proc/mob_negates_gravity()
|
|
return 0
|
|
|
|
/mob/proc/Move_Pulled(atom/A)
|
|
if(!canmove || restrained() || !pulling)
|
|
return
|
|
if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src))
|
|
stop_pulling()
|
|
return
|
|
if(isliving(pulling))
|
|
var/mob/living/L = pulling
|
|
if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it
|
|
stop_pulling()
|
|
return
|
|
if(A == loc && pulling.density)
|
|
return
|
|
if(!Process_Spacemove(get_dir(pulling.loc, A)))
|
|
return
|
|
if(ismob(pulling))
|
|
var/mob/M = pulling
|
|
var/atom/movable/t = M.pulling
|
|
M.stop_pulling()
|
|
step(pulling, get_dir(pulling.loc, A))
|
|
if(M)
|
|
M.start_pulling(t)
|
|
else
|
|
step(pulling, get_dir(pulling.loc, A))
|
|
return
|
|
|
|
/mob/proc/update_gravity(has_gravity)
|
|
return
|
|
|
|
/client/proc/check_has_body_select()
|
|
return mob && mob.hud_used && mob.hud_used.zone_select && istype(mob.hud_used.zone_select, /obj/screen/zone_sel)
|
|
|
|
/client/verb/body_toggle_head()
|
|
set name = "body-toggle-head"
|
|
set hidden = 1
|
|
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/next_in_line
|
|
switch(mob.zone_selected)
|
|
if(BODY_ZONE_HEAD)
|
|
next_in_line = BODY_ZONE_PRECISE_EYES
|
|
if(BODY_ZONE_PRECISE_EYES)
|
|
next_in_line = BODY_ZONE_PRECISE_MOUTH
|
|
else
|
|
next_in_line = BODY_ZONE_HEAD
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(next_in_line, mob)
|
|
|
|
/client/verb/body_r_arm()
|
|
set name = "body-r-arm"
|
|
set hidden = 1
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/next_in_line
|
|
if(mob.zone_selected == BODY_ZONE_R_ARM)
|
|
next_in_line = BODY_ZONE_PRECISE_R_HAND
|
|
else
|
|
next_in_line = BODY_ZONE_R_ARM
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(next_in_line, mob)
|
|
|
|
/client/verb/body_chest()
|
|
set name = "body-chest"
|
|
set hidden = 1
|
|
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(BODY_ZONE_CHEST, mob)
|
|
|
|
/client/verb/body_l_arm()
|
|
set name = "body-l-arm"
|
|
set hidden = 1
|
|
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/next_in_line
|
|
if(mob.zone_selected == BODY_ZONE_L_ARM)
|
|
next_in_line = BODY_ZONE_PRECISE_L_HAND
|
|
else
|
|
next_in_line = BODY_ZONE_L_ARM
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(next_in_line, mob)
|
|
|
|
/client/verb/body_r_leg()
|
|
set name = "body-r-leg"
|
|
set hidden = 1
|
|
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/next_in_line
|
|
if(mob.zone_selected == BODY_ZONE_R_LEG)
|
|
next_in_line = BODY_ZONE_PRECISE_R_FOOT
|
|
else
|
|
next_in_line = BODY_ZONE_R_LEG
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(next_in_line, mob)
|
|
|
|
/client/verb/body_groin()
|
|
set name = "body-groin"
|
|
set hidden = 1
|
|
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(BODY_ZONE_PRECISE_GROIN, mob)
|
|
|
|
/client/verb/body_l_leg()
|
|
set name = "body-l-leg"
|
|
set hidden = 1
|
|
|
|
if(!check_has_body_select())
|
|
return
|
|
|
|
var/next_in_line
|
|
if(mob.zone_selected == BODY_ZONE_L_LEG)
|
|
next_in_line = BODY_ZONE_PRECISE_L_FOOT
|
|
else
|
|
next_in_line = BODY_ZONE_L_LEG
|
|
|
|
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
|
|
selector.set_selected_zone(next_in_line, mob)
|
|
|
|
/client/verb/toggle_walk_run()
|
|
set name = "toggle-walk-run"
|
|
set hidden = TRUE
|
|
set instant = TRUE
|
|
if(mob)
|
|
mob.toggle_move_intent()
|
|
|
|
/mob/proc/toggle_move_intent()
|
|
if(iscarbon(src))
|
|
var/mob/living/carbon/C = src
|
|
if(C.legcuffed)
|
|
to_chat(C, "<span class='notice'>You are legcuffed! You cannot run until you get [C.legcuffed] removed!</span>")
|
|
C.m_intent = MOVE_INTENT_WALK //Just incase
|
|
C.hud_used.move_intent.icon_state = "walking"
|
|
return
|
|
|
|
var/icon_toggle
|
|
if(m_intent == MOVE_INTENT_RUN)
|
|
m_intent = MOVE_INTENT_WALK
|
|
icon_toggle = "walking"
|
|
else
|
|
m_intent = MOVE_INTENT_RUN
|
|
icon_toggle = "running"
|
|
|
|
if(hud_used && hud_used.move_intent && hud_used.static_inventory)
|
|
hud_used.move_intent.icon_state = icon_toggle
|
|
for(var/obj/screen/mov_intent/selector in hud_used.static_inventory)
|
|
selector.update_icon(src)
|