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 5bda3bc7a3..3f2e4217f4 100644 Binary files a/icons/mob/items/lefthand.dmi and b/icons/mob/items/lefthand.dmi differ diff --git a/icons/mob/items/righthand.dmi b/icons/mob/items/righthand.dmi index d44cff61fd..5c4521e6e6 100644 Binary files a/icons/mob/items/righthand.dmi and b/icons/mob/items/righthand.dmi differ diff --git a/icons/obj/64x32.dmi b/icons/obj/64x32.dmi new file mode 100644 index 0000000000..84cabfc551 Binary files /dev/null and b/icons/obj/64x32.dmi differ diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi index e70275591f..85e245ce9f 100644 Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ diff --git a/icons/obj/vehicles_36x32.dmi b/icons/obj/vehicles_36x32.dmi new file mode 100644 index 0000000000..f32d433916 Binary files /dev/null and b/icons/obj/vehicles_36x32.dmi differ 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"