Teleporter Safety (#9879)

* Teleporter Safety

* better keyword

* initialize can't handle skips
This commit is contained in:
Geeves
2020-10-06 14:30:53 +02:00
committed by GitHub
parent bd064d3f53
commit eac305e39b
7 changed files with 119 additions and 80 deletions
+42 -34
View File
@@ -1,6 +1,6 @@
/obj/effect/portal
name = "portal"
desc = "Looks unstable. Best to test it carefully."
desc = "A bluespace tear in space, reaching directly to another point within this region. Looks unstable. Best to test it carefully."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "portal"
density = TRUE
@@ -8,61 +8,69 @@
var/does_teleport = TRUE // Some portals might just be visual
var/has_lifespan = TRUE // Whether we want to directly control the lifespan or not
var/failchance = 5
var/has_failed = FALSE
var/obj/target
var/creator
var/precision = TRUE
var/precision = 1
anchored = TRUE
/obj/effect/portal/CollidedWith(mob/M as mob|obj)
set waitfor = FALSE
if(does_teleport)
src.teleport(M)
/obj/effect/portal/Crossed(AM as mob|obj)
set waitfor = FALSE
if(does_teleport)
src.teleport(AM)
/obj/effect/portal/attack_hand(mob/user as mob)
set waitfor = FALSE
if(does_teleport)
src.teleport(user)
/obj/effect/portal/New(loc, turf/target, creator=null, lifespan=300, precise = 1)
..()
if(target)
src.target = target
if(creator)
src.creator = creator
/obj/effect/portal/Initialize(mapload, turf/set_target, set_creator, lifespan = 300, precise = 1)
. = ..()
if(set_target)
target = set_target
if(set_creator)
creator = set_creator
if(has_lifespan && lifespan > 0)
QDEL_IN(src, lifespan)
if(prob(failchance))
has_failed = TRUE
precision = precise
/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj)
/obj/effect/portal/CollidedWith(mob/M)
set waitfor = FALSE
if(does_teleport)
teleport(M)
/obj/effect/portal/Crossed(AM)
set waitfor = FALSE
if(does_teleport)
teleport(AM)
/obj/effect/portal/attack_hand(mob/user)
set waitfor = FALSE
if(does_teleport)
teleport(user)
/obj/effect/portal/proc/teleport(atom/movable/M)
if(!does_teleport) // just to be safe
return
if(istype(M, /obj/effect)) //sparks don't teleport
return
if (icon_state == "portal1")
return
if (!( target ))
if(!target)
qdel(src)
return
if (istype(M, /atom/movable))
if(prob(failchance)) //oh dear a problem, put em in deep space
src.icon_state = "portal1"
if(istype(M, /atom/movable))
if(has_failed) //oh dear a problem, put em in deep space
icon_state = "portal1" // only tell people the portal failed after a teleport has been done
desc = "A bluespace tear in space, reaching directly to another point within this region. Definitely unstable."
do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0)
else
do_teleport(M, target, precision)
/obj/effect/portal/Destroy()
if(istype(creator, /obj/item/hand_tele))
var/obj/item/hand_tele/HT = creator
HT.remove_portal(src)
return ..()
/obj/effect/portal/spawner
name = "portal"
desc = "Looks like a one-way portal, don't come too close."
desc = "A bluespace tear in space, reaching directly to another point within this region. This one looks like a one-way portal to here, don't come too close."
desc_info = "This portal is a spawner portal. You cannot enter it to teleport, but it will periodically spawn things."
does_teleport = FALSE
has_lifespan = FALSE
+1 -1
View File
@@ -164,4 +164,4 @@
/obj/item/syndie/teleporter/pickup()
..()
addtimer(CALLBACK(src, .proc/check_maptext), 1)
addtimer(CALLBACK(src, .proc/check_maptext), 1) // invoke async does not work here
@@ -125,7 +125,7 @@ Frequency:
*/
/obj/item/hand_tele
name = "hand tele"
desc = "A portable item using blue-space technology."
desc = "A hand-held bluespace teleporter that can rip open portals to a random nearby location, or lock onto a teleporter with a selected teleportation beacon."
icon = 'icons/obj/device.dmi'
icon_state = "hand_tele"
item_state = "electronic"
@@ -135,62 +135,85 @@ Frequency:
throw_range = 5
origin_tech = list(TECH_MAGNET = 1, TECH_BLUESPACE = 3)
matter = list(DEFAULT_WALL_MATERIAL = 10000)
var/list/active_teleporters = list()
var/held_maptext = "<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 7px;\">Ready</span>"
/obj/item/hand_tele/attack_self(mob/user as mob)
/obj/item/hand_tele/Initialize()
. = ..()
if(ismob(loc) || ismob(loc.loc))
maptext = held_maptext
/obj/item/hand_tele/attack_self(mob/user)
var/turf/current_location = get_turf(user)//What turf is the user on?
if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist.
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
if(!current_location || isNotStationLevel(current_location.z))
to_chat(user, SPAN_WARNING("\The [src] can't get a bearing on anything right now."))
return
var/list/L = list( )
var/list/teleport_options = list()
for(var/obj/machinery/teleport/hub/R in SSmachinery.all_machines)
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(R.x - 2, R.y, R.z))
if (istype(com, /obj/machinery/computer/teleporter) && com.locked && !com.one_time_use)
var/obj/machinery/computer/teleporter/com = R.com
if(com?.locked && !com.one_time_use)
if(R.icon_state == "tele1")
L["[com.id] (Active)"] = com.locked
teleport_options["[com.id] (Active)"] = com.locked
else
L["[com.id] (Inactive)"] = com.locked
var/list/turfs = list( )
teleport_options["[com.id] (Inactive)"] = com.locked
var/list/potential_turfs = list()
for(var/turf/T in orange(10))
if(T.x>world.maxx-8 || T.x<8)
if(T.x > world.maxx-8 || T.x < 8)
continue //putting them at the edge is dumb
if(T.y>world.maxy-8 || T.y<8)
if(T.y > world.maxy-8 || T.y < 8)
continue
if(T.density)
if(T.density || turf_contains_dense_objects(T))
continue
potential_turfs += T
var/breakcheck = 0
for(var/atom/movable/A in T)
if(A.density && A.opacity && A.anchored)
breakcheck = 1
break
if(length(potential_turfs))
teleport_options["None (Dangerous)"] = pick(potential_turfs)
if(breakcheck)
continue
turfs += T
if(turfs.len)
L["None (Dangerous)"] = pick(turfs)
var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L
if ((user.get_active_hand() != src || user.stat || user.restrained()))
var/teleport_choice = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") as null|anything in teleport_options
if(!teleport_choice || user.get_active_hand() != src || use_check_and_message(user))
return
var/count = 0 //num of portals from this teleport in world
for(var/obj/effect/portal/PO in world)
if(PO.creator == src) count++
if(count >= 3)
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
if(length(active_teleporters) >= 3)
user.show_message(SPAN_WARNING("\The [src] is recharging!"))
return
var/T = L[t1]
for(var/mob/O in hearers(user, null))
O.show_message("<span class='notice'>Locked In.</span>", 2)
var/obj/effect/portal/P = new /obj/effect/portal( get_turf(src) )
P.target = T
P.creator = src
src.add_fingerprint(user)
return
var/T = teleport_options[teleport_choice]
audible_message(SPAN_NOTICE("Locked in."), hearing_distance = 3)
var/obj/effect/portal/P = new /obj/effect/portal(get_turf(src), T, src)
active_teleporters += P
if(length(active_teleporters) >= 3)
check_maptext("<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 6px;\">Charge</span>")
add_fingerprint(user)
/obj/item/hand_tele/proc/remove_portal(var/obj/effect/portal/P)
active_teleporters -= P
if(length(active_teleporters) < 3)
check_maptext("<span style=\"font-family: 'Small Fonts'; -dm-text-outline: 1 black; font-size: 7px;\">Ready</span>")
/obj/item/hand_tele/proc/check_maptext(var/new_maptext)
if(new_maptext)
held_maptext = new_maptext
if(ismob(loc) || ismob(loc.loc))
maptext = held_maptext
else
maptext = ""
/obj/item/hand_tele/throw_at()
..()
check_maptext()
/obj/item/hand_tele/dropped()
..()
check_maptext()
/obj/item/hand_tele/on_give()
check_maptext()
/obj/item/hand_tele/pickup()
..()
addtimer(CALLBACK(src, .proc/check_maptext), 1) // invoke async does not work here
/obj/item/closet_teleporter
name = "closet teleporter"