diff --git a/code/datums/riding.dm b/code/datums/riding.dm
index 27911b88dfb..20bbc1552ad 100644
--- a/code/datums/riding.dm
+++ b/code/datums/riding.dm
@@ -15,6 +15,17 @@
else
ridden.layer = OBJ_LAYER
+/datum/riding/proc/on_vehicle_move()
+ for(var/mob/living/M in ridden.buckled_mobs)
+ ride_check(M)
+ handle_vehicle_offsets()
+ handle_vehicle_layer()
+
+/datum/riding/proc/ride_check(mob/living/M)
+ return TRUE
+
+/datum/riding/proc/force_dismount(mob/living/M)
+ ridden.unbuckle_mob(M)
//Override this to set your vehicle's various pixel offsets
//if they differ between directions, otherwise use the
@@ -36,7 +47,6 @@
return TRUE
return FALSE
-
//BUCKLE HOOKS
/datum/riding/proc/restore_position(mob/living/buckled_mob)
if(istype(buckled_mob))
@@ -45,11 +55,6 @@
if(buckled_mob.client)
buckled_mob.client.change_view(world.view)
-
-
-
-
-
//MOVEMENT
/datum/riding/proc/handle_ride(mob/user, direction)
if(user.incapacitated())
@@ -298,12 +303,59 @@
else
user << "You'll need something to guide the [ridden.name]."
-//CYBORGS. NO, THEY ARE NOT ANIMALS.
+///////Humans. Yes, I said humans. No, this won't end well...//////////
+/datum/riding/human
+ keytype = null
+
+/datum/riding/human/ride_check(mob/living/M)
+ var/mob/living/carbon/human/H = ridden //IF this runtimes I'm blaming the admins.
+ if(M.incapacitated(FALSE, TRUE) || H.incapacitated(FALSE, TRUE))
+ M.visible_message("[M] falls off of [ridden]!")
+ ridden.unbuckle_mob(M)
+ return FALSE
+ if(M.restrained(TRUE))
+ M.visible_message("[M] can't hang onto [ridden] with their hands cuffed!") //Honestly this should put the ridden mob in a chokehold.
+ ridden.unbuckle_mob(M)
+ return FALSE
+ if(H.pulling == M)
+ H.stop_pulling()
+
+/datum/riding/human/handle_vehicle_offsets()
+ for(var/mob/living/M in ridden.buckled_mobs)
+ M.setDir(ridden.dir)
+ switch(ridden.dir)
+ if(NORTH)
+ M.pixel_x = 0
+ M.pixel_y = 6
+ if(SOUTH)
+ M.pixel_x = 0
+ M.pixel_y = 6
+ if(EAST)
+ M.pixel_x = -6
+ M.pixel_y = 4
+ if(WEST)
+ M.pixel_x = 6
+ M.pixel_y = 4
+
+/datum/riding/human/handle_vehicle_layer()
+ if(ridden.buckled_mobs && ridden.buckled_mobs.len)
+ if(ridden.dir == SOUTH)
+ ridden.layer = ABOVE_MOB_LAYER
+ else
+ ridden.layer = OBJ_LAYER
+ else
+ ridden.layer = MOB_LAYER
+
+/datum/riding/human/force_dismount(mob/living/user)
+ ridden.unbuckle_mob(user)
+ user.Weaken(3)
+ user.Stun(3)
+ user.visible_message("[ridden] pushes [user] off of them!")
+
/datum/riding/cyborg
keytype = null
- vehicle_move_delay = 1
-/datum/riding/cyborg/proc/ride_check(mob/user)
+/datum/riding/cyborg/ride_check(mob/user)
if(user.incapacitated())
var/kick = TRUE
if(istype(ridden, /mob/living/silicon/robot))
@@ -322,11 +374,12 @@
return
/datum/riding/cyborg/handle_vehicle_layer()
- if(ridden.dir == SOUTH)
- ridden.layer = ABOVE_MOB_LAYER
+ if(ridden.buckled_mobs && ridden.buckled_mobs.len)
+ if(ridden.dir == SOUTH)
+ ridden.layer = ABOVE_MOB_LAYER
+ else
+ ridden.layer = OBJ_LAYER
else
- ridden.layer = OBJ_LAYER
- if(!ridden.buckled_mobs)
ridden.layer = MOB_LAYER
/datum/riding/cyborg/handle_vehicle_offsets()
@@ -353,19 +406,65 @@
M.pixel_x = 6
M.pixel_y = 3
-/datum/riding/cyborg/proc/on_vehicle_move()
- for(var/mob/living/M in ridden.buckled_mobs)
- ride_check(M)
- handle_vehicle_offsets()
- handle_vehicle_layer()
+/datum/riding/cyborg/force_dismount(mob/living/M)
+ ridden.unbuckle_mob(M)
+ var/turf/target = get_edge_target_turf(ridden, ridden.dir)
+ var/turf/targetm = get_step(get_turf(ridden), ridden.dir)
+ M.Move(targetm)
+ M.visible_message("[M] is thrown clear of [ridden]!")
+ M.throw_at(target, 14, 5, ridden)
+ M.Weaken(3)
-/datum/riding/cyborg/proc/force_dismount()
- for(var/mob/living/M in ridden.buckled_mobs)
- ridden.unbuckle_mob(M)
- var/turf/target = get_edge_target_turf(ridden, ridden.dir)
- var/turf/targetm = get_step(get_turf(ridden), ridden.dir)
- M.Move(targetm)
- M.visible_message("[M] is thrown clear of [ridden] by rapid spinning!")
- M.throw_at(target, 14, 5, ridden)
- M.Weaken(3)
+/datum/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
+ var/amount_equipped = 0
+ for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
+ var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
+ inhand.rider = user
+ inhand.ridden = ridden
+ if(user.put_in_hands(inhand, TRUE))
+ amount_equipped++
+ else
+ break
+ if(amount_equipped >= amount_required)
+ return TRUE
+ else
+ unequip_buckle_inhands(user)
+ return FALSE
+/datum/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
+ for(var/obj/item/riding_offhand/O in user.contents)
+ if(O.ridden != ridden)
+ CRASH("RIDING OFFHAND ON WRONG MOB")
+ continue
+ if(O.selfdeleting)
+ continue
+ else
+ qdel(O)
+ return TRUE
+
+/obj/item/riding_offhand
+ name = "offhand"
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "offhand"
+ w_class = WEIGHT_CLASS_HUGE
+ flags = ABSTRACT | DROPDEL | NOBLUDGEON
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ var/mob/living/carbon/rider
+ var/mob/living/ridden
+ var/selfdeleting = FALSE
+
+/obj/item/riding_offhand/dropped()
+ selfdeleting = TRUE
+ . = ..()
+
+/obj/item/riding_offhand/equipped()
+ if(loc != rider)
+ selfdeleting = TRUE
+ qdel(src)
+ . = ..()
+
+/obj/item/riding_offhand/Destroy()
+ if(selfdeleting)
+ if(rider in ridden.buckled_mobs)
+ ridden.unbuckle_mob(rider)
+ . = ..()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0ff51c45cf7..b0eac013cd8 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -895,3 +895,39 @@
.["Make alien"] = "?_src_=vars;makealien=\ref[src]"
.["Make slime"] = "?_src_=vars;makeslime=\ref[src]"
.["Toggle Purrbation"] = "?_src_=vars;purrbation=\ref[src]"
+
+/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
+ if((target != pulling) || (grab_state < GRAB_AGGRESSIVE) || (user != target)) //Get consent first :^)
+ . = ..()
+ return
+ buckle_mob(target, FALSE, TRUE, TRUE)
+ . = ..()
+
+/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE, yes = FALSE)
+ if(!yes)
+ return
+ if(!is_type_in_typecache(M, can_ride_typecache))
+ M.visible_message("[M] really can't seem to mount [src]...")
+ return
+ if(!riding_datum)
+ riding_datum = new /datum/riding/human
+ riding_datum.ridden = src
+ if(buckled_mobs && ((M in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)))
+ return
+ if(buckled) //NO INFINITE STACKING!!
+ return
+ if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
+ M.visible_message("[M] can't hang onto [src]!")
+ return
+ if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 2))) //MAKE SURE THIS IS LAST!!
+ M.visible_message("[M] can't climb onto [src] because [M.p_their()] hands are full!")
+ return
+ . = ..(M, force, check_loc)
+ stop_pulling()
+
+/mob/living/carbon/human/unbuckle_mob(mob/living/M)
+ if(iscarbon(M))
+ if(riding_datum)
+ riding_datum.unequip_buckle_inhands(M)
+ riding_datum.restore_position(M)
+ . = ..(M)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 2cc4c859920..16c2ae46bc4 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -201,6 +201,9 @@
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return
+ if(M.a_intent == INTENT_DISARM)
+ if(M.buckled_mobs && (src in M.buckled_mobs) && M.riding_datum)
+ M.riding_datum.force_dismount(src)
dna.species.spec_attack_hand(M, src)
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 6bd8d9cef98..d712ce9b6a9 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -50,3 +50,6 @@ var/global/default_martial_art = new/datum/martial_art
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/datum/personal_crafting/handcrafting
+ can_buckle = TRUE
+ buckle_lying = FALSE
+ can_ride_typecache = list(/mob/living/carbon/human)
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index ed5828dfa4b..7abcefe143e 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -55,7 +55,8 @@
//End bloody footprints
S.step_action()
-
+ if(buckled_mobs && buckled_mobs.len && riding_datum)
+ riding_datum.on_vehicle_move()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(..())
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index ddcd73cbb88..2b0e14350c8 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -462,6 +462,10 @@
user.spin(20, 1)
if(istype(user, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
- if(R.riding_datum)
- R.riding_datum.force_dismount()
+ if(R.buckled_mobs)
+ for(var/mob/M in R.buckled_mobs)
+ if(R.riding_datum)
+ R.riding_datum.force_dismount(M)
+ else
+ R.unbuckle_all_mobs()
..()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 224222169df..fb06982843b 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -91,7 +91,7 @@
can_buckle = TRUE
buckle_lying = FALSE
- var/datum/riding/cyborg/riding_datum = null
+ can_ride_typecache = list(/mob/living/carbon/human)
/mob/living/silicon/robot/New(loc)
spark_system = new /datum/effect_system/spark_spread()
@@ -1006,6 +1006,9 @@
buckle_mob(M)
/mob/living/silicon/robot/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
+ if(!is_type_in_typecache(M, can_ride_typecache))
+ M.visible_message("[M] really can't seem to mount the [src]...")
+ return
if(!riding_datum)
riding_datum = new /datum/riding/cyborg
riding_datum.ridden = src
@@ -1020,69 +1023,18 @@
return
if(M.restrained())
return
- if(iscyborg(M))
- M.visible_message("[M] really can't seem to mount the [src]...")
- return
- if(isbot(M))
- M.visible_message("No. Just... no.")
- return
if(module)
if(!module.allow_riding)
M.visible_message("Unfortunately, [M] just can't seem to hold onto [src]!")
return
- if(iscarbon(M))
- if(!equip_buckle_inhands(M)) //MAKE SURE THIS IS LAST!
- M.visible_message("[M] can't climb onto [src] because his hands are full!")
- return
+ if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 1)))
+ M.visible_message("[M] can't climb onto [src] because his hands are full!")
+ return
. = ..(M, force, check_loc)
- riding_datum.handle_vehicle_offsets()
/mob/living/silicon/robot/unbuckle_mob(mob/user)
if(iscarbon(user))
- unequip_buckle_inhands(user)
+ if(riding_datum)
+ riding_datum.unequip_buckle_inhands(user)
+ riding_datum.restore_position(user)
. = ..(user)
- riding_datum.restore_position(user)
-
-/mob/living/silicon/robot/proc/unequip_buckle_inhands(mob/living/carbon/user)
- for(var/obj/item/cyborgride_offhand/O in user.contents)
- if(O.ridden != src)
- CRASH("RIDING OFFHAND ON WRONG MOB")
- continue
- if(O.selfdeleting)
- continue
- else
- qdel(O)
- return TRUE
-
-/mob/living/silicon/robot/proc/equip_buckle_inhands(mob/living/carbon/user)
- var/obj/item/cyborgride_offhand/inhand = new /obj/item/cyborgride_offhand(user)
- inhand.rider = user
- inhand.ridden = src
- return user.put_in_hands(inhand, TRUE)
-
-/obj/item/cyborgride_offhand
- name = "offhand"
- icon = 'icons/obj/weapons.dmi'
- icon_state = "offhand"
- w_class = WEIGHT_CLASS_HUGE
- flags = ABSTRACT | DROPDEL | NOBLUDGEON
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
- var/mob/living/carbon/rider
- var/mob/living/silicon/robot/ridden
- var/selfdeleting = FALSE
-
-/obj/item/cyborgride_offhand/dropped()
- selfdeleting = TRUE
- . = ..()
-
-/obj/item/cyborgride_offhand/equipped()
- if(loc != rider)
- selfdeleting = TRUE
- qdel(src)
- . = ..()
-
-/obj/item/cyborgride_offhand/Destroy()
- if(selfdeleting)
- if(rider in ridden.buckled_mobs)
- ridden.unbuckle_mob(rider)
- . = ..()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index b2772c7312f..e9a26713e2f 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -84,7 +84,6 @@
//domestication
var/tame = 0
- var/datum/riding/riding_datum = null
/mob/living/simple_animal/New()
..()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index c75ca28534b..1384ebe5d7d 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -28,6 +28,7 @@ var/next_mob_id = 0
else
living_mob_list += src
prepare_huds()
+ can_ride_typecache = typecacheof(can_ride_typecache)
..()
/atom/proc/prepare_huds()
@@ -944,4 +945,8 @@ var/next_mob_id = 0
switch(var_name)
if ("attack_log")
return debug_variable(var_name, attack_log, 0, src, FALSE)
- . = ..()
\ No newline at end of file
+ . = ..()
+
+/mob/post_buckle_mob(mob/living/M)
+ riding_datum.handle_vehicle_offsets()
+ riding_datum.handle_vehicle_layer()
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index e6ce7a37443..db64420414e 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -145,4 +145,6 @@
var/list/observers = null //The list of people observing this mob.
- var/list/progressbars = null //for stacking do_after bars
\ No newline at end of file
+ var/list/progressbars = null //for stacking do_after bars
+ var/datum/riding/riding_datum
+ var/list/can_ride_typecache = list()
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 3e6cb63df32..0b8c488ccd8 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -1,435 +1,435 @@
-/mob/CanPass(atom/movable/mover, turf/target, height=0)
- if(height==0)
- return 1
- if(istype(mover, /obj/item/projectile) || mover.throwing)
- return (!density || lying)
- if(mover.checkpass(PASSMOB))
- return 1
- if(buckled == mover)
- return 1
- if(ismob(mover))
- if (mover in buckled_mobs)
- return 1
- return (!mover.density || !density || lying)
-
-
-//The byond version of these verbs wait for the next tick before acting.
-// instant verbs however can run mid tick or even during the time between ticks.
-/client/verb/moveup()
- set name = ".moveup"
- set instant = 1
- Move(get_step(mob, NORTH), NORTH)
-
-/client/verb/movedown()
- set name = ".movedown"
- set instant = 1
- Move(get_step(mob, SOUTH), SOUTH)
-
-/client/verb/moveright()
- set name = ".moveright"
- set instant = 1
- Move(get_step(mob, EAST), EAST)
-
-/client/verb/moveleft()
- set name = ".moveleft"
- set instant = 1
- Move(get_step(mob, WEST), WEST)
-
-/client/Northeast()
- swap_hand()
- return
-
-
-/client/Southeast()
- attack_self()
- return
-
-
-/client/Southwest()
- if(iscarbon(usr))
- var/mob/living/carbon/C = usr
- C.toggle_throw_mode()
- else
- usr << "This mob type cannot throw items."
- return
-
-
-/client/Northwest()
- if(!usr.get_active_held_item())
- usr << "You have nothing to drop in your hand!"
- return
- usr.drop_item()
-
-//This gets called when you press the delete button.
-/client/verb/delete_key_pressed()
- set hidden = 1
-
- if(!usr.pulling)
- usr << "You are not pulling anything."
- return
- usr.stop_pulling()
-
-/client/verb/swap_hand()
- set category = "IC"
- set name = "Swap hands"
-
- if(mob)
- mob.swap_hand()
-
-/client/verb/attack_self()
- set hidden = 1
- if(mob)
- mob.mode()
- return
-
-
-/client/verb/drop_item()
- set hidden = 1
- if(!iscyborg(mob))
- mob.drop_item_v()
- return
-
-
-/client/Center()
- if(isobj(mob.loc))
- var/obj/O = mob.loc
- if(mob.canmove)
- return O.relaymove(mob, 0)
- 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.setDir(direct)
- else
- mob.control_object.loc = get_step(mob.control_object,direct)
- return
-
-
-/client/Move(n, direct)
- if(world.time < move_delay)
- return 0
- move_delay = world.time+world.tick_lag //this is here because Move() can now be called mutiple times per tick
- if(!mob || !mob.loc)
- return 0
- 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(mob.force_moving)
- return 0
- if(isliving(mob))
- var/mob/living/L = mob
- if(L.incorporeal_move) //Move though walls
- Process_Incorpmove(direct)
- return 0
-
- if(mob.remote_control) //we're controlling something, our movement is relayed to it
- return mob.remote_control.relaymove(mob, direct)
-
- if(isAI(mob))
- return AIMove(n,direct,mob)
-
- if(Process_Grab()) //are we restrained by someone's grip?
- return
-
- if(mob.buckled) //if we're buckled to something, tell it we moved.
- return mob.buckled.relaymove(mob, direct)
-
- if(!mob.canmove)
- 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(!mob.Process_Spacemove(direct))
- return 0
-
- //We are now going to move
- moving = 1
- move_delay = mob.movement_delay() + world.time
-
- if(mob.confused)
- if(mob.confused > 40)
- step(mob, pick(cardinal))
- else if(prob(mob.confused * 1.5))
- step(mob, angle2dir(dir2angle(direct) + pick(90, -90)))
- else if(prob(mob.confused * 3))
- step(mob, angle2dir(dir2angle(direct) + pick(45, -45)))
- else
- step(mob, direct)
- else
- . = ..()
-
- moving = 0
- if(mob && .)
- if(mob.throwing)
- mob.throwing.finalize(FALSE)
-
- for(var/obj/O in mob)
- O.on_mob_move(direct, src)
-
- return .
-
-
-///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.pulledby)
- if(mob.incapacitated(ignore_restraints = 1))
- move_delay = world.time + 10
- return 1
- else if(mob.restrained(ignore_grab = 1))
- move_delay = world.time + 10
- src << "You're restrained! You can't move!"
- return 1
- else
- return mob.resist_grab(1)
-
-
-///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.loc = get_step(L, direct)
- L.setDir(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.loc = locate(locx,locy,mobloc.z)
- var/limit = 2//For only two trailing shadows.
- for(var/turf/T in getline(mobloc, L.loc))
- new /obj/effect/overlay/temp/dir_setting/ninja/shadow(T, L.dir)
- limit--
- if(limit<=0)
- break
- else
- new /obj/effect/overlay/temp/dir_setting/ninja/shadow(mobloc, L.dir)
- L.loc = get_step(L, direct)
- L.setDir(direct)
- if(3) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
- var/turf/open/floor/stepTurf = get_step(L, direct)
- for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
- L << "[S] bars your passage!"
- if(isrevenant(L))
- var/mob/living/simple_animal/revenant/R = L
- R.reveal(20)
- R.stun(20)
- return
- if(stepTurf.flags & NOJAUNT)
- L << "Holy energies block your path."
- else
- L.loc = get_step(L, direct)
- L.setDir(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)
- if(backup.newtonian_move(turn(movement_dir, 180))) //You're pushing off something movable, so it moves
- src << "You push off of [backup] to propel yourself."
- 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(isspaceturf(turf))
- 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()
- return has_gravity()
-
-/mob/proc/mob_negates_gravity()
- return 0
-
-//moves the mob/object we're pulling
-/mob/proc/Move_Pulled(atom/A)
- if(!pulling)
- return
- if(pulling.anchored || !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
- step(pulling, get_dir(pulling.loc, A))
-
-
-/mob/proc/slip(s_amount, w_amount, obj/O, lube)
- return
-
-/mob/proc/update_gravity()
- return
-
-//bodypart selection - Cyberboss
-//8 toggles through head - eyes - mouth
-//4: r-arm 5: chest 6: l-arm
-//1: r-leg 2: groin 3: l-leg
-
-/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("head")
- next_in_line = "eyes"
- if("eyes")
- next_in_line = "mouth"
- else
- next_in_line = "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/obj/screen/zone_sel/selector = mob.hud_used.zone_select
- selector.set_selected_zone("r_arm", 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("chest", mob)
-
-/client/verb/body_l_arm()
- set name = "body-l-arm"
- set hidden = 1
-
- if(!check_has_body_select())
- return
-
- var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
- selector.set_selected_zone("l_arm", mob)
-
-/client/verb/body_r_leg()
- set name = "body-r-leg"
- set hidden = 1
-
- if(!check_has_body_select())
- return
-
- var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
- selector.set_selected_zone("r_leg", 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("groin", mob)
-
-/client/verb/body_l_leg()
- set name = "body-l-leg"
- set hidden = 1
-
- if(!check_has_body_select())
- return
-
- var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
- selector.set_selected_zone("l_leg", 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(hud_used && hud_used.static_inventory)
- for(var/obj/screen/mov_intent/selector in hud_used.static_inventory)
- selector.toggle(src)
+/mob/CanPass(atom/movable/mover, turf/target, height=0)
+ if(height==0)
+ return 1
+ if(istype(mover, /obj/item/projectile) || mover.throwing)
+ return (!density || lying)
+ if(mover.checkpass(PASSMOB))
+ return 1
+ if(buckled == mover)
+ return 1
+ if(ismob(mover))
+ if (mover in buckled_mobs)
+ return 1
+ return (!mover.density || !density || lying)
+
+
+//The byond version of these verbs wait for the next tick before acting.
+// instant verbs however can run mid tick or even during the time between ticks.
+/client/verb/moveup()
+ set name = ".moveup"
+ set instant = 1
+ Move(get_step(mob, NORTH), NORTH)
+
+/client/verb/movedown()
+ set name = ".movedown"
+ set instant = 1
+ Move(get_step(mob, SOUTH), SOUTH)
+
+/client/verb/moveright()
+ set name = ".moveright"
+ set instant = 1
+ Move(get_step(mob, EAST), EAST)
+
+/client/verb/moveleft()
+ set name = ".moveleft"
+ set instant = 1
+ Move(get_step(mob, WEST), WEST)
+
+/client/Northeast()
+ swap_hand()
+ return
+
+
+/client/Southeast()
+ attack_self()
+ return
+
+
+/client/Southwest()
+ if(iscarbon(usr))
+ var/mob/living/carbon/C = usr
+ C.toggle_throw_mode()
+ else
+ usr << "This mob type cannot throw items."
+ return
+
+
+/client/Northwest()
+ if(!usr.get_active_held_item())
+ usr << "You have nothing to drop in your hand!"
+ return
+ usr.drop_item()
+
+//This gets called when you press the delete button.
+/client/verb/delete_key_pressed()
+ set hidden = 1
+
+ if(!usr.pulling)
+ usr << "You are not pulling anything."
+ return
+ usr.stop_pulling()
+
+/client/verb/swap_hand()
+ set category = "IC"
+ set name = "Swap hands"
+
+ if(mob)
+ mob.swap_hand()
+
+/client/verb/attack_self()
+ set hidden = 1
+ if(mob)
+ mob.mode()
+ return
+
+
+/client/verb/drop_item()
+ set hidden = 1
+ if(!iscyborg(mob))
+ mob.drop_item_v()
+ return
+
+
+/client/Center()
+ if(isobj(mob.loc))
+ var/obj/O = mob.loc
+ if(mob.canmove)
+ return O.relaymove(mob, 0)
+ 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.setDir(direct)
+ else
+ mob.control_object.loc = get_step(mob.control_object,direct)
+ return
+
+
+/client/Move(n, direct)
+ if(world.time < move_delay)
+ return 0
+ move_delay = world.time+world.tick_lag //this is here because Move() can now be called mutiple times per tick
+ if(!mob || !mob.loc)
+ return 0
+ 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(mob.force_moving)
+ return 0
+ if(isliving(mob))
+ var/mob/living/L = mob
+ if(L.incorporeal_move) //Move though walls
+ Process_Incorpmove(direct)
+ return 0
+
+ if(mob.remote_control) //we're controlling something, our movement is relayed to it
+ return mob.remote_control.relaymove(mob, direct)
+
+ if(isAI(mob))
+ return AIMove(n,direct,mob)
+
+ if(Process_Grab()) //are we restrained by someone's grip?
+ return
+
+ if(mob.buckled) //if we're buckled to something, tell it we moved.
+ return mob.buckled.relaymove(mob, direct)
+
+ if(!mob.canmove)
+ 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(!mob.Process_Spacemove(direct))
+ return 0
+
+ //We are now going to move
+ moving = 1
+ move_delay = mob.movement_delay() + world.time
+
+ if(mob.confused)
+ if(mob.confused > 40)
+ step(mob, pick(cardinal))
+ else if(prob(mob.confused * 1.5))
+ step(mob, angle2dir(dir2angle(direct) + pick(90, -90)))
+ else if(prob(mob.confused * 3))
+ step(mob, angle2dir(dir2angle(direct) + pick(45, -45)))
+ else
+ step(mob, direct)
+ else
+ . = ..()
+
+ moving = 0
+ if(mob && .)
+ if(mob.throwing)
+ mob.throwing.finalize(FALSE)
+
+ for(var/obj/O in mob)
+ O.on_mob_move(direct, src)
+
+ return .
+
+
+///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.pulledby)
+ if(mob.incapacitated(ignore_restraints = 1))
+ move_delay = world.time + 10
+ return 1
+ else if(mob.restrained(ignore_grab = 1))
+ move_delay = world.time + 10
+ src << "You're restrained! You can't move!"
+ return 1
+ else
+ return mob.resist_grab(1)
+
+
+///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.loc = get_step(L, direct)
+ L.setDir(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.loc = locate(locx,locy,mobloc.z)
+ var/limit = 2//For only two trailing shadows.
+ for(var/turf/T in getline(mobloc, L.loc))
+ new /obj/effect/overlay/temp/dir_setting/ninja/shadow(T, L.dir)
+ limit--
+ if(limit<=0)
+ break
+ else
+ new /obj/effect/overlay/temp/dir_setting/ninja/shadow(mobloc, L.dir)
+ L.loc = get_step(L, direct)
+ L.setDir(direct)
+ if(3) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
+ var/turf/open/floor/stepTurf = get_step(L, direct)
+ for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
+ L << "[S] bars your passage!"
+ if(isrevenant(L))
+ var/mob/living/simple_animal/revenant/R = L
+ R.reveal(20)
+ R.stun(20)
+ return
+ if(stepTurf.flags & NOJAUNT)
+ L << "Holy energies block your path."
+ else
+ L.loc = get_step(L, direct)
+ L.setDir(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)
+ if(backup.newtonian_move(turn(movement_dir, 180))) //You're pushing off something movable, so it moves
+ src << "You push off of [backup] to propel yourself."
+ 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(isspaceturf(turf))
+ 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()
+ return has_gravity()
+
+/mob/proc/mob_negates_gravity()
+ return 0
+
+//moves the mob/object we're pulling
+/mob/proc/Move_Pulled(atom/A)
+ if(!pulling)
+ return
+ if(pulling.anchored || !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
+ step(pulling, get_dir(pulling.loc, A))
+
+
+/mob/proc/slip(s_amount, w_amount, obj/O, lube)
+ return
+
+/mob/proc/update_gravity()
+ return
+
+//bodypart selection - Cyberboss
+//8 toggles through head - eyes - mouth
+//4: r-arm 5: chest 6: l-arm
+//1: r-leg 2: groin 3: l-leg
+
+/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("head")
+ next_in_line = "eyes"
+ if("eyes")
+ next_in_line = "mouth"
+ else
+ next_in_line = "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/obj/screen/zone_sel/selector = mob.hud_used.zone_select
+ selector.set_selected_zone("r_arm", 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("chest", mob)
+
+/client/verb/body_l_arm()
+ set name = "body-l-arm"
+ set hidden = 1
+
+ if(!check_has_body_select())
+ return
+
+ var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
+ selector.set_selected_zone("l_arm", mob)
+
+/client/verb/body_r_leg()
+ set name = "body-r-leg"
+ set hidden = 1
+
+ if(!check_has_body_select())
+ return
+
+ var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
+ selector.set_selected_zone("r_leg", 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("groin", mob)
+
+/client/verb/body_l_leg()
+ set name = "body-l-leg"
+ set hidden = 1
+
+ if(!check_has_body_select())
+ return
+
+ var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
+ selector.set_selected_zone("l_leg", 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(hud_used && hud_used.static_inventory)
+ for(var/obj/screen/mov_intent/selector in hud_used.static_inventory)
+ selector.toggle(src)