Here, fixes locking properly. (#13074)

* Here, fixes locking properly.

* Done

* Happy now?
This commit is contained in:
Pieter-Jan Briers
2016-12-27 11:57:41 +01:00
committed by Probe1
parent 3275888e64
commit 2d5eb2df56
22 changed files with 105 additions and 85 deletions

View File

@@ -61,9 +61,6 @@
for(var/matID in starting_materials)
materials.addAmount(matID, starting_materials[matID])
locked_atoms = list()
locking_categories = list()
locking_categories_name = list()
on_moved = new("owner"=src)
/atom/movable/Destroy()
@@ -247,8 +244,9 @@
// Category is the locking category to lock this atom to, see /code/datums/locking_category.dm.
// For category you should pass the typepath of the category, however strings should be used for slots made dynamically at runtime.
/atom/movable/proc/lock_atom(var/atom/movable/AM, var/datum/locking_category/category = /datum/locking_category)
locking_init()
if (AM in locked_atoms || AM.locked_to || !istype(AM))
return 0
return FALSE
category = get_lock_cat(category)
if (!category) // String category which didn't exist.
@@ -259,27 +257,28 @@
locked_atoms[AM] = category
category.lock(AM)
return 1
return TRUE
/atom/movable/proc/unlock_atom(var/atom/movable/AM)
if (!locked_atoms.Find(AM))
return
if (!locked_atoms || !locked_atoms.Find(AM))
return FALSE
var/datum/locking_category/category = locked_atoms[AM]
locked_atoms -= AM
AM.locked_to = null
category.unlock(AM)
return 1
return TRUE
/atom/movable/proc/unlock_from()
if(!locked_to)
return 0
return FALSE
locked_to.unlock_atom(src)
return locked_to.unlock_atom(src)
// Proc for adding an unique locking category with a certain ID.
/atom/movable/proc/add_lock_cat(var/type, var/id)
locking_init()
if(locking_categories_name.Find(id))
return locking_categories_name[id]
@@ -289,6 +288,7 @@
locking_categories += C
/atom/movable/proc/get_lock_cat(var/category = /datum/locking_category)
locking_init()
. = locking_categories_name[category]
if (!.)
@@ -299,19 +299,51 @@
locking_categories_name[category] = .
locking_categories += .
/atom/movable/proc/get_locked(var/category)
// Returns the locking category for a locked atom.
// Returns null if the object is not locked to this.
/atom/movable/proc/get_lock_cat_for(var/atom/movable/AM)
return locked_atoms && locked_atoms[AM]
// Returns a list (yes, always a list!) of things locked to this category.
/atom/movable/proc/get_locked(var/category, var/subtypes = FALSE)
if (!locked_atoms) // Uninitialized
return list()
if (!category)
return locked_atoms
if (subtypes)
. = list()
for (var/datum/locking_category/C in locking_categories)
if (istype(C, category))
. += C.locked
return
if (locking_categories_name.Find(category))
var/datum/locking_category/C = locking_categories_name[category]
return C.locked
return list()
/atom/movable/proc/is_locking(var/category) // Returns true if we have any locked atoms in this category.
var/list/atom/movable/locked = get_locked(category)
return locked && locked.len
// Returns the amount of things locked to this category.
// The length of get_locked() with the same arguments will always be equal to this.
/atom/movable/proc/is_locking(var/category, var/subtypes = FALSE)
var/list/atom/movable/locked = get_locked(category, subtypes)
return locked.len
// Checks if this atom is locking anything of a specific type, if category is not provided, search all categories.
/atom/movable/proc/is_locking_type(var/type, var/category, var/subtypes = FALSE)
if (category)
return locate(type) in get_locked(category, subtypes)
else
return locate(type) in locked_atoms
/atom/movable/proc/locking_init()
if (!locked_atoms)
locked_atoms = list()
locking_categories = list()
locking_categories_name = list()
/atom/movable/proc/recycle(var/datum/materials/rec)
if(materials)

View File

@@ -89,7 +89,7 @@ var/list/all_doors = list()
var/obj/structure/bed/chair/vehicle/vehicle = AM
if (density)
if (vehicle.locked_atoms.len && !operating && allowed(vehicle.locked_atoms[1]))
if (vehicle.is_locking(/datum/locking_category/buckle/chair/vehicle, subtypes=TRUE) && !operating && allowed(vehicle.get_locked(/datum/locking_category/buckle/chair/vehicle, subtypes=TRUE)[1]))
if(istype(vehicle, /obj/structure/bed/chair/vehicle/wizmobile))
vehicle.forceMove(get_step(vehicle,vehicle.dir))//Firebird doesn't wait for no slowpoke door to fully open before dashing through!
open()

View File

@@ -117,7 +117,7 @@
// /vg/ vehicles
else if( istype(T, /obj/structure/bed/chair/vehicle) )
var/obj/structure/bed/chair/vehicle/V = T
if(V.locked_atoms.len)
if(V.is_locking_type(/mob/living))
return 1
else if(istype(T,/mob/living/simple_animal))
var/mob/living/simple_animal/A = T
@@ -146,7 +146,7 @@
// /vg/ vehicles
for(var/obj/structure/bed/chair/vehicle/V in protected_area.turretTargets)
if(V.locked_atoms.len)
if(V.is_locking_type(/mob/living))
new_targets += V
if(new_targets.len)

View File

@@ -223,7 +223,10 @@
to_chat(victim, "<span class='notice'>You suddenly find yourself locked in a cage!</span>")
/obj/structure/cage/proc/mob_is_inside(mob/checked)
return ((contents.Find(checked)) || (locked_atoms.Find(checked)))
if (contents.Find(checked))
return TRUE
return checked in get_locked(/datum/locking_category/cage)
#undef C_OPENED
#undef C_CLOSED

View File

@@ -415,7 +415,7 @@
if(istype(AM, /obj/structure/bed)) //This is only necessary because of rollerbeds and swivel chairs.
var/obj/structure/bed/B = AM
if(B.locked_atoms.len)
if(B.is_locking(/datum/locking_category/buckle, subtypes=TRUE))
return 0
AM.forceMove(src)

View File

@@ -63,14 +63,14 @@
return
if(!A.powered(EQUIP))
return
if(locked_atoms.len)
if(is_locking(/datum/locking_category/buckle, subtypes=TRUE))
A.use_power(EQUIP, 5000)
var/light = A.power_light
A.updateicon()
flick("echair1", src)
var/mob/living/M = locked_atoms[1]
var/mob/living/M = get_locked(/datum/locking_category/buckle, subtypes=TRUE)[1]
M.Stun(60)
M.Jitter(60)
visible_message("<span class='danger'>The electric chair went off!</span>", "<span class='danger'>You hear a deep sharp shock!</span>")

View File

@@ -43,7 +43,7 @@
var/string_pulled = 0
/obj/structure/popout_cake/Destroy()
for(var/mob/living/L in locked_atoms + contents) //Release all mobs inside
for(var/mob/living/L in get_locked(/datum/locking_category/popout_cake) + contents) //Release all mobs inside
relaymove(L, NORTH)
..()
@@ -138,7 +138,7 @@
if(!istype(L))
return
if(locked_atoms.Find(L))
if(L in get_locked(/datum/locking_category/popout_cake))
unlock_atom(L)
else if(contents.Find(L))
L.forceMove(get_turf(src))

View File

@@ -17,8 +17,8 @@
..()
/obj/structure/bed/nest/manual_unbuckle(mob/user as mob)
if(locked_atoms.len)
var/mob/M = locked_atoms[1]
if(is_locking(/datum/locking_category/buckle/bed/nest))
var/mob/M = get_locked(/datum/locking_category/buckle/bed/nest)[1]
if(M != user)
M.visible_message(\
"<span class='notice'>[user.name] pulls [M.name] free from the sticky nest!</span>",\
@@ -39,7 +39,7 @@
src.add_fingerprint(user)
/obj/structure/bed/nest/buckle_mob(mob/M as mob, mob/user as mob)
if (locked_atoms.len || !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || user.stat || M.locked_to || istype(user, /mob/living/silicon/pai) )
if (is_locking(/datum/locking_category/buckle/bed/nest) || !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || user.stat || M.locked_to || istype(user, /mob/living/silicon/pai) )
return
if(ishuman(M) && M.client && !M.lying)
@@ -59,7 +59,7 @@
"<span class='notice'>[user.name] secretes a thick vile goo, securing [M.name] into \the [src]!</span>",\
"<span class='warning'>[user.name] drenches you in a foul-smelling resin, trapping you in \the [src]!</span>",\
"<span class='notice'>You hear squelching...</span>")
lock_atom(M, /datum/locking_category/bed/nest)
lock_atom(M, /datum/locking_category/buckle/bed/nest)
src.add_fingerprint(user)
var/image/nest_covering = image(icon,"nest-covering")
nest_covering.plane = ABOVE_OBJ_PLANE
@@ -90,10 +90,10 @@
qdel(src)
/obj/structure/bed/nest/proc/stabilize()
if(!locked_atoms || !locked_atoms.len)
if(!is_locking(/datum/locking_category/buckle/bed/nest))
return
var/mob/M = locked_atoms[1]
var/mob/M = get_locked(/datum/locking_category/buckle/bed/nest)[1]
if(iscarbon(M) && (M.stat != DEAD) && (M.reagents.get_reagent_amount(STABILIZINE) < 1))
M.reagents.add_reagent(STABILIZINE, 2)
@@ -101,7 +101,7 @@
return
spawn(15)
if(!gcDestroyed && locked_atoms.len)
if(!gcDestroyed && is_locking(/datum/locking_category/buckle/bed/nest))
stabilize()
/obj/structure/bed/nest/acidable()
@@ -109,5 +109,5 @@
#undef ALIEN_NEST_LOCKED_Y_OFFSET
/datum/locking_category/bed/nest
/datum/locking_category/buckle/bed/nest
pixel_y_offset = 6 * PIXEL_MULTIPLIER

View File

@@ -17,7 +17,7 @@
var/sheet_type = /obj/item/stack/sheet/metal
var/sheet_amt = 1
var/lock_type = /datum/locking_category/bed
var/lock_type = /datum/locking_category/buckle/bed
/obj/structure/bed/alien
name = "resting contraption"
@@ -52,14 +52,14 @@
buckle_mob(M, user)
/obj/structure/bed/proc/manual_unbuckle(mob/user as mob)
if(!locked_atoms.len)
if(!is_locking(lock_type))
return
if(user.size <= SIZE_TINY)
to_chat(user, "<span class='warning'>You are too small to do that.</span>")
return
var/mob/M = locked_atoms[1]
var/mob/M = get_locked(lock_type)[1]
if(M != user)
M.visible_message(\
"<span class='notice'>[M] was unbuckled by [user]!</span>",\
@@ -128,7 +128,7 @@
anchored = 0
lockflags = DENSE_WHEN_LOCKED
lock_type = /datum/locking_category/bed/roller
lock_type = /datum/locking_category/buckle/bed/roller
/obj/item/roller
name = "roller bed"
@@ -162,7 +162,7 @@
if(!ishuman(usr) || usr.incapacitated() || usr.lying)
return
if(locked_atoms.len)
if(is_locking(lock_type))
return 0
visible_message("[usr] collapses \the [src.name].")
@@ -181,9 +181,9 @@
. = ..()
/datum/locking_category/bed
/datum/locking_category/buckle/bed
flags = LOCKED_SHOULD_LIE
/datum/locking_category/bed/roller
/datum/locking_category/buckle/bed/roller
pixel_y_offset = 6 * PIXEL_MULTIPLIER
flags = DENSE_WHEN_LOCKING | LOCKED_SHOULD_LIE

View File

@@ -7,7 +7,7 @@
var/image/secondary_buckle_overlay = null // for those really complicated chairs
var/noghostspin = 0 //Set it to 1 if ghosts should NEVER be able to spin this
lock_type = /datum/locking_category/chair
lock_type = /datum/locking_category/buckle/chair
/obj/structure/bed/chair/New()
..()
@@ -166,7 +166,7 @@
/obj/structure/bed/chair/comfy/update_icon()
..()
if(locked_atoms.len)
if(is_locking(lock_type))
overlays += buckle_overlay
if(secondary_buckle_overlay)
overlays += secondary_buckle_overlay
@@ -195,7 +195,7 @@
return ..()
/obj/structure/bed/chair/comfy/attack_hand(var/mob/user)
if(locked_atoms.len)
if(is_locking(lock_type))
return ..()
for (var/obj/item/I in src)
@@ -240,7 +240,7 @@
/obj/structure/bed/chair/office/update_icon()
..()
if(locked_atoms.len)
if(is_locking(lock_type))
overlays += buckle_overlay
else
overlays -= buckle_overlay
@@ -249,7 +249,7 @@
/obj/structure/bed/chair/office/handle_layer() // Fixes layer problem when and office chair is buckled and facing north
if(dir == NORTH && !locked_atoms.len)
if(dir == NORTH && !is_locking(lock_type))
layer = CHAIR_ARMREST_LAYER
plane = ABOVE_HUMAN_PLANE
else
@@ -267,7 +267,7 @@
// Subtype only for seperation purposes.
/datum/locking_category/chair
/datum/locking_category/buckle/chair
// Couches, offshoot of /comfy/ so that the armrest code can be used easily

View File

@@ -331,8 +331,8 @@
var/distributed = 0
if(locked_atoms.len)
var/mob/living/M = locked_atoms[1]
if(is_locking(/datum/locking_category/adminbus))
var/mob/living/M = get_locked(/datum/locking_category/adminbus)[1]
if(iscarbon(M))
for(var/i = 1 to M.held_items.len)
if(M.held_items[i] == null)
@@ -393,8 +393,8 @@
var/distributed = 0
if(locked_atoms.len)
var/mob/living/M = locked_atoms[1]
if(is_locking(/datum/locking_category/adminbus))
var/mob/living/M = get_locked(/datum/locking_category/adminbus)[1]
if(iscarbon(M))
var/obj/item/weapon/gun/energy/laser/admin/L = new /obj/item/weapon/gun/energy/laser/admin(M)
@@ -979,8 +979,8 @@
var/turf/T = get_turf(src)
T.turf_animation('icons/effects/160x160.dmi',"busteleport",-WORLD_ICON_SIZE*2,-WORLD_ICON_SIZE,MOB_LAYER+1,'sound/effects/busteleport.ogg', anim_plane = EFFECTS_PLANE)
if(locked_atoms.len)
var/mob/living/M = locked_atoms[1]
if(is_locking(/datum/locking_category/adminbus))
var/mob/living/M = get_locked(/datum/locking_category/adminbus)[1]
M.hud_used.remove_adminbus_hud()
qdel(src)//RIP ADMINBUS

View File

@@ -43,6 +43,7 @@
var/movement_delay = 0 //Speed of the vehicle decreases as this value increases. Anything above 6 is slow, 1 is fast and 0 is very fast
var/mob/occupant
lock_type = /datum/locking_category/buckle/chair/vehicle
/obj/structure/bed/chair/vehicle/proc/getMovementDelay()
return movement_delay
@@ -165,7 +166,7 @@
"<span class='notice'>[M] climbs onto \the [nick]!</span>",\
"<span class='notice'>You climb onto \the [nick]!</span>")
lock_atom(M, /datum/locking_category/chair/vehicle)
lock_atom(M, /datum/locking_category/buckle/chair/vehicle)
add_fingerprint(user)
@@ -267,7 +268,7 @@
unlock_atom(occupant)
/obj/structure/bed/chair/vehicle/Bump(var/atom/movable/obstacle)
if(obstacle == src || (locked_atoms.len && obstacle == locked_atoms[1]))
if(obstacle == src || (is_locking(/datum/locking_category/buckle/chair/vehicle, subtypes=TRUE) && obstacle == get_locked(/datum/locking_category/buckle/chair/vehicle, subtypes=TRUE)[1]))
return
if(istype(obstacle, /obj/structure))// || istype(obstacle, /mob/living)
@@ -295,4 +296,4 @@
update_mob()
/datum/locking_category/chair/vehicle
/datum/locking_category/buckle/chair/vehicle

View File

@@ -169,7 +169,7 @@
/obj/structure/bed/chair/vehicle/wheelchair/multi_people/examine(mob/user)
..()
if(locked_atoms.len > 9)
if(is_locking(/datum/locking_category/buckle/chair/vehicle) > 9)
to_chat(user, "<b>WHAT THE FUCK</b>")
/obj/structure/bed/chair/vehicle/wheelchair/multi_people/can_buckle(mob/M, mob/user)
@@ -180,7 +180,7 @@
/obj/structure/bed/chair/vehicle/wheelchair/multi_people/update_mob()
var/i = 0
for(var/mob/living/L in locked_atoms)
for(var/mob/living/L in get_locked(/datum/locking_category/buckle/chair/vehicle))
L.pixel_x = 0
L.pixel_y = 3 * PIXEL_MULTIPLIER + (i * 6 * PIXEL_MULTIPLIER) //Stack people on top of each other!

View File

@@ -70,7 +70,7 @@ var/list/mechtoys = list(
return prob(60)
var/obj/structure/bed/B = mover
if (istype(mover, /obj/structure/bed) && B.locked_atoms.len)//if it's a bed/chair and someone is locked_to, it will not pass
if (istype(mover, /obj/structure/bed) && B.is_locking(B.lock_type))//if it's a bed/chair and someone is buckled, it will not pass
return 0
else if(isliving(mover)) // You Shall Not Pass!

View File

@@ -154,7 +154,7 @@
if(istype(A, /obj/structure/bed/chair/vehicle))
var/obj/structure/bed/chair/vehicle/B = A
if(B.locked_atoms.len)
if(B.is_locking(B.lock_type))
contents_brought += recursive_type_check(B)
var/locked_to_current_z = 0//To prevent the moveable atom from leaving this Z, examples are DAT DISK and derelict MoMMIs.

View File

@@ -49,7 +49,6 @@
throwforce = 100
density = 1
anchored = 1
locked_atoms = list()
grillepasschance = 0
mouse_opacity = 1

View File

@@ -63,8 +63,8 @@
update_icon()
if(is_mature() && special_cooldown())
if(locked_atoms && locked_atoms.len)
var/mob/V = locked_atoms[1]
if(is_locking_type(/mob, /datum/locking_category/plantsegment))
var/mob/V = locate(/mob) in get_locked(/datum/locking_category/plantsegment)
if(istype(V, /mob/living/carbon/human))
do_chem_inject(V)
do_carnivorous_bite(V, seed.potency)
@@ -110,7 +110,7 @@
// We shouldn't have spawned if the controller doesn't exist.
check_health()
// Keep processing us until we've done all there is for us to do in life.
if(neighbors.len || health != max_health || !harvest || locked_atoms.len)
if(neighbors.len || health != max_health || !harvest || is_locking(/datum/locking_category/plantsegment))
plant_controller.add_plant(src)
/obj/effect/plantsegment/proc/die_off()

View File

@@ -1,18 +1,3 @@
/*/obj/effect/plantsegment/HasProximity(var/mob/living/M)
if(!istype(M) || !Adjacent(M))
return
if(!is_mature() || limited_growth)
return
if(!(locked_atoms && locked_atoms.len) && !M.locked_to && !M.anchored && (M.size <= SIZE_SMALL || prob(round(seed.potency/6))) )
//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)
if(M && !M.locked_to)
entangle_mob(M)*/
/obj/effect/plantsegment/proc/special_cooldown()
return world.time >= last_special + max(3 SECONDS, 100-seed.potency)

View File

@@ -92,9 +92,9 @@
manual_unbuckle(user)
/obj/effect/plantsegment/proc/manual_unbuckle(mob/user as mob)
if(locked_atoms && locked_atoms.len)
if(is_locking(/datum/locking_category/plantsegment))
if(prob(seed ? min(max(0,100 - seed.potency),100) : 50))
var/mob/M = locked_atoms[1]
var/mob/M = get_locked(/datum/locking_category/plantsegment)[1]
if(M != user)
M.visible_message(\
"<span class='notice'>[user.name] frees [M.name] from \the [src].</span>",\

View File

@@ -630,7 +630,7 @@ Thanks.
/mob/living/Move(atom/newloc, direct)
if (locked_to && locked_to.loc != newloc)
var/datum/locking_category/category = locked_to.locked_atoms[src]
var/datum/locking_category/category = locked_to.get_lock_cat_for(src)
if (locked_to.anchored || category.flags & CANT_BE_MOVED_BY_LOCKED_MOBS)
return 0
else

View File

@@ -144,7 +144,7 @@ var/list/nest_locations = list()
var/smallest_distance = 555
var/best_nest
for(var/obj/structure/bed/nest/N in nest_locations)
if((N.z == src.z) && (N.locked_atoms.len == 0))
if(N.z == z && !N.is_locking(/datum/locking_category/buckle/bed/nest))
var/dist = get_dist(src,N)
if(dist < smallest_distance)
smallest_distance = dist

View File

@@ -1450,8 +1450,8 @@ var/list/slot_equipment_priority = list( \
//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
/mob/proc/update_canmove()
if (locked_to)
var/datum/locking_category/category = locked_to.locked_atoms[src]
if (category && category.flags ^ LOCKED_CAN_LIE_AND_STAND)
var/datum/locking_category/category = locked_to.get_lock_cat_for(src)
if (category && ~category.flags & LOCKED_CAN_LIE_AND_STAND)
canmove = 0
lying = (category.flags & LOCKED_SHOULD_LIE) ? TRUE : FALSE //A lying value that !=1 will break this