From d4a6cdc0e80cd2ccf71b26f37e7b57449cae5bad Mon Sep 17 00:00:00 2001 From: kevinz000 Date: Sat, 18 Feb 2017 13:39:35 -0800 Subject: [PATCH] Adds riding on other carbon mobs rscadd: You can now ride piggyback on other human beings, as a human being! To do so they must grab you aggressively and you must climb on without outside assistance without being restrained or incapacitated in any manner. They must also not be restrained or incapacitated in any manner. rscadd: If someone is riding on you and you want them to get off, disarm them to instantly floor them for a few seconds! It's pretty rude, though. --- code/datums/riding.dm | 153 ++- code/modules/mob/living/carbon/human/human.dm | 36 + .../mob/living/carbon/human/human_defense.dm | 3 + .../mob/living/carbon/human/human_defines.dm | 3 + .../mob/living/carbon/human/human_movement.dm | 3 +- code/modules/mob/living/emote.dm | 8 +- .../modules/mob/living/silicon/robot/robot.dm | 68 +- .../mob/living/simple_animal/simple_animal.dm | 1 - code/modules/mob/mob.dm | 7 +- code/modules/mob/mob_defines.dm | 4 +- code/modules/mob/mob_movement.dm | 870 +++++++++--------- 11 files changed, 630 insertions(+), 526 deletions(-) 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)