[MIRROR] Hilbert's Hotel orb now has a bunch of checks to prevent users pulling shenanigans (#1342)

* Hilbert's Hotel orb now has a bunch of checks to prevent users pulling shenanigans (#54229)

Hilbert's Hotel now does some basic level of sanity checking after the input to cut down on a number of shenanigans.

The following are all the new changes:

    Hilbert's cannot be activated via telekinesis. It must be activated by direct player attack.
    If the item isn't adjacent to the target after their input, it aborts.
    If the player attempting to enter the hotel is incapacitated after their input, it aborts.
    If the user no longer has the item in their possession after their input, it aborts even if there is a different target.
    If the user is also the target, it will attempt to drop the item normally. If the item fails to drop, it may be teleported to the hotel with the user. The item can fail to drop when it is in the user's possession but not in their hands, or when it has TRAIT_NODROP.
    When the item enters a hotel room created by itself, it will now recursively check for the first mob in its loc stack. It will gib this mob before teleporting away.
    This prevents the warp-whistle effect where a user could put the item in their backpack at INCREDIBLY low risk to themselves (0.135685% chance of anything bad happening) to enter a hotel room and have the orb warped away at random. They could then immediately leave for a free warp whistle effect.

* Hilbert's Hotel orb now has a bunch of checks to prevent users pulling shenanigans

Co-authored-by: Timberpoes <silent_insomnia_pp@hotmail.co.uk>
This commit is contained in:
SkyratBot
2020-10-17 01:15:54 +01:00
committed by GitHub
co-authored by Timberpoes
parent 186ac10d51
commit 204c74c435
@@ -36,27 +36,63 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
/obj/item/hilbertshotel/attack(mob/living/M, mob/living/user)
if(M.mind)
to_chat(user, "<span class='notice'>You invite [M] to the hotel.</span>")
promptAndCheckIn(M)
promptAndCheckIn(user, M)
else
to_chat(user, "<span class='warning'>[M] is not intelligent enough to understand how to use this device!</span>")
/obj/item/hilbertshotel/attack_self(mob/user)
. = ..()
promptAndCheckIn(user)
promptAndCheckIn(user, user)
/obj/item/hilbertshotel/attack_tk(mob/user)
to_chat(user, "<span class='notice'>\The [src] actively rejects your mind as the bluespace energies surrounding it disrupt your telekinesis.</span>")
return
/obj/item/hilbertshotel/proc/promptAndCheckIn(mob/user, mob/target)
var/chosenRoomNumber
// Input text changes depending on if you're using this in yourself or someone else.
if(user == target)
chosenRoomNumber = input(target, "What number room will you be checking into?", "Room Number") as null|num
else
chosenRoomNumber = input(target, "[user] is inviting you to enter \the [src]. What number room will you be checking into?", "Room Number") as null|num
/obj/item/hilbertshotel/proc/promptAndCheckIn(mob/user)
var/chosenRoomNumber = input(user, "What number room will you be checking into?", "Room Number") as null|num
if(!chosenRoomNumber)
return
if(chosenRoomNumber > SHORT_REAL_LIMIT)
to_chat(user, "<span class='warning'>You have to check out the first [SHORT_REAL_LIMIT] rooms before you can go to a higher numbered one!</span>")
to_chat(target, "<span class='warning'>You have to check out the first [SHORT_REAL_LIMIT] rooms before you can go to a higher numbered one!</span>")
return
if((chosenRoomNumber < 1) || (chosenRoomNumber != round(chosenRoomNumber)))
to_chat(user, "<span class='warning'>That is not a valid room number!</span>")
to_chat(target, "<span class='warning'>That is not a valid room number!</span>")
return
if(ismob(loc))
if(user == loc) //Not always the same as user
forceMove(get_turf(user))
// Orb is not adjacent to the target. No teleporties.
if(!src.Adjacent(target))
to_chat(target, "<span class='warning'>You too far away from \the [src] to enter it!</span>")
// If the target is incapacitated after selecting a room, they're not allowed to teleport.
if(target.incapacitated())
to_chat(target, "<span class='warning'>You aren't able to activate \the [src] anymore!</span>")
// Has the user thrown it away or otherwise disposed of it such that it's no longer in their hands or in some storage connected to them?
if(!(get_atom_on_turf(src, /mob) == user))
if(user == target)
to_chat(user, "<span class='warning'>\The [src] is no longer in your possession!</span>")
else
to_chat(target, "<span class='warning'>\The [src] is no longer in the possession of [user]!</span>")
return
// If the player is using it on themselves, we've got some logic to deal with.
// The user should drop the item before teleporting, but we're not going to force the item to be dropped if it can't be done normally...
if(user == target)
// The item should be on the user or in the user's inventory somewhere.
// However, if they're not holding it, it may be in a pocket? In a backpack? Who knows! Still, they can't just drop it to the floor anymore...
if(!user.get_held_index_of_item(src))
to_chat(user, "<span class='warning'>You try to drop \the [src], but it's too late! It's no longer in your hands! Prepare for unforeseen consequences...</span>")
// Okay, so they HAVE to be holding it here, because it's in their hand from the above check. Try to drop the item and if it fails, oh dear...
else if(!user.dropItemToGround(src))
to_chat(user, "<span class='warning'>You can't seem to drop \the [src]! It must be stuck to your hand somehow! Prepare for unforeseen consequences...</span>")
if(!storageTurf) //Blame subsystems for not allowing this to be in Initialize
if(!GLOB.hhStorageTurf)
var/datum/map_template/hilbertshotelstorage/storageTemp = new()
@@ -65,12 +101,11 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
GLOB.hhStorageTurf = locate(storageReservation.bottom_left_coords[1]+1, storageReservation.bottom_left_coords[2]+1, storageReservation.bottom_left_coords[3])
else
storageTurf = GLOB.hhStorageTurf
if(tryActiveRoom(chosenRoomNumber, user))
if(tryActiveRoom(chosenRoomNumber, target))
return
if(tryStoredRoom(chosenRoomNumber, user))
if(tryStoredRoom(chosenRoomNumber, target))
return
sendToNewRoom(chosenRoomNumber, user)
sendToNewRoom(chosenRoomNumber, target)
/obj/item/hilbertshotel/proc/tryActiveRoom(roomNumber, mob/user)
if(activeRooms["[roomNumber]"])
@@ -334,6 +369,16 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
if(prob(0.135685)) //Because screw you
qdel(H)
return
// Prepare for...
var/mob/unforeseen_consequences = get_atom_on_turf(H, /mob)
// Turns out giving anyone who grabs a Hilbert's Hotel a free, complementary warp whistle is probably bad.
// Let's gib the last person to have selected a room number in it.
if(unforeseen_consequences)
to_chat(unforeseen_consequences, "<span class='warning'>\The [H] starts to resonate. Forcing it to enter itself induces a bluespace paradox, violently tearing your body apart.</span>")
unforeseen_consequences.gib()
var/turf/targetturf = find_safe_turf()
if(!targetturf)
if(GLOB.blobstart.len > 0)