From 96d3d361d0fccb172b36fd50e7db729f08521b35 Mon Sep 17 00:00:00 2001 From: Neerti Date: Sun, 14 Jan 2018 15:58:15 -0500 Subject: [PATCH] Adds Boats, Ports /TG/ Buckling (#4527) * Adds Boats, Ports /TG/ Buckling * Travis Appeasement * Changelog --- code/ATMOSPHERICS/he_pipes.dm | 25 +- code/__defines/_planes+layers.dm | 18 ++ code/__defines/lighting.dm | 2 +- code/__defines/misc.dm | 12 +- code/_helpers/mobs.dm | 2 +- code/datums/riding.dm | 224 ++++++++++++++++++ code/game/area/areas.dm | 2 +- code/game/atoms.dm | 10 + code/game/atoms_movable.dm | 2 + code/game/jobs/job_controller.dm | 2 +- code/game/mecha/equipment/tools/tools.dm | 2 +- code/game/objects/buckling.dm | 113 ++++++--- .../objects/items/weapons/material/knives.dm | 1 + code/game/objects/items/weapons/traps.dm | 14 +- code/game/objects/items/weapons/weaponry.dm | 34 +-- code/game/objects/structures/bonfire.dm | 12 +- .../structures/crates_lockers/crates.dm | 2 +- code/game/objects/structures/electricchair.dm | 14 +- code/game/objects/structures/janicart.dm | 57 +++-- code/game/objects/structures/simple_doors.dm | 4 +- .../stool_bed_chair_nest/alien_nests.dm | 8 +- .../structures/stool_bed_chair_nest/bed.dm | 24 +- .../structures/stool_bed_chair_nest/chairs.dm | 78 +++--- .../stool_bed_chair_nest/wheelchair.dm | 76 +++--- code/game/supplyshuttle.dm | 2 +- code/game/turfs/simulated/wall_types.dm | 8 +- code/game/turfs/simulated/water.dm | 6 + .../hydroponics/spreading/spreading_growth.dm | 14 +- .../spreading/spreading_response.dm | 44 ++-- code/modules/materials/material_recipes.dm | 3 + code/modules/materials/material_sheets.dm | 39 ++- code/modules/materials/materials.dm | 10 +- code/modules/mob/inventory.dm | 4 + .../mob/living/carbon/human/inventory.dm | 7 + code/modules/mob/living/carbon/resist.dm | 2 +- code/modules/mob/living/living.dm | 11 +- code/modules/mob/living/silicon/robot/life.dm | 5 +- .../mob/living/simple_animal/slime/combat.dm | 11 +- code/modules/mob/mob_movement.dm | 22 +- code/modules/shieldgen/directional_shield.dm | 2 +- code/modules/vehicles/bike.dm | 5 +- code/modules/vehicles/boat.dm | 82 +++++++ code/modules/vehicles/cargo_train.dm | 11 +- code/modules/vehicles/train.dm | 4 +- code/modules/vehicles/vehicle.dm | 147 ++++++++---- html/changelogs/Neerti - Boats.yml | 36 +++ icons/mob/items/lefthand.dmi | Bin 66902 -> 67233 bytes icons/mob/items/righthand.dmi | Bin 67257 -> 67545 bytes icons/obj/64x32.dmi | Bin 0 -> 2849 bytes icons/obj/vehicles.dmi | Bin 10594 -> 10805 bytes icons/obj/vehicles_36x32.dmi | Bin 0 -> 9351 bytes polaris.dme | 2 + 52 files changed, 888 insertions(+), 327 deletions(-) create mode 100644 code/datums/riding.dm create mode 100644 code/modules/vehicles/boat.dm create mode 100644 html/changelogs/Neerti - Boats.yml create mode 100644 icons/obj/64x32.dmi create mode 100644 icons/obj/vehicles_36x32.dmi diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/he_pipes.dm index 58c2ee3a2d..aa474a8572 100644 --- a/code/ATMOSPHERICS/he_pipes.dm +++ b/code/ATMOSPHERICS/he_pipes.dm @@ -71,20 +71,23 @@ else if(istype(loc, /turf/space/)) parent.radiate_heat_to_space(surface, 1) - if(buckled_mob) - var/hc = pipe_air.heat_capacity() - var/avg_temp = (pipe_air.temperature * hc + buckled_mob.bodytemperature * 3500) / (hc + 3500) - pipe_air.temperature = avg_temp - buckled_mob.bodytemperature = avg_temp + if(has_buckled_mobs()) + for(var/M in buckled_mobs) + var/mob/living/L = M - var/heat_limit = 1000 + var/hc = pipe_air.heat_capacity() + var/avg_temp = (pipe_air.temperature * hc + L.bodytemperature * 3500) / (hc + 3500) + pipe_air.temperature = avg_temp + L.bodytemperature = avg_temp - var/mob/living/carbon/human/H = buckled_mob - if(istype(H) && H.species) - heat_limit = H.species.heat_level_3 + var/heat_limit = 1000 - if(pipe_air.temperature > heat_limit + 1) - buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BP_TORSO, used_weapon = "Excessive Heat") + var/mob/living/carbon/human/H = L + if(istype(H) && H.species) + heat_limit = H.species.heat_level_3 + + if(pipe_air.temperature > heat_limit + 1) + L.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BP_TORSO, used_weapon = "Excessive Heat") //fancy radiation glowing if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //start glowing at 500K diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm index 129236125c..b58a50c05a 100644 --- a/code/__defines/_planes+layers.dm +++ b/code/__defines/_planes+layers.dm @@ -52,3 +52,21 @@ What is the naming convention for planes or layers? #define OPENSPACE_PLANE -25 // /turf/simulated/open will use OPENSPACE_PLANE + z (Valid z's being 2 thru 17) #define OVER_OPENSPACE_PLANE -7 + + +// Now for the regular layers. Try to keep these in order, from lowest to highest numbers, please. + +//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define +#define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6 +//#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define +#define DOOR_CLOSED_LAYER 3.1 //Above most items if closed + +#define BELOW_MOB_LAYER 3.9 +//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define +#define ABOVE_MOB_LAYER 4.1 + +//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define +#define LIGHTING_LAYER 11 +#define HUD_LAYER 20 //Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots) +#define OBFUSCATION_LAYER 21 //Where images covering the view for eyes are put +#define SCREEN_LAYER 22 //Mob HUD/effects layer \ No newline at end of file diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm index 30f2dac84d..6b05896b8d 100644 --- a/code/__defines/lighting.dm +++ b/code/__defines/lighting.dm @@ -9,7 +9,7 @@ #define LIGHTING_LAMBERTIAN 0 // use lambertian shading for light sources #define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone -#define LIGHTING_LAYER 10 // drawing layer for lighting overlays +//#define LIGHTING_LAYER 10 // drawing layer for lighting overlays #define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects #define LIGHTING_ICON_STATE_DARK "soft_dark" // Change between "soft_dark" and "dark" to swap soft darkvision diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 9b9bc8cb14..3a8ee870e5 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -121,14 +121,6 @@ //Area flags, possibly more to come #define RAD_SHIELDED 1 //shielded from radiation, clearly -// Custom layer definitions, supplementing the default TURF_LAYER, MOB_LAYER, etc. -#define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6 -#define DOOR_CLOSED_LAYER 3.1 //Above most items if closed -#define LIGHTING_LAYER 11 -#define HUD_LAYER 20 //Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots) -#define OBFUSCATION_LAYER 21 //Where images covering the view for eyes are put -#define SCREEN_LAYER 22 //Mob HUD/effects layer - // Convoluted setup so defines can be supplied by Bay12 main server compile script. // Should still work fine for people jamming the icons into their repo. #ifndef CUSTOM_ITEM_OBJ @@ -155,6 +147,10 @@ #define MAT_PHORON "phoron" #define MAT_DIAMOND "diamond" #define MAT_SNOW "snow" +#define MAT_WOOD "wood" +#define MAT_LOG "log" +#define MAT_SIFWOOD "alien wood" +#define MAT_SIFLOG "alien log" #define SHARD_SHARD "shard" #define SHARD_SHRAPNEL "shrapnel" diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 1dffebf607..a9939b0ecb 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -5,7 +5,7 @@ return occupant /obj/vehicle/train/get_mob() - return buckled_mob + return buckled_mobs /mob/get_mob() return src diff --git a/code/datums/riding.dm b/code/datums/riding.dm new file mode 100644 index 0000000000..746cc6dcf7 --- /dev/null +++ b/code/datums/riding.dm @@ -0,0 +1,224 @@ +// This is used to make things that are supposed to move while buckled more consistant and easier to handle code-wise. + +/datum/riding + var/next_vehicle_move = 0 // Used for move delays + var/vehicle_move_delay = 2 // Tick delay between movements, lower = faster, higher = slower + var/keytype = null // Can give this a type to require the rider to hold the item type inhand to move the ridden atom. + var/nonhuman_key_exemption = FALSE // If true, nonhumans who can't hold keys don't need them, like borgs and simplemobs. + var/key_name = "the keys" // What the 'keys' for the thing being rided on would be called. + var/atom/movable/ridden = null // The thing that the datum is attached to. + var/only_one_driver = FALSE // If true, only the person in 'front' (first on list of riding mobs) can drive. + +/datum/riding/New(atom/movable/_ridden) + ridden = _ridden + +/datum/riding/Destroy() + ridden = null + return ..() + +/datum/riding/proc/handle_vehicle_layer() + if(ridden.dir != NORTH) + ridden.layer = ABOVE_MOB_LAYER + 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) + +/datum/riding/proc/handle_vehicle_offsets() + var/ridden_dir = "[ridden.dir]" + var/passindex = 0 + if(ridden.has_buckled_mobs()) + for(var/m in ridden.buckled_mobs) + passindex++ + var/mob/living/buckled_mob = m + var/list/offsets = get_offsets(passindex) + var/rider_dir = get_rider_dir(passindex) + buckled_mob.set_dir(rider_dir) + dir_loop: + for(var/offsetdir in offsets) + if(offsetdir == ridden_dir) + var/list/diroffsets = offsets[offsetdir] + buckled_mob.pixel_x = diroffsets[1] + if(diroffsets.len >= 2) + buckled_mob.pixel_y = diroffsets[2] + if(diroffsets.len == 3) + buckled_mob.layer = diroffsets[3] + break dir_loop + +// Override this to set your vehicle's various pixel offsets +/datum/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer) + return list("[NORTH]" = list(0, 0), "[SOUTH]" = list(0, 0), "[EAST]" = list(0, 0), "[WEST]" = list(0, 0)) + +// Override this to set the passengers/riders dir based on which passenger they are. +// ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc. +/datum/riding/proc/get_rider_dir(pass_index) + return ridden.dir + +// KEYS +/datum/riding/proc/keycheck(mob/user) + if(keytype) + if(nonhuman_key_exemption && !ishuman(user)) + return TRUE + + if(user.is_holding_item_of_type(keytype)) + return TRUE + else + return TRUE + return FALSE + +// BUCKLE HOOKS +/datum/riding/proc/restore_position(mob/living/buckled_mob) + if(istype(buckled_mob)) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + buckled_mob.layer = initial(buckled_mob.layer) + +// MOVEMENT +/datum/riding/proc/handle_ride(mob/user, direction) + if(user.incapacitated()) + Unbuckle(user) + return + + if(only_one_driver && ridden.buckled_mobs.len) + var/mob/living/driver = ridden.buckled_mobs[1] + if(driver != user) + to_chat(user, "\The [ridden] can only be controlled by one person at a time, and is currently being controlled by \the [driver].") + return + + if(world.time < next_vehicle_move) + return + next_vehicle_move = world.time + vehicle_move_delay + if(keycheck(user)) + if(!Process_Spacemove(direction) || !isturf(ridden.loc)) + return + step(ridden, direction) + + handle_vehicle_layer() + handle_vehicle_offsets() + else + to_chat(user, "You'll need [key_name] in one of your hands to move \the [ridden].") + +/datum/riding/proc/Unbuckle(atom/movable/M) +// addtimer(CALLBACK(ridden, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE) + spawn(0) + // On /tg/ this uses the fancy CALLBACK system. Not entirely sure why they needed to do so with a duration of 0, + // so if there is a reason, this should replicate it close enough. Hopefully. + ridden.unbuckle_mob(M) + +/datum/riding/proc/Process_Spacemove(direction) + if(ridden.has_gravity()) + return TRUE + + return FALSE + +/datum/riding/space/Process_Spacemove(direction) + return TRUE + + + +// SUBTYPES + +// I'm on a +/datum/riding/boat + keytype = /obj/item/weapon/oar + key_name = "an oar" + nonhuman_key_exemption = TRUE // Borgs can't hold oars. + only_one_driver = TRUE // Would be pretty crazy if five people try to move at the same time. + +/datum/riding/boat/handle_ride(mob/user, direction) + var/turf/next = get_step(ridden, direction) + var/turf/current = get_turf(ridden) + + if(istype(next, /turf/simulated/floor/water) || istype(current, /turf/simulated/floor/water)) //We can move from land to water, or water to land, but not from land to land + ..() + else + to_chat(user, "Boats don't go on land!") + return FALSE + +/datum/riding/boat/small // 'Small' boats can hold up to two people. + +/datum/riding/boat/small/get_offsets(pass_index) // list(dir = x, y, layer) + var/H = 7 // Horizontal seperation. + var/V = 5 // Vertical seperation. + var/O = 2 // Vertical offset. + switch(pass_index) + if(1) // Person in front. + return list( + "[NORTH]" = list( 0, O+V, MOB_LAYER), + "[SOUTH]" = list( 0, O, ABOVE_MOB_LAYER), + "[EAST]" = list( H, O, MOB_LAYER), + "[WEST]" = list(-H, O, MOB_LAYER) + ) + if(2) // Person in back. + return list( + "[NORTH]" = list( 0, O, ABOVE_MOB_LAYER), + "[SOUTH]" = list( 0, O+V, MOB_LAYER), + "[EAST]" = list(-H, O, MOB_LAYER), + "[WEST]" = list( H, O, MOB_LAYER) + ) + else + return null // This will runtime, but we want that since this is out of bounds. + +/datum/riding/boat/small/handle_vehicle_layer() + ridden.layer = ABOVE_MOB_LAYER + +/datum/riding/boat/big // 'Big' boats can hold up to five people. + +/datum/riding/boat/big/get_offsets(pass_index) // list(dir = x, y, layer) + var/H = 12 // Horizontal seperation. Halved when facing up-down. + var/V = 4 // Vertical seperation. + var/O = 7 // Vertical offset. + switch(pass_index) + if(1) // Person in center front, first row. + return list( + "[NORTH]" = list( 0, O+V, MOB_LAYER+0.1), + "[SOUTH]" = list( 0, O-V, MOB_LAYER+0.3), + "[EAST]" = list( H, O, MOB_LAYER+0.1), + "[WEST]" = list(-H, O, MOB_LAYER+0.1) + ) + if(2) // Person in left, second row. + return list( + "[NORTH]" = list( H/2, O, MOB_LAYER+0.2), + "[SOUTH]" = list(-H/2, O, MOB_LAYER+0.2), + "[EAST]" = list( 0, O-V, MOB_LAYER+0.2), + "[WEST]" = list( 0, O+V, MOB_LAYER) + ) + if(3) // Person in right, second row. + return list( + "[NORTH]" = list(-H/2, O, MOB_LAYER+0.2), + "[SOUTH]" = list( H/2, O, MOB_LAYER+0.2), + "[EAST]" = list( 0, O+V, MOB_LAYER), + "[WEST]" = list( 0, O-V, MOB_LAYER+0.2) + ) + if(4) // Person in left, third row. + return list( + "[NORTH]" = list( H/2, O-V, MOB_LAYER+0.3), + "[SOUTH]" = list(-H/2, O+V, MOB_LAYER+0.1), + "[EAST]" = list(-H, O-V, MOB_LAYER+0.2), + "[WEST]" = list( H, O+V, MOB_LAYER) + ) + if(5) // Person in right, third row. + return list( + "[NORTH]" = list(-H/2, O-V, MOB_LAYER+0.3), + "[SOUTH]" = list( H/2, O+V, MOB_LAYER+0.1), + "[EAST]" = list(-H, O+V, MOB_LAYER), + "[WEST]" = list( H, O-V, MOB_LAYER+0.2) + ) + else + return null // This will runtime, but we want that since this is out of bounds. + +/datum/riding/boat/big/handle_vehicle_layer() + ridden.layer = MOB_LAYER+0.4 + +/datum/riding/boat/get_offsets(pass_index) // list(dir = x, y, layer) + return list("[NORTH]" = list(1, 2), "[SOUTH]" = list(1, 2), "[EAST]" = list(1, 2), "[WEST]" = list(1, 2)) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 0eb0321f13..0c5fe0e7de 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -294,7 +294,7 @@ var/list/mob/living/forced_ambiance_list = new for(var/obj/machinery/door/window/temp_windoor in src) temp_windoor.open() -/area/proc/has_gravity() +/area/has_gravity() return has_gravity /area/space/has_gravity() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index dec7ab1ccf..7a027d207b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -519,3 +519,13 @@ its easier to just keep the beam vertical. /atom/proc/InsertedContents() return contents + +/atom/proc/has_gravity(turf/T) + if(!T || !isturf(T)) + T = get_turf(src) + if(istype(T, /turf/space)) // Turf never has gravity + return FALSE + var/area/A = get_area(T) + if(A && A.has_gravity()) + return TRUE + return FALSE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index e0648f8c95..2dba31d578 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -93,6 +93,8 @@ AM.Crossed(src) if(is_new_area && is_destination_turf) destination.loc.Entered(src, origin) + + Moved(origin) return 1 //called when src is thrown into hit_atom diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index a0ac2f646c..c413bfccd4 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -470,7 +470,7 @@ var/global/datum/controller/occupations/job_master H.buckled = W H.update_canmove() W.set_dir(H.dir) - W.buckled_mob = H + W.buckled_mobs |= H W.add_fingerprint(H) if(R) W.color = R.color diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index cc41d779dc..164140583f 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -19,7 +19,7 @@ //loading if(istype(target,/obj)) var/obj/O = target - if(O.buckled_mob) + if(O.has_buckled_mobs()) return if(locate(/mob/living) in O) occupant_message("You can't load living things into the cargo compartment.") diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index dce392e8f7..9b27cdecbd 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -6,26 +6,44 @@ var/buckle_dir = 0 var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1 var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes - var/mob/living/buckled_mob = null +// var/mob/living/buckled_mob = null + var/list/mob/living/buckled_mobs = null //list() + var/max_buckled_mobs = 1 /atom/movable/attack_hand(mob/living/user) . = ..() - if(can_buckle && buckled_mob) - user_unbuckle_mob(user) +// if(can_buckle && buckled_mob) +// user_unbuckle_mob(user) + + if(can_buckle && has_buckled_mobs()) + if(buckled_mobs.len > 1) + var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs + if(user_unbuckle_mob(unbuckled, user)) + return TRUE + else + if(user_unbuckle_mob(buckled_mobs[1], user)) + return TRUE /obj/proc/attack_alien(mob/user as mob) //For calling in the event of Xenomorph or other alien checks. return /obj/attack_robot(mob/living/user) - if(Adjacent(user) && buckled_mob) //Checks if what we're touching is adjacent to us and has someone buckled to it. This should prevent interacting with anti-robot manual valves among other things. + if(Adjacent(user) && has_buckled_mobs()) //Checks if what we're touching is adjacent to us and has someone buckled to it. This should prevent interacting with anti-robot manual valves among other things. return attack_hand(user) //Process as if we're a normal person touching the object. return ..() //Otherwise, treat this as an AI click like usual. /atom/movable/MouseDrop_T(mob/living/M, mob/living/user) . = ..() if(can_buckle && istype(M)) - user_buckle_mob(M, user) + if(user_buckle_mob(M, user)) + return TRUE + +/atom/movable/proc/has_buckled_mobs() + if(!buckled_mobs) + return FALSE + if(buckled_mobs.len) + return TRUE /atom/movable/Destroy() unbuckle_mob() @@ -33,52 +51,81 @@ /atom/movable/proc/buckle_mob(mob/living/M, forced = FALSE, check_loc = TRUE) - if((!can_buckle && !forced) || !istype(M) || M.buckled || M.pinned.len || (buckle_require_restraints && !M.restrained())) - return 0 + if(!buckled_mobs) + buckled_mobs = list() + + if(!istype(M)) + return FALSE + if(check_loc && M.loc != loc) - return 0 - if(buckled_mob) //Handles trying to buckle yourself to the chair when someone is on it - M << "\The [src] already has someone buckled to it." - return 0 + return FALSE + + if((!can_buckle && !forced) || M.buckled || M.pinned.len || (buckled_mobs.len >= max_buckled_mobs) || (buckle_require_restraints && !M.restrained())) + return FALSE + + if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs) //Handles trying to buckle yourself to the chair when someone is on it + to_chat(M, "\The [src] can't buckle anymore people.") + return FALSE M.buckled = src M.facing_dir = null M.set_dir(buckle_dir ? buckle_dir : dir) M.update_canmove() M.update_floating( M.Check_Dense_Object() ) - buckled_mob = M +// buckled_mob = M + buckled_mobs |= M post_buckle_mob(M) - return 1 + return TRUE + +/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE) + if(!buckled_mob) // If we didn't get told which mob needs to get unbuckled, just assume its the first one on the list. + if(has_buckled_mobs()) + buckled_mob = buckled_mobs[1] + else + return -/atom/movable/proc/unbuckle_mob() if(buckled_mob && buckled_mob.buckled == src) . = buckled_mob buckled_mob.buckled = null buckled_mob.anchored = initial(buckled_mob.anchored) buckled_mob.update_canmove() buckled_mob.update_floating( buckled_mob.Check_Dense_Object() ) - buckled_mob = null + // buckled_mob = null + buckled_mobs -= buckled_mob post_buckle_mob(.) +/atom/movable/proc/unbuckle_all_mobs(force = FALSE) + if(!has_buckled_mobs()) + return + for(var/m in buckled_mobs) + unbuckle_mob(m, force) + +//Handle any extras after buckling/unbuckling +//Called on buckle_mob() and unbuckle_mob() /atom/movable/proc/post_buckle_mob(mob/living/M) return +//Wrapper procs that handle sanity and user feedback /atom/movable/proc/user_buckle_mob(mob/living/M, mob/user, var/forced = FALSE, var/silent = FALSE) if(!ticker) user << "You can't buckle anyone in before the game starts." + return FALSE // Is this really needed? if(!user.Adjacent(M) || user.restrained() || user.stat || istype(user, /mob/living/silicon/pai)) - return - if(M == buckled_mob) - return + return FALSE + if(M in buckled_mobs) + to_chat(user, "\The [M] is already buckled to \the [src].") + return FALSE add_fingerprint(user) - unbuckle_mob() +// unbuckle_mob() //can't buckle unless you share locs so try to move M to the obj. if(M.loc != src.loc) - step_towards(M, src) + if(M.Adjacent(src) && user.Adjacent(src)) + M.forceMove(get_turf(src)) + // step_towards(M, src) . = buckle_mob(M, forced) if(.) @@ -94,8 +141,8 @@ "You are buckled to [src] by [user.name]!",\ "You hear metal clanking.") -/atom/movable/proc/user_unbuckle_mob(mob/user) - var/mob/living/M = unbuckle_mob() +/atom/movable/proc/user_unbuckle_mob(mob/living/buckled_mob, mob/user) + var/mob/living/M = unbuckle_mob(buckled_mob) if(M) if(M != user) M.visible_message(\ @@ -111,18 +158,20 @@ return M /atom/movable/proc/handle_buckled_mob_movement(newloc,direct) - if(buckled_mob) -// if(!buckled_mob.Move(newloc, direct)) - if(!buckled_mob.forceMove(newloc, direct)) - loc = buckled_mob.loc - last_move = buckled_mob.last_move - buckled_mob.inertia_dir = last_move - return FALSE - else - buckled_mob.set_dir(dir) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A +// if(!L.Move(newloc, direct)) + if(!L.forceMove(newloc, direct)) + loc = L.loc + last_move = L.last_move + L.inertia_dir = last_move + return FALSE + else + L.set_dir(dir) return TRUE /atom/movable/Move(atom/newloc, direct = 0) . = ..() - if(. && buckled_mob && !handle_buckled_mob_movement(newloc, direct)) //movement failed due to buckled mob(s) + if(. && has_buckled_mobs() && !handle_buckled_mob_movement(newloc, direct)) //movement failed due to buckled mob(s) . = 0 diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 1fee7b1b85..83f6f0bd89 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -113,3 +113,4 @@ icon_state = "survivalknife" item_state = "knife" applies_material_colour = FALSE + toolspeed = 2 // Use a real axe if you want to chop logs. diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 748d7df06d..317dba9ba9 100644 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -42,14 +42,16 @@ anchored = 1 /obj/item/weapon/beartrap/attack_hand(mob/user as mob) - if(buckled_mob && can_use(user)) + if(has_buckled_mobs() && can_use(user)) + var/victim = english_list(buckled_mobs) user.visible_message( - "[user] begins freeing [buckled_mob] from \the [src].", - "You carefully begin to free [buckled_mob] from \the [src].", + "[user] begins freeing [victim] from \the [src].", + "You carefully begin to free [victim] from \the [src].", ) if(do_after(user, 60)) - user.visible_message("[buckled_mob] has been freed from \the [src] by [user].") - unbuckle_mob() + user.visible_message("[victim] has been freed from \the [src] by [user].") + for(var/A in buckled_mobs) + unbuckle_mob(A) anchored = 0 else if(deployed && can_use(user)) user.visible_message( @@ -109,7 +111,7 @@ "You hear a loud metallic snap!" ) attack_mob(L) - if(!buckled_mob) + if(!has_buckled_mobs()) anchored = 0 deployed = 0 update_icon() diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index c077668bbd..50434de460 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -111,39 +111,41 @@ processing_objects |= src /obj/effect/energy_net/Destroy() - if(buckled_mob) - to_chat(buckled_mob,"You are free of the net!") - unbuckle_mob() + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + to_chat(A,"You are free of the net!") + unbuckle_mob(A) processing_objects -= src return ..() /obj/effect/energy_net/process() - if(isnull(buckled_mob) || buckled_mob.loc != loc) + if(!has_buckled_mobs()) qdel(src) /obj/effect/energy_net/Move() ..() - if(buckled_mob) - var/mob/living/occupant = buckled_mob - occupant.buckled = null - occupant.forceMove(src.loc) - occupant.buckled = src - if (occupant && (src.loc != occupant.loc)) - unbuckle_mob() - qdel(src) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/occupant = A + occupant.buckled = null + occupant.forceMove(src.loc) + occupant.buckled = src + if (occupant && (src.loc != occupant.loc)) + unbuckle_mob(occupant) + qdel(src) -/obj/effect/energy_net/user_unbuckle_mob(mob/user) +/obj/effect/energy_net/user_unbuckle_mob(mob/living/buckled_mob, mob/user) user.setClickCooldown(user.get_attack_speed()) visible_message("[user] begins to tear at \the [src]!") if(do_after(usr, escape_time, src, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY))) - if(!buckled_mob) + if(!has_buckled_mobs()) return visible_message("[user] manages to tear \the [src] apart!") - unbuckle_mob() + unbuckle_mob(buckled_mob) /obj/effect/energy_net/post_buckle_mob(mob/living/M) - if(buckled_mob) //Just buckled someone + if(M.buckled == src) //Just buckled someone ..() layer = M.layer+1 M.can_pull_size = 0 diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm index 339c93385d..1952ddea4f 100644 --- a/code/game/objects/structures/bonfire.dm +++ b/code/game/objects/structures/bonfire.dm @@ -14,7 +14,7 @@ /obj/structure/bonfire/New(newloc, material_name) ..(newloc) if(!material_name) - material_name = "wood" + material_name = MAT_WOOD material = get_material_by_name("[material_name]") if(!material) qdel(src) @@ -23,14 +23,14 @@ // Blue wood. /obj/structure/bonfire/sifwood/New(newloc, material_name) - ..(newloc, "alien wood") + ..(newloc, MAT_SIFWOOD) /obj/structure/bonfire/permanent/New(newloc, material_name) ..() ignite() /obj/structure/bonfire/permanent/sifwood/New(newloc, material_name) - ..(newloc, "alien wood") + ..(newloc, MAT_SIFWOOD) /obj/structure/bonfire/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/stack/rods) && !can_buckle && !grill) @@ -63,7 +63,7 @@ return ..() /obj/structure/bonfire/attack_hand(mob/user) - if(buckled_mob) + if(has_buckled_mobs()) return ..() if(get_fuel_amount()) @@ -194,7 +194,7 @@ I.appearance_flags = RESET_COLOR overlays += I - if(buckled_mob && get_fuel_amount() >= 5) + if(has_buckled_mobs() && get_fuel_amount() >= 5) I = image(icon, "bonfire_intense") I.pixel_y = 13 I.layer = MOB_LAYER + 0.1 @@ -231,7 +231,7 @@ extinguish() /obj/structure/bonfire/post_buckle_mob(mob/living/M) - if(buckled_mob) // Just buckled someone + if(M.buckled == src) // Just buckled someone M.pixel_y += 13 else // Just unbuckled someone M.pixel_y -= 13 diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index da8c5f04cb..97dd747845 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -59,7 +59,7 @@ continue if(istype(O, /obj/structure/bed)) //This is only necessary because of rollerbeds and swivel chairs. var/obj/structure/bed/B = O - if(B.buckled_mob) + if(B.has_buckled_mobs()) continue O.forceMove(src) itemcount++ diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm index 53b2ad224f..e9483386cf 100644 --- a/code/game/objects/structures/electricchair.dm +++ b/code/game/objects/structures/electricchair.dm @@ -64,12 +64,14 @@ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(12, 1, src) s.start() - if(buckled_mob) - buckled_mob.burn_skin(85) - buckled_mob << "You feel a deep shock course through your body!" - sleep(1) - buckled_mob.burn_skin(85) - buckled_mob.Stun(600) + if(has_buckled_mobs()) + for(var/a in buckled_mobs) + var/mob/living/L = a + L.burn_skin(85) + to_chat(L, "You feel a deep shock course through your body!") + sleep(1) + L.burn_skin(85) + L.Stun(600) visible_message("The electric chair went off!", "You hear a deep sharp shock!") A.power_light = light diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index bd23290e30..1b5a95373b 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/janitor.dmi' icon_state = "cart" anchored = 0 - density = 1 + density = 1 climbable = 1 flags = OPENCONTAINER //copypaste sorry @@ -229,9 +229,11 @@ /obj/structure/bed/chair/janicart/Move() ..() - if(buckled_mob) - if(buckled_mob.buckled == src) - buckled_mob.loc = loc + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + if(L.buckled == src) + L.loc = loc /obj/structure/bed/chair/janicart/post_buckle_mob(mob/living/M) @@ -257,36 +259,41 @@ /obj/structure/bed/chair/janicart/set_dir() ..() update_layer() - if(buckled_mob) - if(buckled_mob.loc != loc) - buckled_mob.buckled = null //Temporary, so Move() succeeds. - buckled_mob.buckled = src //Restoring + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + if(L.loc != loc) + L.buckled = null //Temporary, so Move() succeeds. + L.buckled = src //Restoring update_mob() /obj/structure/bed/chair/janicart/proc/update_mob() - if(buckled_mob) - buckled_mob.set_dir(dir) - switch(dir) - if(SOUTH) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 7 - if(WEST) - buckled_mob.pixel_x = 13 - buckled_mob.pixel_y = 7 - if(NORTH) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 4 - if(EAST) - buckled_mob.pixel_x = -13 - buckled_mob.pixel_y = 7 + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + L.set_dir(dir) + switch(dir) + if(SOUTH) + L.pixel_x = 0 + L.pixel_y = 7 + if(WEST) + L.pixel_x = 13 + L.pixel_y = 7 + if(NORTH) + L.pixel_x = 0 + L.pixel_y = 4 + if(EAST) + L.pixel_x = -13 + L.pixel_y = 7 /obj/structure/bed/chair/janicart/bullet_act(var/obj/item/projectile/Proj) - if(buckled_mob) + if(has_buckled_mobs()) if(prob(85)) - return buckled_mob.bullet_act(Proj) + var/mob/living/L = pick(buckled_mobs) + return L.bullet_act(Proj) visible_message("[Proj] ricochets off the [callme]!") diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm index 7312c1ebf9..2aa58488b6 100644 --- a/code/game/objects/structures/simple_doors.dm +++ b/code/game/objects/structures/simple_doors.dm @@ -192,10 +192,10 @@ ..(newloc, "diamond") /obj/structure/simple_door/wood/New(var/newloc,var/material_name) - ..(newloc, "wood") + ..(newloc, MAT_WOOD) /obj/structure/simple_door/sifwood/New(var/newloc,var/material_name) - ..(newloc, "alien wood") + ..(newloc, MAT_SIFWOOD) /obj/structure/simple_door/resin/New(var/newloc,var/material_name) ..(newloc, "resin") \ No newline at end of file diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm index 9d79ad45a1..270583011d 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm @@ -10,7 +10,7 @@ /obj/structure/bed/nest/update_icon() return -/obj/structure/bed/nest/user_unbuckle_mob(mob/user as mob) +/obj/structure/bed/nest/user_unbuckle_mob(mob/living/buckled_mob, mob/user) if(buckled_mob) if(buckled_mob.buckled == src) if(buckled_mob != user) @@ -20,7 +20,7 @@ "You hear squelching...") buckled_mob.pixel_y = 0 buckled_mob.old_y = 0 - unbuckle_mob() + unbuckle_mob(buckled_mob) else if(world.time <= buckled_mob.last_special+NEST_RESIST_TIME) return @@ -34,7 +34,7 @@ buckled_mob.last_special = world.time buckled_mob.pixel_y = 0 buckled_mob.old_y = 0 - unbuckle_mob() + unbuckle_mob(buckled_mob) src.add_fingerprint(user) return @@ -66,7 +66,7 @@ M.update_canmove() M.pixel_y = 6 M.old_y = 6 - src.buckled_mob = M + src.buckled_mobs |= M src.add_fingerprint(user) return diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 1af4fd82c0..219854f15f 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -131,7 +131,7 @@ else if(istype(W, /obj/item/weapon/grab)) var/obj/item/weapon/grab/G = W var/mob/living/affecting = G.affecting - if(buckled_mob) //Handles trying to buckle someone else to a chair when someone else is on it + if(has_buckled_mobs()) //Handles trying to buckle someone else to a chair when someone else is on it to_chat(user, "\The [src] already has someone buckled to it.") return user.visible_message("[user] attempts to buckle [affecting] into \the [src]!") @@ -183,7 +183,7 @@ ..(newloc,"wood","cotton") /obj/structure/bed/double/post_buckle_mob(mob/living/M as mob) - if(M == buckled_mob) + if(M.buckled == src) M.pixel_y = 13 M.old_y = 13 else @@ -216,8 +216,9 @@ if(istype(W, /obj/item/weapon/wrench) || istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters)) return else if(istype(W,/obj/item/roller_holder)) - if(buckled_mob) - user_unbuckle_mob(user) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + user_unbuckle_mob(A, user) else visible_message("[user] collapses \the [src.name].") new rollertype(get_turf(src)) @@ -287,14 +288,15 @@ /obj/structure/bed/roller/Move() ..() - if(buckled_mob) - if(buckled_mob.buckled == src) - buckled_mob.loc = src.loc - else - buckled_mob = null + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + + if(L.buckled == src) + L.loc = src.loc /obj/structure/bed/roller/post_buckle_mob(mob/living/M as mob) - if(M == buckled_mob) + if(M.buckled == src) M.pixel_y = 6 M.old_y = 6 density = 1 @@ -311,7 +313,7 @@ ..() if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) if(!ishuman(usr)) return - if(buckled_mob) return 0 + if(has_buckled_mobs()) return 0 visible_message("[usr] collapses \the [src.name].") new rollertype(get_turf(src)) spawn(0) diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index d1f2753e52..ed9c4e0301 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -31,7 +31,7 @@ qdel(src) /obj/structure/bed/chair/attack_tk(mob/user as mob) - if(buckled_mob) + if(has_buckled_mobs()) ..() else rotate() @@ -42,7 +42,7 @@ /obj/structure/bed/chair/update_icon() ..() - if(buckled_mob && padding_material) + if(has_buckled_mobs() && padding_material) var/cache_key = "[base_icon]-armrest-[padding_material.name]" if(isnull(stool_cache[cache_key])) var/image/I = image(icon, "[base_icon]_armrest") @@ -60,8 +60,10 @@ /obj/structure/bed/chair/set_dir() ..() update_layer() - if(buckled_mob) - buckled_mob.set_dir(dir) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + L.set_dir(dir) /obj/structure/bed/chair/verb/rotate() set name = "Rotate Chair" @@ -136,45 +138,47 @@ /obj/structure/bed/chair/office/Move() ..() - if(buckled_mob) - var/mob/living/occupant = buckled_mob - occupant.buckled = null - occupant.Move(src.loc) - occupant.buckled = src - if (occupant && (src.loc != occupant.loc)) - if (propelled) - for (var/mob/O in src.loc) - if (O != occupant) - Bump(O) - else - unbuckle_mob() + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/occupant = A + occupant.buckled = null + occupant.Move(src.loc) + occupant.buckled = src + if (occupant && (src.loc != occupant.loc)) + if (propelled) + for (var/mob/O in src.loc) + if (O != occupant) + Bump(O) + else + unbuckle_mob() /obj/structure/bed/chair/office/Bump(atom/A) ..() - if(!buckled_mob) return + if(!has_buckled_mobs()) return if(propelled) - var/mob/living/occupant = unbuckle_mob() + for(var/a in buckled_mobs) + var/mob/living/occupant = unbuckle_mob(a) - var/def_zone = ran_zone() - var/blocked = occupant.run_armor_check(def_zone, "melee") - var/soaked = occupant.get_armor_soak(def_zone, "melee") - occupant.throw_at(A, 3, propelled) - occupant.apply_effect(6, STUN, blocked) - occupant.apply_effect(6, WEAKEN, blocked) - occupant.apply_effect(6, STUTTER, blocked) - occupant.apply_damage(10, BRUTE, def_zone, blocked, soaked) - playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - if(istype(A, /mob/living)) - var/mob/living/victim = A - def_zone = ran_zone() - blocked = victim.run_armor_check(def_zone, "melee") - soaked = victim.get_armor_soak(def_zone, "melee") - victim.apply_effect(6, STUN, blocked) - victim.apply_effect(6, WEAKEN, blocked) - victim.apply_effect(6, STUTTER, blocked) - victim.apply_damage(10, BRUTE, def_zone, blocked, soaked) - occupant.visible_message("[occupant] crashed into \the [A]!") + var/def_zone = ran_zone() + var/blocked = occupant.run_armor_check(def_zone, "melee") + var/soaked = occupant.get_armor_soak(def_zone, "melee") + occupant.throw_at(A, 3, propelled) + occupant.apply_effect(6, STUN, blocked) + occupant.apply_effect(6, WEAKEN, blocked) + occupant.apply_effect(6, STUTTER, blocked) + occupant.apply_damage(10, BRUTE, def_zone, blocked, soaked) + playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) + if(istype(A, /mob/living)) + var/mob/living/victim = A + def_zone = ran_zone() + blocked = victim.run_armor_check(def_zone, "melee") + soaked = victim.get_armor_soak(def_zone, "melee") + victim.apply_effect(6, STUN, blocked) + victim.apply_effect(6, WEAKEN, blocked) + victim.apply_effect(6, STUTTER, blocked) + victim.apply_damage(10, BRUTE, def_zone, blocked, soaked) + occupant.visible_message("[occupant] crashed into \the [A]!") /obj/structure/bed/chair/office/light icon_state = "officechair_white" diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm index bdd4b87b0e..550b59d112 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm @@ -17,8 +17,10 @@ overlays = null var/image/O = image(icon = 'icons/obj/furniture.dmi', icon_state = "w_overlay", layer = FLY_LAYER, dir = src.dir) overlays += O - if(buckled_mob) - buckled_mob.set_dir(dir) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + L.set_dir(dir) /obj/structure/bed/chair/wheelchair/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/wrench) || istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters)) @@ -33,7 +35,7 @@ user.pulledby = null user << "You lost your grip!" return - if(buckled_mob && pulling && user == buckled_mob) + if(has_buckled_mobs() && pulling && user in buckled_mobs) if(pulling.stat || pulling.stunned || pulling.weakened || pulling.paralysis || pulling.lying || pulling.restrained()) pulling.pulledby = null pulling = null @@ -51,7 +53,7 @@ if(pulling && (get_dir(src.loc, pulling.loc) == direction)) user << "You cannot go there." return - if(pulling && buckled_mob && (buckled_mob == user)) + if(pulling && has_buckled_mobs() && (user in buckled_mobs)) user << "You cannot drive while being pushed." return @@ -59,10 +61,12 @@ driving = 1 var/turf/T = null //--1---Move occupant---1--// - if(buckled_mob) - buckled_mob.buckled = null - step(buckled_mob, direction) - buckled_mob.buckled = src + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + L.buckled = null + step(L, direction) + L.buckled = src //--2----Move driver----2--// if(pulling) T = pulling.loc @@ -70,8 +74,9 @@ step(pulling, get_dir(pulling.loc, src.loc)) //--3--Move wheelchair--3--// step(src, direction) - if(buckled_mob) // Make sure it stays beneath the occupant - Move(buckled_mob.loc) + if(has_buckled_mobs()) // Make sure it stays beneath the occupant + var/mob/living/L = buckled_mobs[1] + Move(L.loc) set_dir(direction) if(pulling) // Driver if(pulling.loc == src.loc) // We moved onto the wheelchair? Revert! @@ -88,38 +93,41 @@ /obj/structure/bed/chair/wheelchair/Move() ..() - if(buckled_mob) - var/mob/living/occupant = buckled_mob - if(!driving) - occupant.buckled = null - occupant.Move(src.loc) - occupant.buckled = src - if (occupant && (src.loc != occupant.loc)) - if (propelled) - for (var/mob/O in src.loc) - if (O != occupant) - Bump(O) - else - unbuckle_mob() - if (pulling && (get_dist(src, pulling) > 1)) - pulling.pulledby = null - pulling << "You lost your grip!" - pulling = null - else - if (occupant && (src.loc != occupant.loc)) - src.forceMove(occupant.loc) // Failsafe to make sure the wheelchair stays beneath the occupant after driving + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/occupant = A + if(!driving) + occupant.buckled = null + occupant.Move(src.loc) + occupant.buckled = src + if (occupant && (src.loc != occupant.loc)) + if (propelled) + for (var/mob/O in src.loc) + if (O != occupant) + Bump(O) + else + unbuckle_mob() + if (pulling && (get_dist(src, pulling) > 1)) + pulling.pulledby = null + pulling << "You lost your grip!" + pulling = null + else + if (occupant && (src.loc != occupant.loc)) + src.forceMove(occupant.loc) // Failsafe to make sure the wheelchair stays beneath the occupant after driving /obj/structure/bed/chair/wheelchair/attack_hand(mob/living/user as mob) if (pulling) MouseDrop(usr) else - user_unbuckle_mob(user) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + user_unbuckle_mob(A, user) return /obj/structure/bed/chair/wheelchair/CtrlClick(var/mob/user) if(in_range(src, user)) if(!ishuman(user)) return - if(user == buckled_mob) + if(has_buckled_mobs() && user in buckled_mobs) user << "You realize you are unable to push the wheelchair you sit in." return if(!pulling) @@ -137,7 +145,7 @@ /obj/structure/bed/chair/wheelchair/Bump(atom/A) ..() - if(!buckled_mob) return + if(!has_buckled_mobs()) return if(propelled || (pulling && (pulling.a_intent == I_HURT))) var/mob/living/occupant = unbuckle_mob() @@ -213,7 +221,7 @@ ..() if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) if(!ishuman(usr)) return - if(buckled_mob) return 0 + if(has_buckled_mobs()) return 0 visible_message("[usr] collapses \the [src.name].") var/obj/item/wheelchair/R = new/obj/item/wheelchair(get_turf(src)) R.name = src.name diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 2d07f0ffbd..f9331eac1d 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -73,7 +73,7 @@ var/list/mechtoys = list( return prob(60) var/obj/structure/bed/B = A - if (istype(A, /obj/structure/bed) && B.buckled_mob)//if it's a bed/chair and someone is buckled, it will not pass + if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass return 0 if(istype(A, /obj/vehicle)) //no vehicles diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm index 19264e23ba..c137822860 100644 --- a/code/game/turfs/simulated/wall_types.dm +++ b/code/game/turfs/simulated/wall_types.dm @@ -48,16 +48,16 @@ ..(newloc,"durasteel", "durasteel") /turf/simulated/wall/wood/New(var/newloc) - ..(newloc,"wood") + ..(newloc, MAT_WOOD) /turf/simulated/wall/sifwood/New(var/newloc) - ..(newloc,"alien wood") + ..(newloc, MAT_SIFWOOD) /turf/simulated/wall/log/New(var/newloc) - ..(newloc,"log") + ..(newloc, MAT_LOG) /turf/simulated/wall/log_sif/New(var/newloc) - ..(newloc,"alien log") + ..(newloc, MAT_SIFLOG) // Shuttle Walls /turf/simulated/shuttle/wall diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 6f2c606c0d..e766b1bba3 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -55,6 +55,8 @@ if(istype(AM, /mob/living)) var/mob/living/L = AM L.update_water() + if(L.check_submerged() <= 0) + return if(!istype(oldloc, /turf/simulated/floor/water)) to_chat(L, "You get drenched in water from entering \the [src]!") AM.water_act(5) @@ -64,6 +66,8 @@ if(istype(AM, /mob/living)) var/mob/living/L = AM L.update_water() + if(L.check_submerged() <= 0) + return if(!istype(newloc, /turf/simulated/floor/water)) to_chat(L, "You climb out of \the [src].") ..() @@ -97,6 +101,8 @@ return ..() /mob/living/proc/check_submerged() + if(buckled) + return 0 var/turf/simulated/floor/water/T = loc if(istype(T)) return T.depth diff --git a/code/modules/hydroponics/spreading/spreading_growth.dm b/code/modules/hydroponics/spreading/spreading_growth.dm index 0dbe4c9eea..bd4b48893f 100644 --- a/code/modules/hydroponics/spreading/spreading_growth.dm +++ b/code/modules/hydroponics/spreading/spreading_growth.dm @@ -73,10 +73,12 @@ else plant.layer = layer + 0.1 - if(buckled_mob) - seed.do_sting(buckled_mob,src) - if(seed.get_trait(TRAIT_CARNIVOROUS)) - seed.do_thorns(buckled_mob,src) + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + seed.do_sting(L,src) + if(seed.get_trait(TRAIT_CARNIVOROUS)) + seed.do_thorns(L,src) if(world.time >= last_tick+NEIGHBOR_REFRESH_TIME) last_tick = world.time @@ -88,7 +90,7 @@ if(prob(chance)) sampled = 0 - if(is_mature() && !buckled_mob) + if(is_mature() && !has_buckled_mobs()) for(var/turf/neighbor in neighbors) for(var/mob/living/M in neighbor) if(seed.get_trait(TRAIT_SPREAD) >= 2 && (M.lying || prob(round(seed.get_trait(TRAIT_POTENCY))))) @@ -107,7 +109,7 @@ // We shouldn't have spawned if the controller doesn't exist. check_health() - if(buckled_mob || neighbors.len) + if(has_buckled_mobs() || neighbors.len) plant_controller.add_plant(src) //spreading vines aren't created on their final turf. diff --git a/code/modules/hydroponics/spreading/spreading_response.dm b/code/modules/hydroponics/spreading/spreading_response.dm index 12747666c4..8a8ceabfeb 100644 --- a/code/modules/hydroponics/spreading/spreading_response.dm +++ b/code/modules/hydroponics/spreading/spreading_response.dm @@ -7,7 +7,7 @@ if(!istype(M)) return - if(!buckled_mob && !M.buckled && !M.anchored && (issmall(M) || prob(round(seed.get_trait(TRAIT_POTENCY)/3)))) + if(!has_buckled_mobs() && !M.buckled && !M.anchored && (issmall(M) || prob(round(seed.get_trait(TRAIT_POTENCY)/3)))) //wait a tick for the Entered() proc that called HasProximity() to finish (and thus the moving animation), //so we don't appear to teleport from two tiles away when moving into a turf adjacent to vines. spawn(1) @@ -35,31 +35,35 @@ seed.do_sting(victim,src,pick("r_foot","l_foot","r_leg","l_leg")) /obj/effect/plant/proc/unbuckle() - if(buckled_mob) - if(buckled_mob.buckled == src) - buckled_mob.buckled = null - buckled_mob.anchored = initial(buckled_mob.anchored) - buckled_mob.update_canmove() - buckled_mob = null + if(has_buckled_mobs()) + for(var/A in buckled_mobs) + var/mob/living/L = A + if(L.buckled == src) + L.buckled = null + L.anchored = initial(L.anchored) + L.update_canmove() + buckled_mobs = list() return /obj/effect/plant/proc/manual_unbuckle(mob/user as mob) - if(buckled_mob) + if(has_buckled_mobs()) var/chance = 20 if(seed) chance = round(100/(20*seed.get_trait(TRAIT_POTENCY)/100)) if(prob(chance)) - if(buckled_mob != user) - buckled_mob.visible_message(\ - "\The [user] frees \the [buckled_mob] from \the [src].",\ - "\The [user] frees you from \the [src].",\ - "You hear shredding and ripping.") - else - buckled_mob.visible_message(\ - "\The [buckled_mob] struggles free of \the [src].",\ - "You untangle \the [src] from around yourself.",\ - "You hear shredding and ripping.") - unbuckle() + for(var/A in buckled_mobs) + var/mob/living/L = A + if(!(user in buckled_mobs)) + L.visible_message(\ + "\The [user] frees \the [L] from \the [src].",\ + "\The [user] frees you from \the [src].",\ + "You hear shredding and ripping.") + else + L.visible_message(\ + "\The [L] struggles free of \the [src].",\ + "You untangle \the [src] from around yourself.",\ + "You hear shredding and ripping.") + unbuckle() else user.setClickCooldown(user.get_attack_speed()) health -= rand(1,5) @@ -73,7 +77,7 @@ /obj/effect/plant/proc/entangle(var/mob/living/victim) - if(buckled_mob) + if(has_buckled_mobs()) return if(victim.buckled || victim.anchored) diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 7b8a4d4647..a52d66a0fa 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -125,6 +125,9 @@ /material/wood/generate_recipes() ..() + recipes += new/datum/stack_recipe("oar", /obj/item/weapon/oar, 2, time = 30, supplied_material = "[name]") + recipes += new/datum/stack_recipe("boat", /obj/vehicle/boat, 20, time = 10 SECONDS, supplied_material = "[name]") + recipes += new/datum/stack_recipe("dragon boat", /obj/vehicle/boat/dragon, 50, time = 30 SECONDS, supplied_material = "[name]") recipes += new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1) recipes += new/datum/stack_recipe("wood circlet", /obj/item/clothing/head/woodcirclet, 1) recipes += new/datum/stack_recipe("clipboard", /obj/item/weapon/clipboard, 1) diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index c662141fbd..0f76f6172e 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -201,33 +201,48 @@ /obj/item/stack/material/wood name = "wooden plank" icon_state = "sheet-wood" - default_type = "wood" + default_type = MAT_WOOD + +/obj/item/stack/material/wood/sif + name = "alien wooden plank" + color = "#0099cc" + default_type = MAT_SIFWOOD /obj/item/stack/material/log name = "log" icon_state = "sheet-log" - default_type = "log" + default_type = MAT_LOG no_variants = FALSE color = "#824B28" max_amount = 25 w_class = ITEMSIZE_HUGE + description_info = "Use inhand to craft things, or use a sharp and edged object on this to convert it into two wooden planks." + var/plank_type = /obj/item/stack/material/wood /obj/item/stack/material/log/sif name = "alien log" - default_type = "alien log" + default_type = MAT_SIFLOG color = "#0099cc" + plank_type = /obj/item/stack/material/wood/sif /obj/item/stack/material/log/attackby(var/obj/item/W, var/mob/user) - if(!istype(W)) + if(!istype(W) || W.force <= 0) return ..() - if(W.sharp && W.edge && use(1)) - to_chat(user, "You cut up a log into planks.") - playsound(get_turf(src), 'sound/effects/woodcutting.ogg', 50, 1) - var/obj/item/stack/material/wood/existing_wood = locate() in user.loc - var/obj/item/stack/material/wood/new_wood = new(user.loc) - new_wood.amount = 2 - if(existing_wood) - if(new_wood.transfer_to(existing_wood)) + if(W.sharp && W.edge) + var/time = (3 SECONDS / max(W.force / 10, 1)) * W.toolspeed + user.setClickCooldown(time) + if(do_after(user, time, src) && use(1)) + to_chat(user, "You cut up a log into planks.") + playsound(get_turf(src), 'sound/effects/woodcutting.ogg', 50, 1) + var/obj/item/stack/material/wood/existing_wood = null + for(var/obj/item/stack/material/wood/M in user.loc) + if(M.material.name == src.material.name) + existing_wood = M + break + + var/obj/item/stack/material/wood/new_wood = new plank_type(user.loc) + new_wood.amount = 2 + if(existing_wood && new_wood.transfer_to(existing_wood)) to_chat(user, "You add the newly-formed wood to the stack. It now contains [existing_wood.amount] planks.") else return ..() diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 6ad4a6487d..54a890074a 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -672,9 +672,9 @@ var/list/name_to_material /material/wood - name = "wood" + name = MAT_WOOD stack_type = /obj/item/stack/material/wood - icon_colour = "#824B28" + icon_colour = "#9c5930" integrity = 50 icon_base = "wood" explosion_resistance = 2 @@ -694,14 +694,14 @@ var/list/name_to_material sheet_plural_name = "planks" /material/wood/log - name = "log" + name = MAT_LOG icon_base = "log" stack_type = /obj/item/stack/material/log sheet_singular_name = null sheet_plural_name = "pile" /material/wood/log/sif - name = "alien log" + name = MAT_SIFLOG icon_colour = "#0099cc" // Cyan-ish stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2) stack_type = /obj/item/stack/material/log/sif @@ -713,7 +713,7 @@ var/list/name_to_material shard_type = SHARD_NONE /material/wood/sif - name = "alien wood" + name = MAT_SIFWOOD // stack_type = /obj/item/stack/material/wood/sif icon_colour = "#0099cc" // Cyan-ish stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2) // Alien wood would presumably be more interesting to the analyzer. diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index bc75344484..b6c0376aef 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -95,6 +95,10 @@ var/list/slot_equipment_priority = list( \ //Returns the thing in our inactive hand /mob/proc/get_inactive_hand() +// Override for your specific mob's hands or lack thereof. +/mob/proc/is_holding_item_of_type(typepath) + return FALSE + //Puts the item into your l_hand if possible and calls all necessary triggers/updates. returns 1 on success. /mob/proc/put_in_l_hand(var/obj/item/W) if(lying || !istype(W)) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 149c1831f6..3f4a66476b 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -352,3 +352,10 @@ This saves us from having to call add_fingerprint() any time something is put in if(slot_l_ear) return l_ear if(slot_r_ear) return r_ear return ..() + + +/mob/living/carbon/human/is_holding_item_of_type(typepath) + for(var/obj/item/I in list(l_hand, r_hand)) + if(istype(I, typepath)) + return I + return FALSE \ No newline at end of file diff --git a/code/modules/mob/living/carbon/resist.dm b/code/modules/mob/living/carbon/resist.dm index 86597afba6..5c72bd224b 100644 --- a/code/modules/mob/living/carbon/resist.dm +++ b/code/modules/mob/living/carbon/resist.dm @@ -175,4 +175,4 @@ return visible_message("[usr] manages to unbuckle themself!", "You successfully unbuckle yourself.") - buckled.user_unbuckle_mob(src) + buckled.user_unbuckle_mob(src, src) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 15de0b93d9..90ef8ff3cc 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -822,7 +822,7 @@ default behaviour is: /mob/living/proc/escape_buckle() if(buckled) - buckled.user_unbuckle_mob(src) + buckled.user_unbuckle_mob(src, src) /mob/living/proc/resist_grab() var/resisting = 0 @@ -951,11 +951,14 @@ default behaviour is: if(is_physically_disabled()) lying = 0 canmove = 1 - pixel_y = V.mob_offset_y - 5 + if(!V.riding_datum) // If it has a riding datum, the datum handles moving the pixel_ vars. + pixel_y = V.mob_offset_y - 5 else - if(buckled.buckle_lying != -1) lying = buckled.buckle_lying + if(buckled.buckle_lying != -1) + lying = buckled.buckle_lying canmove = 1 - pixel_y = V.mob_offset_y + if(!V.riding_datum) // If it has a riding datum, the datum handles moving the pixel_ vars. + pixel_y = V.mob_offset_y else if(buckled) anchored = 1 canmove = 0 diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 4b492a9498..6d44a4907a 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -338,8 +338,9 @@ weaponlock_time = 120 /mob/living/silicon/robot/update_canmove() - if(paralysis || stunned || weakened || buckled || lockdown || !is_component_functioning("actuator")) canmove = 0 - else canmove = 1 + ..() // Let's not reinvent the wheel. + if(lockdown || !is_component_functioning("actuator")) + canmove = FALSE return canmove /mob/living/silicon/robot/update_fire() diff --git a/code/modules/mob/living/simple_animal/slime/combat.dm b/code/modules/mob/living/simple_animal/slime/combat.dm index 8554a27e5f..5aee0a7a3a 100644 --- a/code/modules/mob/living/simple_animal/slime/combat.dm +++ b/code/modules/mob/living/simple_animal/slime/combat.dm @@ -44,11 +44,12 @@ if(istype(L, /mob/living/carbon) && L.getCloneLoss() >= L.getMaxHealth() * 1.5 || istype(L, /mob/living/simple_animal) && L.stat == DEAD) to_chat(src, "This subject does not have an edible life energy...") return FALSE - if(L.buckled_mob) - if(istype(L.buckled_mob, /mob/living/simple_animal/slime)) - if(L.buckled_mob != src) - to_chat(src, "\The [L.buckled_mob] is already feeding on this subject...") - return FALSE + if(L.has_buckled_mobs()) + for(var/A in L.buckled_mobs) + if(istype(A, /mob/living/simple_animal/slime)) + if(A != src) + to_chat(src, "\The [A] is already feeding on this subject...") + return FALSE return TRUE /mob/living/simple_animal/slime/proc/start_consuming(var/mob/living/L) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index e73d316433..af72ba4dd4 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -167,6 +167,12 @@ src.m_flag = 1 if ((A != src.loc && A && A.z == src.z)) src.last_move = get_dir(A, src.loc) + if(.) + Moved(A, direct) + return + +// Called on a successful Move(). +/atom/movable/proc/Moved(atom/oldloc) return /client/proc/Move_object(direct) @@ -533,23 +539,23 @@ /mob/proc/update_gravity() return - +/* // The real Move() proc is above, but touching that massive block just to put this in isn't worth it. /mob/Move(var/newloc, var/direct) . = ..(newloc, direct) if(.) post_move(newloc, direct) - +*/ // Called when a mob successfully moves. // Would've been an /atom/movable proc but it caused issues. -/mob/proc/post_move(var/newloc, var/direct) +/mob/Moved(atom/oldloc) for(var/obj/O in contents) - O.on_loc_moved(newloc, direct) + O.on_loc_moved(oldloc) -// Received from post_move(), useful for items that need to know that their loc just moved. -/obj/proc/on_loc_moved(var/newloc, var/direct) +// Received from Moved(), useful for items that need to know that their loc just moved. +/obj/proc/on_loc_moved(atom/oldloc) return -/obj/item/weapon/storage/on_loc_moved(var/newloc, var/direct) +/obj/item/weapon/storage/on_loc_moved(atom/oldloc) for(var/obj/O in contents) - O.on_loc_moved(newloc, direct) \ No newline at end of file + O.on_loc_moved(oldloc) \ No newline at end of file diff --git a/code/modules/shieldgen/directional_shield.dm b/code/modules/shieldgen/directional_shield.dm index 41bcda3ceb..1892a3f3ad 100644 --- a/code/modules/shieldgen/directional_shield.dm +++ b/code/modules/shieldgen/directional_shield.dm @@ -208,7 +208,7 @@ ..(newloc, direct) update_shield_positions() -/obj/item/shield_projector/on_loc_moved(var/newloc, var/direct) +/obj/item/shield_projector/on_loc_moved(atom/oldloc) update_shield_positions() diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index 8136b06353..f455be67a5 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -118,8 +118,9 @@ ..() /obj/vehicle/bike/bullet_act(var/obj/item/projectile/Proj) - if(buckled_mob && prob(protection_percent)) - buckled_mob.bullet_act(Proj) + if(has_buckled_mobs() && prob(protection_percent)) + var/mob/living/L = pick(buckled_mobs) + L.bullet_act(Proj) return ..() diff --git a/code/modules/vehicles/boat.dm b/code/modules/vehicles/boat.dm new file mode 100644 index 0000000000..ea17e29678 --- /dev/null +++ b/code/modules/vehicles/boat.dm @@ -0,0 +1,82 @@ +/obj/vehicle/boat + name = "boat" + desc = "It's a wooden boat. Looks like it'll hold two people. Oars not included." + icon = 'icons/obj/vehicles_36x32.dmi' + icon_state = "boat" + health = 100 + maxhealth = 100 + charge_use = 0 // Boats use oars. + pixel_x = -2 + move_delay = 3 // Rather slow, but still faster than swimming, and won't get you wet. + max_buckled_mobs = 2 + anchored = FALSE + var/material/material = null + var/riding_datum_type = /datum/riding/boat/small + +/obj/vehicle/boat/sifwood/New(newloc, material_name) + ..(newloc, MAT_SIFWOOD) + +/obj/vehicle/boat/dragon + name = "dragon boat" + desc = "It's a large wooden boat, carved to have a nordic-looking dragon on the front. Looks like it'll hold five people. Oars not included." + icon = 'icons/obj/64x32.dmi' + icon_state = "dragon_boat" + health = 250 + maxhealth = 250 + pixel_x = -16 + max_buckled_mobs = 5 + riding_datum_type = /datum/riding/boat/big + +/obj/vehicle/boat/dragon/New(newloc, material_name) + ..(newloc, material_name) + var/image/I = image(icon, src, "dragon_boat_underlay", BELOW_MOB_LAYER) + underlays += I + +/obj/vehicle/boat/dragon/sifwood/New(newloc, material_name) + ..(newloc, MAT_SIFWOOD) + +// Oars, which must be held inhand while in a boat to move it. +/obj/item/weapon/oar + name = "oar" + icon = 'icons/obj/vehicles.dmi' + desc = "Used to provide propulsion to a boat." + icon_state = "oar" + item_state = "oar" + force = 12 + var/material/material = null + +/obj/item/weapon/oar/sifwood/New(newloc, material_name) + ..(newloc, MAT_SIFWOOD) + +/obj/item/weapon/oar/New(newloc, material_name) + ..(newloc) + if(!material_name) + material_name = "wood" + material = get_material_by_name("[material_name]") + if(!material) + qdel(src) + return + color = material.icon_colour + +/obj/vehicle/boat/New(newloc, material_name) + ..(newloc) + if(!material_name) + material_name = "wood" + material = get_material_by_name("[material_name]") + if(!material) + qdel(src) + return + color = material.icon_colour + riding_datum = new riding_datum_type(src) + +// Boarding. +/obj/vehicle/boat/MouseDrop_T(var/atom/movable/C, mob/user) + if(ismob(C)) + user_buckle_mob(C, user) + else + ..(C, user) + +/obj/vehicle/boat/load(mob/living/L, mob/living/user) + if(!istype(L)) // Only mobs on boats. + return FALSE + ..(L, user) diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index 7d6acc5fae..e1c643b776 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -81,8 +81,9 @@ //cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead /obj/vehicle/train/cargo/bullet_act(var/obj/item/projectile/Proj) - if(buckled_mob && prob(70)) - buckled_mob.bullet_act(Proj) + if(has_buckled_mobs() && prob(70)) + var/mob/living/L = pick(buckled_mobs) + L.bullet_act(Proj) return ..() @@ -256,7 +257,7 @@ //------------------------------------------- // Loading/unloading procs //------------------------------------------- -/obj/vehicle/train/cargo/trolley/load(var/atom/movable/C) +/obj/vehicle/train/cargo/trolley/load(var/atom/movable/C, var/mob/user) 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) && !istype(C, /mob/living/carbon/human)) @@ -267,12 +268,12 @@ if(istype(C, /obj/machinery)) load_object(C) else - ..() + ..(C, user) if(load) return 1 -/obj/vehicle/train/cargo/engine/load(var/atom/movable/C) +/obj/vehicle/train/cargo/engine/load(var/atom/movable/C, var/mob/user) if(!istype(C, /mob/living/carbon/human)) return 0 diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm index 59396f9daa..c59ffe7e64 100644 --- a/code/modules/vehicles/train.dm +++ b/code/modules/vehicles/train.dm @@ -95,7 +95,7 @@ if(istype(C,/obj/vehicle/train)) latch(C, user) else - if(!load(C)) + if(!load(C, user)) user << "You were unable to load [C] on [src]." /obj/vehicle/train/attack_hand(mob/user as mob) @@ -107,7 +107,7 @@ else if(load) unload(user) //unload if loaded else if(!load && !user.buckled) - load(user) //else try climbing on board + load(user, user) //else try climbing on board else return 0 diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index f725508c88..7bd11955e3 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -17,6 +17,7 @@ buckle_movable = 1 buckle_lying = 0 + var/mechanical = TRUE // If false, doesn't care for things like cells, engines, EMP, keys, etc. var/attack_log = null var/on = 0 var/health = 0 //do not forget to set health for your vehicle! @@ -39,6 +40,8 @@ var/load_offset_y = 0 //pixel_y offset for item overlay var/mob_offset_y = 0 //pixel_y offset for mob overlay + var/datum/riding/riding_datum = null + //------------------------------------------- // Standard procs //------------------------------------------- @@ -46,10 +49,47 @@ ..() //spawn the cell you want in each vehicle +/obj/vehicle/Destroy() + qdel_null(riding_datum) + return ..() + +//BUCKLE HOOKS + +/obj/vehicle/buckle_mob(mob/living/M, forced = FALSE, check_loc = TRUE) + . = ..() + M.update_water() + if(riding_datum) + riding_datum.ridden = src + riding_datum.handle_vehicle_offsets() + +/obj/vehicle/unbuckle_mob(mob/living/buckled_mob, force = FALSE) + . = ..(buckled_mob, force) + buckled_mob.update_water() + if(riding_datum) + riding_datum.restore_position(buckled_mob) + riding_datum.handle_vehicle_offsets() // So the person in back goes to the front. + +/obj/vehicle/set_dir(newdir) + ..(newdir) + if(riding_datum) + riding_datum.handle_vehicle_offsets() + +//MOVEMENT +/obj/vehicle/relaymove(mob/user, direction) + if(riding_datum) + riding_datum.handle_ride(user, direction) + + +/obj/vehicle/Moved() + . = ..() + if(riding_datum) + riding_datum.handle_vehicle_layer() + riding_datum.handle_vehicle_offsets() + /obj/vehicle/Move() if(world.time > l_move_time + move_delay) var/old_loc = get_turf(src) - if(on && powered && cell.charge < charge_use) + if(mechanical && on && powered && cell.charge < charge_use) turn_off() var/init_anc = anchored @@ -61,7 +101,7 @@ set_dir(get_dir(old_loc, loc)) anchored = init_anc - if(on && powered) + if(mechanical && on && powered) cell.use(charge_use) //Dummy loads do not have to be moved as they are just an overlay @@ -77,32 +117,34 @@ /obj/vehicle/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/hand_labeler)) return - if(istype(W, /obj/item/weapon/screwdriver)) - if(!locked) - open = !open - update_icon() - user << "Maintenance panel is now [open ? "opened" : "closed"]." - playsound(src, W.usesound, 50, 1) - else if(istype(W, /obj/item/weapon/crowbar) && cell && open) - remove_cell(user) + if(mechanical) + if(istype(W, /obj/item/weapon/screwdriver)) + if(!locked) + open = !open + update_icon() + user << "Maintenance panel is now [open ? "opened" : "closed"]." + playsound(src, W.usesound, 50, 1) + 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.setClickCooldown(user.get_attack_speed(W)) - playsound(src, T.usesound, 50, 1) - user.visible_message("[user] repairs [src]!"," You repair [src]!") + 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.setClickCooldown(user.get_attack_speed(W)) + playsound(src, T.usesound, 50, 1) + user.visible_message("[user] repairs [src]!"," You repair [src]!") + else + user << "Unable to repair with the maintenance panel closed." else - user << "Unable to repair with the maintenance panel closed." + user << "[src] does not need a repair." else - user << "[src] does not need a repair." - else - user << "Unable to repair while [src] is off." + user << "Unable to repair while [src] is off." + else if(hasvar(W,"force") && hasvar(W,"damtype")) user.setClickCooldown(user.get_attack_speed(W)) switch(W.damtype) @@ -139,6 +181,9 @@ return /obj/vehicle/emp_act(severity) + if(!mechanical) + return + var/was_on = on stat |= EMPED var/obj/effect/overlay/pulse2 = new /obj/effect/overlay(src.loc) @@ -168,41 +213,37 @@ // Vehicle procs //------------------------------------------- /obj/vehicle/proc/turn_on() - if(stat) - return 0 + if(!mechanical || stat) + return FALSE if(powered && cell.charge < charge_use) - return 0 + return FALSE on = 1 set_light(initial(light_range)) update_icon() - return 1 + return TRUE /obj/vehicle/proc/turn_off() + if(!mechanical) + return FALSE on = 0 set_light(0) update_icon() /obj/vehicle/emag_act(var/remaining_charges, mob/user as mob) + if(!mechanical) + return FALSE + if(!emagged) emagged = 1 if(locked) locked = 0 user << "You bypass [src]'s controls." - return 1 + return TRUE /obj/vehicle/proc/explode() src.visible_message("[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/stack/cable_coil/cut(Tsec) - - if(cell) - cell.forceMove(Tsec) - cell.update_icon() - cell = null - //stuns people who are thrown off a train that has been blown up if(istype(load, /mob/living)) var/mob/living/M = load @@ -210,8 +251,17 @@ unload() - new /obj/effect/gibspawner/robot(Tsec) - new /obj/effect/decal/cleanable/blood/oil(src.loc) + if(mechanical) + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/cable_coil/cut(Tsec) + new /obj/effect/gibspawner/robot(Tsec) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + + if(cell) + cell.forceMove(Tsec) + cell.update_icon() + cell = null qdel(src) @@ -220,6 +270,9 @@ explode() /obj/vehicle/proc/powercheck() + if(!mechanical) + return + if(!cell && !powered) return @@ -236,6 +289,8 @@ return /obj/vehicle/proc/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + if(!mechanical) + return if(cell) return if(!istype(C)) @@ -248,6 +303,8 @@ usr << "You install [C] in [src]." /obj/vehicle/proc/remove_cell(var/mob/living/carbon/human/H) + if(mechanical) + return if(!cell) return @@ -267,7 +324,7 @@ // the vehicle load() definition before // calling this parent proc. //------------------------------------------- -/obj/vehicle/proc/load(var/atom/movable/C) +/obj/vehicle/proc/load(var/atom/movable/C, var/mob/living/user) //This loads objects onto the vehicle so they can still be interacted with. //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. @@ -292,10 +349,10 @@ C.pixel_y += mob_offset_y else C.pixel_y += load_offset_y - C.layer = layer + 0.1 //so it sits above the vehicle + C.layer = layer + 0.1 if(ismob(C)) - buckle_mob(C) + user_buckle_mob(C, user) return 1 @@ -358,7 +415,7 @@ user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") user.do_attack_animation(src) src.health -= damage - if(prob(10)) + if(mechanical && prob(10)) new /obj/effect/decal/cleanable/blood/oil(src.loc) spawn(1) healthcheck() return 1 diff --git a/html/changelogs/Neerti - Boats.yml b/html/changelogs/Neerti - Boats.yml new file mode 100644 index 0000000000..855b8eb69b --- /dev/null +++ b/html/changelogs/Neerti - Boats.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Neerti + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Adds boats that can be ridden by multiple people, which use oars. Can be crafted with large amounts of wooden planks." diff --git a/icons/mob/items/lefthand.dmi b/icons/mob/items/lefthand.dmi index 5bda3bc7a3bc2eeff3b4a2fa6e7001605f75ba53..3f2e4217f4c01975ddbe7cf948aac22e0a82f4ae 100644 GIT binary patch delta 8053 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 A3IG5A delta 7720 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 FzW^E|>YxAs diff --git a/icons/mob/items/righthand.dmi b/icons/mob/items/righthand.dmi index d44cff61fd7b39053a2df142812ee44770473d71..5c4521e6e6793f7c42d34f85afc176d06a2acd08 100644 GIT binary patch delta 7238 zcmY*dbyQSew7#Sw>d+uar*uhoONw+3T@uog7gPiU#6f8hDd~`|VUUm%L`qtbM!Ff8 zc^BXB{qgp?cdc{JI_up1?S1y%-#$$V_*04aZ`g1cKeOXrV<(`_<`3l83u!~m&7n{s zAo^f;?;!ejXLhzH7G@)8Fw|XBgRGIeX8a4638+a~b;AR9^!2Sy7}`-ifzBEQ`p>D0 zqfAT4Jlut>Tpw4AfWe z`d({4IWmm02s6`ii#~oSisx{75px}l5qke80`KNvP{&ElM49c-&D9g>kl{arUdL0b z3^0aQNFa3tJj4H$^OJaM-&mEeYJE=!h$yU=Ef|v0aSxv0`GIK-%Kampw@>sgCCH*q zXUrx_pCNeFB}#0)e7UI!h&UKvjfiSLyG7dAQe|f5X>7ji;Sk~%?-2{L-5_s8Uy4_j zcZhr4KgKR26hwr}M94Jw;zWe=#|a2J{vLc;LljPfLd{t(CaK&u#7;_!iyurrt$#@L zeK(qj6>WnxN?p?2r4q6vdRZ{ST7jR+wpyyWSMbeHoFr6s&b*aC0@j7=rT92l;{X(^6E-%Oxc)uvd9Y^Z(ZGzxz3R0TM}I>N)Z2GU;fTzX>RPREOJ z+KDpb@gwWZ8r5Heb1cj3*1qTTtHR715|XFeD#-?rlc@uhzhd_}<8{=W_u1-=(;}$9 zb1j(Lj1B24c+6a8;39NBWqx-al%UMZE;mZaf>(5SXVFTaWN^pF$75c- za!YM!Eo%s(n_|G&kt5ppQ{k?GI{7d8)!Qvw0&eXv$i&#I%Xgi&aM-rjJq}(Te>_=X z)!7{<4pY2AL^Q(ovN90H&;@EglGScGLL2u>edXLT+e-!R_vTqiS!X62pP75Gk&xLmx-D0mck62 zB_%hdDSZNK`~UqoGbW}?&!@>!ZB;?#e`T!DU;5fj(*J}Y`mN=5#@qC5Y7ntbFCCyw zlcmgbI5^7fq4aOLHE%n~e@k8C320b^`5I>Ua`W=KC(12I>FN1qJsa++hpnX-8cn~5 zxsvHkeH^DR&j^}#*62tLZUrxu2hLPs@p>>O>hA7khDJv0I0{Ba$rN;SJnR4OSD?z) z1OC*_lqjKWd2YZ4!&rE4fV;G0cc_H;bgf?8aA69yS|Bm9d-}wW%GW%YM$B{8C0*bS zF%>U~&pdfDN>j$J78TH3znVk0ZEeZ$JJ<1Wg4_G_2tJG#Na z&5usa>fDlDv#$lOxF(A+vp@poW?sCGxQAW!;DX+wvXYK#jA1Wea_85f&4u`6wU6*Q zzV^gzSdKVq^MsudMkLUQYwlCq2U$Q`zVj#>qD-S8L2XWR=f2fpA%^kJ zec3ex+g$hcm-Cm5F?U3q+UYmNc*B`yKYI?Q2`M)`HFkMx!^XjJ13a_y<44*aT_iXi z9oGb7RMa%JwJBDIvm5?y_H3Nd6&DpXj*4w=$g!FUttyzwf;IcnxS#Tf^kkS*vU z--~?0ez-O4Qm2Dly^RAz!^R&(@`~f}`SNpfQxzBYg=0}*DSFJ#uLX558Q66QX1}JY zO{-Xtrj3cT!@^JOr%`&FVv`X!1XWbjl3-0j2fxMsWmSFU*%S%VJ!5<^uX*?MEp5nT zbv15AQ+vmk1ml_>A75r<(C+n1kEeHYk^x zsvW9=&_>Kuzz;Qrwt6LI<*in7a`LFr^{ym#t@G|pR8f&BuSEs`NSGZm$)yL<03?`x z!+5PZV!$+|hQOSfK3Hk*-ZVON#(}$aabKN`lp7;W3GApO{}R2HHE3&^|6g- zxH(4-1;JfwH_@oae?gCnvtdw-#XWI79fU%N&6Lzj^<#i>`H1VG##WiRN-Jefe=`J) z*JHlb>{V>6>&bu{_$HL;&cP>D<}-!rk>bOcjG&&bu3vwq%?}$esMT%nwA9_SYNRSk zuc50Ry&?%A^&X!4!^^0(9e0A=udN7svTcWcT>4OCXWFdp>Dh8B`rD@b)+Bh6(}uAh zn*`&@&8XEErjg2j8>+s2evbuMPiAZ~tl)6?c zd+rU?$*A-$)FY$_j}95*CGc&P{6wL!sA~SGz&q3{=t1D_uNVo%l$-dy5=wi&sLKV( zV^jb`&=M(Y$MH|rM44wsV5#vsRorcNW$MlLu&QgnUOwE`g;sVlr7{V8Qzk{mWlAlNym7OsGsJ^A_zD;j-9b+r zdVW#(q-Va>gP`r~e1$RoHLF{h7z-DTU8hoO(2il==o;yL-?n)f-5a+qxv!v+eT65B zdE!IQ)hKkwfZY`6dKncQg$vZy*2naMLbeiN)nt6-e4iL_CVot_=w_FxETvUN_|&Q3 z5Jot*J=s7&M^s72c*^Nm9?@(`#NX$JI^IHUB$WxmBd7YdT*fgbd|ufIh0E^E8Lj44 z595F8Do?jjHOlS<>~IO6*%8Q{ai3jdp1Ad5r}3z{l2-UMzv$p5VyV*&3_vY@OTM6ecIa;x{jtYre>Wr&U zshVI*#Gm#m{{rOWex8+1=M2aBn0<&HUSVV2D7D@4L{&ScM&2P%8*V*%H7@j;!7_b< zySaaC$b#X4FM6~A4^RW+pOU~Pitc=Q|H$BNL2jc6aKHHlUL!Kz+=H@=MvPy`3%dtV%NDZ+gQcB97IUOl? zaFkV4#^7e&Y}boBOIRbHeIXTGiFHh_-+3z)k3TK#B5-_r`mvue*!+h0_KdK+pj2{% zYjTYxutx=N?WRY@J=(8d=NprwSjZ4nJZVJkl|LXSabu+YZf_RxuW*fOSp9169SL0g zp7WeW@?1Bc{|QajBZb33i%L`aKX1Y<)A{=ry4PB3mqHqcG8bgxqqc8_?}(7g`iPY< zjeE~%(EqFPASuFisWQZbAWE<5HSH{^?4M2weCt=o>mhW@+B#8vxMsAyfV!dnl z|EV#^!pEo63s#!ds0jDYe27{hiQs)=3M-*pox^D{WYzy6aIiI| zDOSF6%TY*>!1kI!&ji^O3ri;*el`}>84ZgoD&o3W768A%!gulFX@oisjk>i``H3VK zHa6U}v!sk_-bdf2=LUYYN8*7o2?_VZW=Q;<`;wA1nLE})zy26rXV)^;1k7hVZxkNf z87JPRw=0@(lG~)*U6Fg3a70FW*5BVx29rG`;pXOEn&}-Fc;5ND>JW{RpPHJ=t*xa9 zXrYH%gAz};t7|b3aeDexXS%$$*3hNS6KupT+~3BM6GXGxG>?pp;e)_+7))H^ZF_G} ze^9Avc+D0KkBrP+h_i?9a8~Co6*6=?JKtvEajfr!%+t5(Z`|)Lw6rg8E{8sqWs^TD zTDFtO8omx_gl~|p*CZ~`y-5~s=`IOVR9UGFIq}?^u<*($Dbc*w7=K5EFe)l)i^0Uw z(mnR%!##sfewl@Hpy$rfxxJm8inexqOnf}W{=&ZM@M4U0BX+0z5_~L(Hp?iIrLt-M z=y+rb3trAfAac}cSgdriq$o)dc{T+C7_)md1!eE1SXg}CotWIq$*-6WQKS|UWm2rI zXAwJ|!J9tMO(rKKN6;!MDFMLai836Byi?_V{!DuR{{1bGfpfv@KIAlNNI9jp+c22A zrlw{)7H(?FwG{Wwi5yx~R9viRWktV)T81VJ?2`;^j5;7u608Z5eSHy?xW_oj_K1ZjDU zcPZ87CAg(9<qZ z=f3sq$n+&xq|V=Vc)~IW@v|2wu`~$C!txll^K1vnDZ3tgovic`&LOib@PX>L(UIfWjhIUN<#&#TYu&)8&B+2k(b_m znd?8VRu@OQ1^)SZYk(5&0RBN8T^a)!x|XGm@%0a$I^wpsH~Frb*UR^2$mwX1XlRnL zehAi7QCE+fgoATq*?6OW7P}7B87X^S(;M&&S5*mm!yhFz3fx;y@t;q9$JWu&p<-&9 z=Hl+&b$+y|Gbd+NTvCDyh>D5PzK;zKg^}WVdfF>1KleE`G6^LX0QdIxViFV8gMuXc z2L?zP855V59F{T9p5gv<7c2Oc_mzt#h`voVf4jGvxh|aM7Y1blPGe8l6OXGpuE*Eb zis~C1b4XCf-#=^w4iZ63-oT9cs5C=e;EYED(E}P*CdUa|d3@aE$s~7q`Kdoe3l?z`eI-(4iFyrS9WfK|U2FtGvV5T*vt1RVAYgL?`AhxD~JfeE;zS7ofTC zX81kmHjSXdQyGTZ*~Z8eI`Lg(lW($rxYxGjh|eF8P=)~pJy6nxTG>demVos7Fe#|$ z-~muO`an-+4ptE+g| zLs_iPzL$-S83OIa28Hj??qYOu7rV+`-Q9H-&i3}K85tRGva=ce(95fZUjv?Pi_1N|lg0&rwv@1iHiE1Z+lfRmlK-LqoPl z1_mK>UbEPf4FNP3lV4B}n=ax^n?-n}I7el3yfwuczHiCjpHkV?z}a&eHi*(Sw7*0| z0%HR4SKca<7bdxLk~?~8PAg>hVr*>8Ayyo&&=NWdj*hnco!pkADZjd{`FSyoW!n3l zZGVsn_AGW_@qsJH_N+`|t}USF9iEFE>ivrz&|7b-h2O^~#id!qau0(}6P;?&2?p0; zYV&c@`MI-EWWVMJ6)q*s4`Z0$=HnDS#fG{5SnAXGHUTb0j;_C(4@Y}=V=qtW_QAV? zQsE|p?=xvXgzi6Bw|o%mf?%uFAe;3RcXM-lXm0K{y@e#SdFU$wwEx+|&vJ%xi=n{D>^ef(;R&{gRLqF{=fCs^e9 z07gC?Zf>4Y)$!XVa&1pfab0eOHDi z&wLn<1v%HXdE}$c53-LmHD5WbED{5E{hRVxy-<7!jPllXGKJddEXb3U%q;6q&`2j; zShd*)Tz<9uO2DMTa*xkk<94)idQVrOjcvNe{!kzaiP|o-k05b&)-p$Jgj-tLB8gaXj?w@ss?VV< zYI%O(2Nyw{Wgb@wzi$#l3<}o*c7CDY2HJYAmciQ_h6i{i-c$@5_wVYKjW-c5@0rJ5 z!k^b{zMlx98|TL?x^+X`P*{2~S|DIfFq2k#<-!(Z%LZETg+Bg3C>v5ThY& zQSbhFY18OKkCL3P9%Klgg*VK~&_OEMa80grXqcHvkO|suTAj8UI3akH212ZWMmm5u zBQrC(Lk-H2v~+aI%C(`y3=3GyN%E<^(S@SZ-=Cj*zkQ>GpY@x(OGBaOc0AW%LA8lq z6+Viuio};X6St8k*30$j>hLuL#MyrcIl)Ifa8@q555iM-P`iZ@jC415qnKHH zVv6t@JMhwe+5j7|SW!#_V}b^Bj-6sStDuxzMr zY;NL!vogz{cg!lvg!fffES~(Vdz@MYv7rlrHs`|XnXN{jWzE#hlFCYT-NHFr)J_3A^U#H~cnZJObcGG&AQ#QT@$k2AU^2kO z$*B&I$Yb^rz06jd{Wsr*25isXxYIL`&|vteQUd3_&zyGH4#GaYGq}`VkNoh z$!}b!l>PFP>P}*pm42Kvx=sNx@`kce&jub=s|&=z-nXnGRGOskCqp>gtEs~q9QVNC zSYH({og5V`AMNq?hYR8+=v}q1V|4VxH^=7EpAEYItg_9T2X7yKzZ*oMZ6VaTL*3Hf zuPG`jIx9S#pOb?VI3L8Rnz1Oe(0{+zQG` zqP{EId7}??DsL-Z0cY9ZfntL2>`i)pKHK_S;6mMB>h#xz_$NqN_n(4;+4Axqal5@h zv;`5cq+}RB=NY}@?;Ld-I!OkFxq(hv2ebfqpsK4}rnk&qNYx*HUb4v}6!>F%XrP^2Xmq@)|9L}F2vP*PGrI#!hK zk`(qg_&4+@A9<`QRE--9ZMgzi z&k+pgFV=Y2=|JxsDaj?^Yj&U=JkpjH0JKI^NS@Y+ei0K#C-ZuaSMh2}y^SpKW< zvNtL35+ZklE@`$AZ8+DLFJB*TWQw=X-q~L9Y{i_quLxq!n^C^Ia{VfeZwBuJAX!JI zQwoaneMoYAB_1GEfAjz`Zf`*;Fpq3lQHOD--bvQVt?Qq8@0@>~>&^am$tPTODz*bd zgV%w~G{&3#xS9{ix;0M!^m^2eaJsV06j(c{1rq9}{+!!s4Roez@hh*v^2X!6OS8#B z$~mMbrLc1k_EFm8kSWDWjl~UbgRJNVoMIQx*7fyuuUOl=_i$)0`CeEtI?3)N!uRHx z!@1@^2uXBM?IbP+>OE)?y0dcqRdtC;3<_9znYPAlr$HD+H8Ygq!;p4^sRnn!u6H5> z#X0n{7%2xl6uiY@sL#z~myXh#d0kq-%))~6>_z5es5DpCgFek{DSIaiXE5^38wEv0 ze1OC6oQK$ZPN_b^byIN$<;W0E`17)L^Zw2S-fy?6nJsKzzgZx14O#Mz-&h(?ML$4^ z16IB|gR1rz4jp&4ENa+!-x0X;XDZRt7rp3inKYa(6;(;a{u5uQ7ez#ae!-_bCiFEt zvXoeYUl#trn8dG!C_w*BJD30~e`|ezx!et2a$U2Z>!d(&}1NVI4S&DA^M^g0L3i$uo%)Pl3VJ14qB$HV(BS(j>?FUe=TEc@WzUd-a9s6{c~05X=O_-oc?#j0 zM=c@}jLgjSYL%u<`m`Q1mcPzQIS#kSh}+m^>z5sVz+&6J?0d9phRrfm?u&es{@cmU z%)F5V=SdwFC#U#NL)dQ(;yhOPZ~O8hDRbK~>HW46Xyt!?yaQ8OAt#hRs8h}OHy;Tj z=KJ4NT1%YpNcFxg@0ik3jvAW*S||fC0H@_R0;Gp$GqaH<+zj$?y~ zfDhHuF>``&dFOb2{^<>3?lVTabMc9>GxJ!H9|Ga?)!3uL;$qIQ9K{&w^drAq+iZP% z$}7W}!O#6WglUObc--y zi!fG@KLu4(frd|YMLWIJad(%GW&h5sbT23`Odd(8;Ioc}Zm$?rM$FzkU!B9gOcQfw zp5=FG|3&bX{&!bL6eS|YHcaG((xXSO5G{ z39iU)MG_GanK;)rYzrn*dER_Gb|A{t%JSTp_Vnbp#r)zoAjE#O*j@m)c*%}byqJ3L z@FTQ9$Uk2QI0AN>ZDxMD1`OOPsB8i1)JyVRrZ(`+(F!(5I zB9_|XxI4No)SlzPgJEmDH&oLKq~hY@xPX9wz{A=s{r)K@4-b!ylu8qKY|t^z2Yr*? z3*HsiqSEN1)=hWKc~k-+ z(oN+>aw!=vQ^aAnZ%4m<%i4;?jDtZA{GaD!FIGw{zJgkE*J#xzcDVm2Xw_Wg%LZGGoVp$MXA0wwe#(?jZT z6RInr{?j`Y0M zc@uR0yTl9fGdo4BrI&zu)2xOI8SOg4WxcCH5`_*=slJLvlz*&(TvI96uT0D@D9E_@ zI8D#GrT+DB52-wzZso;EpKmiiJUo0-{GMp866^ZOUaYuVHs8thOLZYwP}KGE#cM%BH@FochAC5nBb-v^d)xpToQC&?iUsFT)rFV`j5Z=+sWiu$;}Z?BgkS;Z)=aaNGdiD8n*3bN6?&QNh%&o#Dv{sz2K93&giXTIZaB%hUJlD;xq~&qjb2+nWAdj*pF}gdGt`tZ;R5iO zK{eP$#N(EsRjDBR^jbK8gT|*9qLP~x-IgCoZ|=3^885G4GuTHt@11S_^7f-=z_ENS zZf`%*Q_7Kc+9#T;1rZFfu#t7f6n5IE&JJmH^w{}uaG1zBKm5Il9=TxbV7_ICdZ~;9 z*d5LC@)g^%=*3=Lp1l`bw?*|*{^PoG?(?j(ZK>}o#yj<4tLZ4Sn!{~kAClcUF3cBt z&(j8~ljV&Jkk2@-v}QUo_j%+}?e0Q#*PSe-h|=_f&a;J)5FFWd=>GI?+$gm+!1;0J|nKe?Hlmsj)U2TL0*?cEOKW9vv7T3YR@6pl9F zLqAMYdcRK9r1Tr-O#kKmr>R`?Y(`rXEn6$5iB!v6e3GB&E2pvVm$n3Nl{Wc;raBp@ z0o5V&pJ;3483UXNR`_pvMRxOww)^I6*n1t&TKq9E^U(|PXS_9*Et42%H~<#=%=)_d zlR!MDC@-H^dUS|9JCw0{&-=@Nxxz=j7t^q|b->%_R$Q!k+?eHFTzoSJG@|})*)-fO zPCJjM!NiddD3j|y)?AJ%!SPDE#18yWP`G?pH?`%X?<&Ms(DpBY#$CgqTyw^X z2Ie%rJ_TO0WDc%emAm?ceDRWFjare)fS^na8UMOMX#ZB%IlGMdo z`fr_C-5$;ONQkw{w00gp+R))^nJGS&QMR&T<>ch#b2#J(y5{rfpCGv=`D{{v<#}Xe z5)Qw zZ~j*dsIdQq^XhAm6VV$MY-lAZu+M-3hvyuGSwv zYD5}K`fG!?RSAj}yR?wr4e5YGp{)iHA(6-dMi(V0o=UL{V=h$>+x{zEkoG+#ULu}* zisMMQA2sX0s?E$SK+1L7%!>Y7@>OxTYU|V%mX@)aFF*5ZepO5QvaJNE8%c0|Ss<}Q zS!qS?O3wTks{#HefeQJlp%wc4DN}TUxWMz?zc;M=-^mI|-vz0tm#NQO z*vo4K?}F1V*G5aiGF>5~yJGK_7!3xUA5j4xJXbV3Iy%x?oFk_NeYPJJkuP}3xUQ`n z&VC|h17bBq!LZR&^g8}AHUBe5!JI!tzMeZ}UH(y#f!0=5kpv9BKv7ZAzVqVZV%vh7 z;n@Wyr@voa2M#A`nu{A5d8&u1ZfrCJzMt z{2K5&EbLCE%JW63CG;3`>r}%VDr)NR=xCzWV@e}XXGAw??_$`rM>(4riiF|5UlvkI z@lgESsQno8msmwhqXAA*a^QypsAx$)48jhy`dhJT*?({_Cr64qPuHn9&7mxPv@f&){hB>J%?|_mCMtXW~s7xtBr8WVZ!s}1{{KnVXY~D??hd1>LjEthz*ByGmK4_#kko-0bM(n4c&L>gJfXNJv z8o0o=xnXlkJq<(hLKKyhM9$^POG`f-65Q5t)UU$466=nk5m;U6@$+o9&R!9Bt%ALH z@j^O+6)z=nZn;==ULStJ90U?m*u(;>e6q9^wS@Lg@^)S*isglYu|s;y$30@Z#9t-{@|M%JY`V`^J}*Fcynj zI>$oR`r%970@>d{<8j~iN=kp+5Y`84F5l6_nwq7)_25-=OG~49Lnpo;y)iv)j6NJuE3K+hf}8*$A9K4_VMgxmHLJ?!mh3I3x1xvQRo(77FL)pS`|$ zbi$@0Gj{Coa@RWQjl1mLy*6M64l_lZ-&voBR;)Fh_`d8=;NLAPQF!+3tuOZCSmQ#R zj|mjfS5K2N+QhV)*GoNq{J1kKD(cr@M+euqpRGkcAt@US@i zxLQtaShXk|8-&5^%BiFDwHQ9*73XJ7J?^q+-Lf4TqH~1-j1}hDmg(Po1rtjm5q+ME zaJ?a;Y^-7*&48azKCkKLAC19&adnp-vo6-#v!9A5T`oV^BaKgj0CUU8c8M@N)C=Z~#8v-JiJ!o5KYWyS`F(jb1lMQ+XDS>_^`s=4G7U zT@5hA6F|R(g#|(~vTlg=G-hPD^$ZNI0lj^FMcs@bUC41?Fa$*i`rNhj0wtqmi8~!u@F+J%MGfPKn)F24^K}VJQ<4WKs$X^RU+W$?m~NSkVpopdGIM4MA;dYwNU&K z2t?1o0O{uoXttuMDZPWEBUGH2AXPAJT9R45^TN6?ZuV{q;xOox;H-RFn zpsr5Bu9?XJAs9y}$ApcWTjNu+D@JD4t)0|OjEupWbbgqy}G#E5+}* zB+Z+jg(44@{mbqJq~Q6YKpbr_j#}EHhqa7ARTc}Um9`;yD)5KV@28hUQM}BV@@&xY zT(}g$n>Y-$;7W1${hYw35@yd>X<2WOCgP!HVtad4p^A~=9l#5$>Y0-P5LV<@?$FY5 zCa0tjVQ|&eJQl2X=9_^K(RttYx~<<@P{Nx9{n4}kmdN% z5Q+YnnBbc6INCItbP|Cc#pvQfl-ha}-x-+sDM}sBdfo!0P8X9b)_;@%A&8Cfh1KDL zTR?xd^j(N|zPg|u^Y~iX+7es@o0^+f*98R>m}i5Rel>1+$KS`UUNP&xQ7Iq)YT-W% z141hk0rsYopS||re}$|m+h}r`^W7}y^0$;yf8HD`;JJ8_e*4D&*?K(-@D}3UF)YJ%kV(RB@AvnDazETWJ zyXE6`4@VvvevnholAwYF6bCnV7(8;14JP%mwl<7bu^bXnDm;sI2I}dc1cHy2;~C!{wIi zb=wJv$^()2rhhxfq9Gk;?cHz#8i&o%Li%ig2E~MhdMmZh7xu8Vv`t9%c@rpL3><}07E$sR7IZg6i zr9@aPR5^c)k8?)Yol;9}H~zlKcF9KtCfpHmqJiA%)B?|R*_MfU(Qb-hPeD+iXEO0q z1qGW?7o6peGRojoSJ~5*5XQSCI}#D^Tg;fjI0nhuvG5xGagRDzL_rT7@}pzCA|Z!9%(#P^-KkYpvj0|QiR zYilF>OMRVFwYI~pAlUy-Sk35ivv#QAJpCTbe$k>kQ{1!TGh*W{l2=ht5eVswfvEu> z>_^$bD-T`grOHZ6m2Xo~ML}XYm&gE`gS#8|`de@Bt@d!z(AHnXKc!jUTg%Wv2b4Br zc@%uInOGcB(pb6DW9?kBo44(f4Vw0%>fDZ{kCk1U|D@1}cyaUwA4~cMlcF83&7-#v zbkg1=J{ZsV2jGo=ydtg9mJkS5k(c_*h`lo8FQFf`W?P-VLlU ztyjruX&lxzHk{B&-0zHyks`ICvorr9*Qm(;;`WGpIBf(3M0}^P2M#OXNZv{NfGFY1 z&xD`S$d^2DfNU3Imo6l4%YQM)LqVZqJCMfzc)HeBtM<`LNG4iXvbEh;Hd zYbkjt6Z}^!j!`!5@X$*o7;b22n6Y8p=$3Z~ad>K@Xx}dmNO#dPe z_6D*dd)`cQx3S8&fAW`R_-z6evSWOf?CnWHGa}cjx0m0lmFXg z=2zvLw+1JWrK_l`zxCdneDSG0!HQe!#&$pxG@iz9sU(LVEql2ae+%ddqiLGEiP;z@ uqW5m1k04{*{!x}IdC+?IA(|YS{8yHviA?Q1qRR__nu?;PLe-<^ul^4SX@2Ga diff --git a/icons/obj/64x32.dmi b/icons/obj/64x32.dmi new file mode 100644 index 0000000000000000000000000000000000000000..84cabfc5515f120ffddd2b52723e107f455727db GIT binary patch literal 2849 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 literal 0 HcmV?d00001 diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi index e70275591fc4ea810bbdf564cc1ad63db9bbad72..85e245ce9fe34072235d2bdc9a21b75ff1a70232 100644 GIT binary patch literal 10805 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 bpsMmHsSvRVSf+W diff --git a/icons/obj/vehicles_36x32.dmi b/icons/obj/vehicles_36x32.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f32d433916ec9a6073051b27b89c3d50dfc1f4d4 GIT binary patch literal 9351 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 Ky6Tnb`~L?>m5}%V literal 0 HcmV?d00001 diff --git a/polaris.dme b/polaris.dme index c22e8d991b..c5b957df64 100644 --- a/polaris.dme +++ b/polaris.dme @@ -193,6 +193,7 @@ #include "code\datums\organs.dm" #include "code\datums\progressbar.dm" #include "code\datums\recipe.dm" +#include "code\datums\riding.dm" #include "code\datums\sun.dm" #include "code\datums\weakref.dm" #include "code\datums\autolathe\arms.dm" @@ -2272,6 +2273,7 @@ #include "code\modules\turbolift\turbolift_map.dm" #include "code\modules\turbolift\turbolift_process.dm" #include "code\modules\turbolift\turbolift_turfs.dm" +#include "code\modules\vehicles\boat.dm" #include "code\modules\vehicles\cargo_train.dm" #include "code\modules\vehicles\train.dm" #include "code\modules\vehicles\vehicle.dm"