diff --git a/baystation12.dme b/baystation12.dme index 85fa384377..e5ad012bbc 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1290,6 +1290,9 @@ #include "code\modules\surgery\ribcage.dm" #include "code\modules\surgery\robolimbs.dm" #include "code\modules\surgery\surgery.dm" +#include "code\modules\vehicles\cargo_train.dm" +#include "code\modules\vehicles\train.dm" +#include "code\modules\vehicles\vehicle.dm" #include "code\modules\virus2\analyser.dm" #include "code\modules\virus2\antibodies.dm" #include "code\modules\virus2\centrifuge.dm" diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 7d4db127c8..f8047e5f2e 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -100,7 +100,8 @@ /obj/machinery/bot, /obj/machinery/door, /obj/machinery/telecomms, - /obj/machinery/mecha_part_fabricator + /obj/machinery/mecha_part_fabricator, + /obj/vehicle ) @@ -200,7 +201,7 @@ access = list(access_maint_tunnels, access_syndicate, access_external_airlocks) origin_tech = "syndicate=3" var/registered_user=null - + /obj/item/weapon/card/id/syndicate/New(mob/user as mob) ..() if(!isnull(user)) // Runtime prevention on laggy starts or where users log out because of lag at round start. @@ -208,7 +209,7 @@ else registered_name = "Agent Card" assignment = "Agent" - name = "[registered_name]'s ID Card ([assignment])" + name = "[registered_name]'s ID Card ([assignment])" /obj/item/weapon/card/id/syndicate/afterattack(var/obj/item/weapon/O as obj, mob/user as mob, proximity) if(!proximity) return @@ -239,7 +240,7 @@ registered_user = user else if(!registered_user || registered_user == user) - if(!registered_user) registered_user = user // + if(!registered_user) registered_user = user // switch(alert("Would you like to display the ID, or retitle it?","Choose.","Rename","Show")) if("Rename") diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 7b254cf890..2925449d0e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -440,12 +440,17 @@ return // called when something steps onto a human -// this could be made more general, but for now just handle mulebot +// this handles mulebots and vehicles /mob/living/carbon/human/HasEntered(var/atom/movable/AM) - var/obj/machinery/bot/mulebot/MB = AM - if(istype(MB)) + if(istype(AM, /obj/machinery/bot/mulebot)) + var/obj/machinery/bot/mulebot/MB = AM MB.RunOver(src) + if(istype(AM, /obj/vehicle)) + var/obj/vehicle/V = AM + V.RunOver(src) + + //gets assignment from ID or ID inside PDA or PDA itself //Useful when player do something with computers /mob/living/carbon/human/proc/get_assignment(var/if_no_id = "No id", var/if_no_job = "No job") diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm new file mode 100644 index 0000000000..559c9dbc35 --- /dev/null +++ b/code/modules/vehicles/cargo_train.dm @@ -0,0 +1,266 @@ +/obj/vehicle/train/cargo/engine + name = "cargo train tug" + icon = 'icons/obj/aibots.dmi' + icon_state = "mulebot1" //mulebot icons until I get some proper icons + on = 1 + powered = 1 + locked = 0 + + load_item_visible = 1 + load_offset_x = 0 + load_offset_y = 9 + + var/car_limit = 3 //how many cars an engine can pull before performance degrades + var/lead_engine = 0 //if the engine is the lead engine - set automatically + +/obj/vehicle/train/cargo/trolley + name = "cargo train trolley" + icon = 'icons/obj/aibots.dmi' + icon_state = "mulebot0" + anchored = 0 + passenger_allowed = 0 + locked = 0 + + load_item_visible = 1 + load_offset_x = 0 + load_offset_y = 9 + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/train/cargo/engine/New() + ..() + cell = new /obj/item/weapon/cell/high + verbs -= /atom/movable/verb/pull + +/obj/vehicle/train/cargo/engine/initialize() + ..() + if(!lead) + lead_engine = 1 + +/obj/vehicle/train/cargo/engine/Move() + if(on && cell.charge < power_use) + turn_off() + update_stats() + if(load && lead_engine) + load << "The drive motor briefly whines, then crawls to a stop." + if(lead_engine && !on) + return 0 + + return ..() + +/obj/vehicle/train/cargo/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(open && istype(W, /obj/item/weapon/wirecutters)) + passenger_allowed = !passenger_allowed + user.visible_message("[user] [passenger_allowed ? "cuts" : "mends"] a cable in [src].","You [passenger_allowed ? "cut" : "mend"] the load limiter cable.") + else + ..() + +/obj/vehicle/train/cargo/update_icon() + if(open) + icon_state = "mulebot-hatch" + else + icon_state = initial(icon_state) + +/obj/vehicle/train/cargo/engine/Emag(mob/user as mob) + ..() + flick("mulebot-emagged", src) + +/obj/vehicle/train/cargo/trolley/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + return + +/obj/vehicle/train/cargo/engine/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + ..() + update_stats() + +/obj/vehicle/train/cargo/engine/remove_cell(var/mob/living/carbon/human/H) + ..() + update_stats() + +/obj/vehicle/train/cargo/engine/Bump(atom/Obstacle) + var/obj/machinery/door/D = Obstacle + var/mob/living/carbon/human/H = load + if(istype(D) && istype(H)) + D.Bumped(H) //a little hacky, but hey, it works, and repects access rights + + ..() + +//------------------------------------------- +// Train procs +//------------------------------------------- +/obj/vehicle/train/cargo/RunOver(var/mob/living/carbon/human/H) + var/list/parts = list("head", "chest", "l_leg", "r_leg", "l_arm", "r_arm") + + H.apply_effects(5, 5) + for(var/i = 0, i < rand(1,3), i++) + H.apply_damage(rand(1,5), BRUTE, pick(parts)) + +/obj/vehicle/train/cargo/trolley/RunOver(var/mob/living/carbon/human/H) + ..() + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + +/obj/vehicle/train/cargo/engine/RunOver(var/mob/living/carbon/human/H) + ..() + + if(lead_engine && istype(load, /mob/living/carbon/human)) + var/mob/living/carbon/human/D = load + D << "\red \b You ran over [H]!" + visible_message("\red \The [src] ran over [H]!") + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey]), driven by [D.name] ([D.ckey])") + else + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + + +//------------------------------------------- +// Interaction procs +//------------------------------------------- +/obj/vehicle/train/cargo/trolley/verb/rotate() + set name = "Rotate" + set category = "Object" + set src in view(1) + + if(anchored) + usr << "You cannot turn the trolley while it is latched onto a train." + return + + var/cur_dir = null + switch(dir) + if(NORTH) + cur_dir = "North" + if(SOUTH) + cur_dir = "South" + if(EAST) + cur_dir = "East" + if(WEST) + cur_dir = "West" + + var/new_dir = input("Select a new direction:", "Rotate", cur_dir) in list("North", "South", "East", "West") + + switch(new_dir) + if("North") + dir = NORTH + if("South") + dir = SOUTH + if("East") + dir = EAST + if("West") + dir = WEST + + +/obj/vehicle/train/cargo/engine/relaymove(mob/user, direction) + if(user != load) + return 0 + + if(lead_engine) + if(direction == reverse_direction(dir)) + return 0 + if(Move(get_step(src, direction))) + return 1 + return 0 + else + return ..() + + +/obj/vehicle/train/cargo/engine/verb/start_engine() + set name = "Start engine" + set category = "Object" + set src in view(1) + + if(on) + usr << "The engine is already running." + return + + if(turn_on()) + usr << "You start [src]." + else + if(cell.charge < power_use) + usr << "[src] is out of power." + else + usr << "[src] won't start." + +//------------------------------------------- +// Latching/unlatching procs +//------------------------------------------- +/obj/vehicle/train/cargo/trolley/latch(var/obj/vehicle/train/T) + if(..()) + //if this is a trolley, and is now part of a train, anchor it so it cant be pushed around + if(lead || tow) + anchored = 1 + return 1 + else + return 0 + +/obj/vehicle/train/cargo/trolley/unlatch() + if(..()) + //if this carraige isn't part of a train anymore; unanchor it so it can be pushed around + if(!tow && !lead) + anchored = 0 + return 1 + else + return 0 + + +/obj/vehicle/train/cargo/engine/latch(var/obj/vehicle/train/T) + if(..()) + //check if this is not the lead engine + if(lead) + lead_engine = 0 + return 1 + else + return 0 + +/obj/vehicle/train/cargo/engine/unlatch() + if(..()) + //check if this is now the lead engine + if(!lead) + lead_engine = 1 + return 1 + else + return 0 + + +//------------------------------------------- +// Loading/unloading procs +//------------------------------------------- +/obj/vehicle/train/cargo/trolley/load(var/atom/movable/C) + if(ismob(C) && !passenger_allowed) + return 0 + if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !ismob(C)) + return 0 + + return ..() + +/obj/vehicle/train/cargo/engine/load(var/atom/movable/C) + if(!ismob(C)) + return 0 + + return ..() + + +//------------------------------------------------------- +// Stat update procs +// +// Update the trains stats for speed calculations. +// The longer the train, the slower it will go. car_limit +// sets the max number of cars one engine can pull at +// full speed. Adding more cars beyond this will slow the +// train proportionate to the length of the train. Adding +// more engines increases this limit by car_limit per +// engine. +//------------------------------------------------------- +/obj/vehicle/train/cargo/engine/update_train_stats() + ..() + + speed_calc() + + if(!lead) //check if this is the lead engine + lead_engine = 1 + +/obj/vehicle/train/cargo/engine/proc/speed_calc() + if(!lead_engine) + move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind + else + move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains + move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) + move_delay += config.run_speed //base reference speed + move_delay *= 0.75 //makes cargo trains 25% faster than running when not overweight \ No newline at end of file diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm new file mode 100644 index 0000000000..521fde0cd7 --- /dev/null +++ b/code/modules/vehicles/train.dm @@ -0,0 +1,200 @@ +/obj/vehicle/train + name = "train" + dir = 4 + + move_delay = 1 + + health = 100 + maxhealth = 100 + fire_dam_coeff = 0.7 + brute_dam_coeff = 0.5 + + var/passenger_allowed = 1 + + var/active_engines = 0 + var/train_length = 0 + + var/obj/vehicle/train/lead + var/obj/vehicle/train/tow + + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/train/initialize() + for(var/obj/vehicle/train/T in orange(1, src)) + latch(T) + +/obj/vehicle/train/Move() + var/old_loc = get_turf(src) + if(..()) + if(tow) + tow.Move(old_loc) + return 1 + else + return 0 + +/obj/vehicle/train/Bump(atom/Obstacle) + if(!istype(Obstacle, /atom/movable) || !anchored) + return + + var/atom/movable/A = Obstacle + + if(!A.anchored) + var/turf/T = get_step(A, dir) + if(isturf(T)) + if(!emagged) //if not emagged, bump people away, else just run over them + A.Move(T) + else if(!ismob(A)) //always bump objects even if emagged + A.Move(T) + + if(istype(A, /mob/living)) + var/mob/living/M = A + if(istype(load, /mob/living/carbon/human)) + load << "\red You hit [M]!" + visible_message("\red [src] knocks over [M]!") + M.apply_effects(5, 5) //knock people down if you hit them + if(emagged) //and do damage if it's emagged + M.apply_damages(5 * train_length / move_delay) // according to how fast the train is going and how heavy it is + + +//------------------------------------------- +// Interaction procs +//------------------------------------------- +/obj/vehicle/train/relaymove(mob/user, direction) + var/turf/T = get_step_to(src, get_step(src, direction)) + if(!T) + user << "You can't find a clear area to step onto." + return 0 + + if(user != load) + if(user in src) //for handling players stuck in src + unload(user, direction, 1) + return 1 + return 0 + + unload(user, direction) + + user << "\blue You climb down from [src]." + + return 1 + +/obj/vehicle/train/MouseDrop_T(var/atom/movable/C, mob/user as mob) + if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr) || !user.Adjacent(C)) + return + + if(istype(C,/obj/vehicle/train)) + if(latch(C)) + user << "\blue You successfully connect the [C] to [src]." + else + user << "\red You were unable to connect the [C] to [src]." + return + + if(!load(C)) + user << "\red You were unable to load [C] on [src]." + +/obj/vehicle/train/attack_hand(mob/user as mob) + if(!user.canmove || user.stat || user.restrained() || !Adjacent(user)) + return 0 + + if(user != load && (user in src)) + unload(user, null, 1) //for handling players stuck in src + else if(load) + unload(user) //unload if loaded + else if(!load) + load(user) //else try climbing on board + else + return 0 + +/obj/vehicle/train/verb/unlatch_v() + set name = "Unlatch" + set category = "Object" + set src in view(1) + + if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) + return + + if(unlatch()) + usr << "\blue You unlatch [src]." + else + usr << "\red [src] is already unlatched." + + +//------------------------------------------- +// Latching/unlatching procs +//------------------------------------------- +/obj/vehicle/train/proc/latch(var/obj/vehicle/train/T) + if(!istype(T) || !Adjacent(T)) + return 0 + + if(dir != T.dir) //cars need to be inline to latch + return 0 + + var/T_dir = get_dir(src, T) + + if(dir & T_dir) //if car is ahead + if(!lead && !T.tow) + lead = T + T.tow = src + else + return 0 + else if(reverse_direction(dir) & T_dir) //else if car is behind + if(!tow && !T.lead) + tow = T + T.lead = src + else + return 0 + else + return 0 + + update_stats() + + return 1 + +/obj/vehicle/train/proc/unlatch() + if(!lead && !tow) + return 0 + + if(tow) + tow.lead = null + tow.update_stats() + tow = null + if(lead) + lead.tow = null + lead.update_stats() + lead = null + + update_stats() + + return 1 + + + +//------------------------------------------------------- +// Stat update procs +// +// Used for updating the stats for how long the train is. +// These are useful for calculating speed based on the +// size of the train, to limit super long trains. +//------------------------------------------------------- +/obj/vehicle/train/update_stats() + if(!tow) + update_train_stats() + else + return tow.update_stats() + +/obj/vehicle/train/proc/update_train_stats() + if(powered && on) + active_engines = 1 //increment active engine count if this is a running engine + else + active_engines = 0 + + train_length = 1 + + if(tow) + active_engines += tow.active_engines + train_length += tow.train_length + + //update the next section of train ahead of us + if(lead) + lead.update_train_stats() \ No newline at end of file diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm new file mode 100644 index 0000000000..6ae7f3ee14 --- /dev/null +++ b/code/modules/vehicles/vehicle.dm @@ -0,0 +1,378 @@ +/obj/vehicle + name = "vehicle" + icon = 'icons/obj/vehicles.dmi' + layer = MOB_LAYER + density = 1 + anchored = 1 + animate_movement=1 + luminosity = 3 + + var/attack_log = null + var/on = 0 + var/health = 0 //do not forget to set health for your vehicle! + var/maxhealth = 0 + var/fire_dam_coeff = 1.0 + var/brute_dam_coeff = 1.0 + var/open = 0 //Maint panel + var/locked = 1 + var/stat = 0 + var/emagged = 0 + var/powered = 0 //set if vehicle is powered and should use fuel when moving + var/move_delay = 1 //set this to limit the speed of the vehicle + + var/obj/item/weapon/cell/cell + var/power_use = 5 //set this to adjust the amount of power the vehicle uses per move + + var/atom/movable/load //all vehicles can take a load, since they should all be a least drivable + var/load_item_visible = 1 //set if the loaded item should be overlayed on the vehicle sprite + var/load_offset_x = 0 //pixel_x offset for item overlay + var/load_offset_y = 0 //pixel_y offset for item overlay + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/New() + ..() + //spawn the cell you want in each vehicle + +/obj/vehicle/Move() + if(world.timeofday > l_move_time + move_delay) + if(on && powered && cell.charge < power_use) + turn_off() + + var/init_anc = anchored + anchored = 0 + if(..()) + if(on && powered) + cell.use(power_use) + anchored = init_anc + + return 1 + else + return 0 + +/obj/vehicle/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/screwdriver)) + if(!locked) + open = !open + update_icon() + user << "Maintenance panel is now [open ? "opened" : "closed"]." + else if(istype(W, /obj/item/weapon/crowbar) && cell && open) + remove_cell(user) + + else if(istype(W, /obj/item/weapon/cell) && !cell && open) + insert_cell(W, user) + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/T = W + if(T.welding) + if(health < maxhealth) + if(open) + health = min(maxhealth, health+10) + user.visible_message("\red [user] repairs [src]!","\blue You repair [src]!") + else + user << "Unable to repair with the maintenance panel closed." + else + user << "[src] does not need a repair." + else + user << "Unable to repair while [src] is off." + else if(istype(W, /obj/item/weapon/card/emag) && !emagged) + Emag(user) + else if(hasvar(W,"force") && hasvar(W,"damtype")) + switch(W.damtype) + if("fire") + health -= W.force * fire_dam_coeff + if("brute") + health -= W.force * brute_dam_coeff + ..() + healthcheck() + else + ..() + +/obj/vehicle/attack_animal(var/mob/living/simple_animal/M as mob) + if(M.melee_damage_upper == 0) return + health -= M.melee_damage_upper + src.visible_message("\red [M] has [M.attacktext] [src]!") + M.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + if(prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + healthcheck() + +/obj/vehicle/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + healthcheck() + +/obj/vehicle/meteorhit() + explode() + return + +/obj/vehicle/blob_act() + src.health -= rand(20,40)*fire_dam_coeff + healthcheck() + return + +/obj/vehicle/ex_act(severity) + switch(severity) + if(1.0) + explode() + return + if(2.0) + health -= rand(5,10)*fire_dam_coeff + health -= rand(10,20)*brute_dam_coeff + healthcheck() + return + if(3.0) + if (prob(50)) + health -= rand(1,5)*fire_dam_coeff + health -= rand(1,5)*brute_dam_coeff + healthcheck() + return + return + +/obj/vehicle/emp_act(severity) + var/was_on = on + stat |= EMPED + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + + spawn(10) + pulse2.delete() + if(on) + turn_off() + spawn(severity*300) + stat &= ~EMPED + if(was_on) + turn_on() + +/obj/vehicle/attack_ai(mob/user as mob) + return + + +//------------------------------------------- +// Vehicle procs +//------------------------------------------- +/obj/vehicle/proc/turn_on() + if(stat) + return 0 + if(powered && cell.charge < power_use) + return 0 + on = 1 + luminosity = initial(luminosity) + update_icon() + return 1 + +/obj/vehicle/proc/turn_off() + on = 0 + luminosity = 0 + update_icon() + +/obj/vehicle/proc/Emag(mob/user as mob) + emagged = 1 + + if(locked) + locked = 0 + user << "You bypass [src]'s controls." + +/obj/vehicle/proc/explode() + src.visible_message("\red [src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/rods(Tsec) + new /obj/item/weapon/cable_coil/cut(Tsec) + + if(cell) + cell.loc = Tsec + cell.update_icon() + cell = null + + unload() + + new /obj/effect/gibspawner/robot(Tsec) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + + del(src) + +/obj/vehicle/proc/healthcheck() + if(health <= 0) + explode() + +/obj/vehicle/proc/powercheck() + if(!cell && !powered) + return + + if(!cell && powered) + turn_off() + return + + if(cell.charge < power_use) + turn_off() + return + + if(cell && powered) + turn_on() + return + +/obj/vehicle/proc/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + if(cell) + return + if(!istype(C)) + return + + H.drop_from_inventory(C) + cell = C + C.loc = null //this wont be GC'd since it's referrenced above + powercheck() + usr << "You install [C] in [src]." + +/obj/vehicle/proc/remove_cell(var/mob/living/carbon/human/H) + if(!cell) + return + + usr << "You remove [cell] from [src]." + cell.loc = get_turf(H) + cell = null + powercheck() + +/obj/vehicle/proc/RunOver(var/mob/living/carbon/human/H) + return //write specifics for different vehicles + +//------------------------------------------- +// Loading/unloading procs +// +// Set specific item restriction checks in +// the vehicle load() definition before +// calling this parent proc. +//------------------------------------------- +/obj/vehicle/proc/load(var/atom/movable/C) + //define allowed items for loading in specific vehicle definitions + + if(!isturf(C.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly. + return 0 + if(load || C.anchored) + return 0 + + // if a create/closet, close before loading + var/obj/structure/closet/crate = C + if(istype(crate)) + crate.close() + + C.loc = loc + sleep(2) + if(C.loc != loc) //To prevent you from going onto more than one train. + return 0 + C.loc = src + + load = C + + if(load_item_visible) + C.pixel_x += load_offset_x + C.pixel_y += load_offset_y + C.layer = layer + + overlays += C + + //we can set these back now since we have already cloned the icon into the overlay + C.pixel_x = initial(C.pixel_x) + C.pixel_y = initial(C.pixel_y) + C.layer = initial(C.layer) + + if(ismob(C)) + var/mob/M = C + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + + return 1 + + +/obj/vehicle/proc/unload(var/mob/user, var/direction, var/exception = 0) + if(!load) + // in case non-load items end up in contents, dump everything else too + for(var/atom/movable/AM in src) + AM.loc = get_turf(src) + AM.pixel_x = initial(AM.pixel_x) + AM.pixel_y = initial(AM.pixel_y) + AM.layer = initial(AM.layer) + if(ismob(AM)) + var/mob/M = AM + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + return 0 + + var/turf/dest = null + + //find a turf to unload to + if(direction) //if direction specified, unload in that direction + dest = get_step(src, direction) + else if(user) //if a user has unloaded the vehicle, unload at their feet + dest = get_turf(user) + + if(!dest) + dest = get_step_to(src, get_step(src, turn(dir, 90))) //try unloading to the side of the vehicle first if neither of the above are present + + //if these all result in the same turf as the vehicle or nullspace, pick a new turf with open space + if(!dest || dest == get_turf(src)) + var/list/options = new() + for(var/test_dir in alldirs) + var/new_dir = get_step_to(src, get_step(src, test_dir)) + if(new_dir) + options += new_dir + if(options.len) + dest = pick(options) + else + dest = get_turf(src) //otherwise just dump it on the same turf as the vehicle + + if(!isturf(dest)) //if there still is nowhere to unload, cancel out since the vehicle is probably in nullspace + return 0 + + + if(exception) //for handling any players that end up in src.contents that are trying to climb off + user.loc = dest + user.pixel_x = initial(user.pixel_x) + user.pixel_y = initial(user.pixel_y) + user.layer = initial(user.layer) + + if(ismob(user)) + var/mob/M = user + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + + src.contents -= user + + return 1 + + overlays.Cut() + + load.loc = dest + + /* + load.pixel_x = initial(load.pixel_x) + load.pixel_y = initial(load.pixel_y) + load.layer = initial(load.layer) + */ + + if(ismob(load)) + var/mob/M = load + if(M.client) + M.client.perspective = MOB_PERSPECTIVE + M.client.eye = src + + load = null + + unload() //recursive check for anything left in contents + + return 1 + + +//------------------------------------------------------- +// Stat update procs +//------------------------------------------------------- +/obj/vehicle/proc/update_stats() + return \ No newline at end of file