mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-25 16:45:42 +00:00
cl Denton
add: Added three new .38 ammo types. TRAC bullets, which embed a tracking implant inside the target's body. The implant only lasts for five minutes and doesn't work as a teleport beacon. Hot Shot bullets set targets on fire; Iceblox bullets drastically lower the target's body temperature. They are available after researching the Subdermal Implants node (TRAC) or Exotic Ammunition node (Hot Shot/Iceblox).
tweak: Renamed the Technological Shells research node to Exotic Ammunition.
code: The "lifespan_postmortem" var now determines how long tracking implants work after death.
/cl
Flavor aside, the detective's revolver is little more than a weak Stechkin. I figured that some ammo variety might make it more fun to use:
TRAC: Only deals 10 damage, but implants a tracking implant once it hits someone. Security can then track the perp with a bluespace locator. It will delete itself after 5 minutes and doesn't work as a teleport beacon.
Hot Shot: 20 damage and hits the target with 6 fire stacks.
Iceblox: 20 damage, lowers the target's body temp similar to the temp gun.
Let me know if you think that Hot Shot/Iceblox are too strong - they won't be available early during most rounds because they're gated behind the tech shells node and require plasma to print.
237 lines
8.5 KiB
Plaintext
237 lines
8.5 KiB
Plaintext
|
|
#define SOURCE_PORTAL 1
|
|
#define DESTINATION_PORTAL 2
|
|
|
|
/* Teleportation devices.
|
|
* Contains:
|
|
* Locator
|
|
* Hand-tele
|
|
*/
|
|
|
|
/*
|
|
* Locator
|
|
*/
|
|
/obj/item/locator
|
|
name = "bluespace locator"
|
|
desc = "Used to track portable teleportation beacons and targets with embedded tracking implants."
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "locator"
|
|
var/temp = null
|
|
flags_1 = CONDUCT_1
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
item_state = "electronic"
|
|
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
|
throw_speed = 3
|
|
throw_range = 7
|
|
materials = list(MAT_METAL=400)
|
|
|
|
/obj/item/locator/attack_self(mob/user)
|
|
user.set_machine(src)
|
|
var/dat
|
|
if (temp)
|
|
dat = "[temp]<BR><BR><A href='byond://?src=[REF(src)];temp=1'>Clear</A>"
|
|
else
|
|
dat = {"
|
|
<B>Persistent Signal Locator</B><HR>
|
|
<A href='?src=[REF(src)];refresh=1'>Refresh</A>"}
|
|
user << browse(dat, "window=radio")
|
|
onclose(user, "radio")
|
|
return
|
|
|
|
/obj/item/locator/Topic(href, href_list)
|
|
..()
|
|
if (usr.stat || usr.restrained())
|
|
return
|
|
var/turf/current_location = get_turf(usr)//What turf is the user on?
|
|
if(!current_location || is_centcom_level(current_location.z))//If turf was not found or they're on CentCom
|
|
to_chat(usr, "[src] is malfunctioning.")
|
|
return
|
|
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)))
|
|
usr.set_machine(src)
|
|
if (href_list["refresh"])
|
|
temp = "<B>Persistent Signal Locator</B><HR>"
|
|
var/turf/sr = get_turf(src)
|
|
|
|
if (sr)
|
|
temp += "<B>Beacon Signals:</B><BR>"
|
|
for(var/obj/item/beacon/W in GLOB.teleportbeacons)
|
|
if (!W.renamed)
|
|
continue
|
|
var/turf/tr = get_turf(W)
|
|
if (tr.z == sr.z && tr)
|
|
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
|
|
if (direct < 5)
|
|
direct = "very strong"
|
|
else
|
|
if (direct < 10)
|
|
direct = "strong"
|
|
else
|
|
if (direct < 20)
|
|
direct = "weak"
|
|
else
|
|
direct = "very weak"
|
|
temp += "[W.name]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
|
|
|
|
temp += "<B>Implant Signals:</B><BR>"
|
|
for (var/obj/item/implant/tracking/W in GLOB.tracked_implants)
|
|
if (!W.imp_in || !isliving(W.loc))
|
|
continue
|
|
else
|
|
var/mob/living/M = W.loc
|
|
if (M.stat == DEAD)
|
|
if (M.timeofdeath + W.lifespan_postmortem < world.time)
|
|
continue
|
|
|
|
var/turf/tr = get_turf(W)
|
|
if (tr.z == sr.z && tr)
|
|
var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y))
|
|
if (direct < 20)
|
|
if (direct < 5)
|
|
direct = "very strong"
|
|
else
|
|
if (direct < 10)
|
|
direct = "strong"
|
|
else
|
|
direct = "weak"
|
|
temp += "[W.imp_in.name]-[dir2text(get_dir(sr, tr))]-[direct]<BR>"
|
|
|
|
temp += "<B>You are at \[[sr.x],[sr.y],[sr.z]\]</B> in orbital coordinates.<BR><BR><A href='byond://?src=[REF(src)];refresh=1'>Refresh</A><BR>"
|
|
else
|
|
temp += "<B><FONT color='red'>Processing Error:</FONT></B> Unable to locate orbital position.<BR>"
|
|
else
|
|
if (href_list["temp"])
|
|
temp = null
|
|
if (ismob(src.loc))
|
|
attack_self(src.loc)
|
|
else
|
|
for(var/mob/M in viewers(1, src))
|
|
if (M.client)
|
|
src.attack_self(M)
|
|
return
|
|
|
|
|
|
/*
|
|
* Hand-tele
|
|
*/
|
|
/obj/item/hand_tele
|
|
name = "hand tele"
|
|
desc = "A portable item using blue-space technology."
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "hand_tele"
|
|
item_state = "electronic"
|
|
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
|
throwforce = 0
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
throw_speed = 3
|
|
throw_range = 5
|
|
materials = list(MAT_METAL=10000)
|
|
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
|
var/list/active_portal_pairs
|
|
var/max_portal_pairs = 3
|
|
var/atmos_link_override
|
|
|
|
/obj/item/hand_tele/Initialize()
|
|
. = ..()
|
|
active_portal_pairs = list()
|
|
|
|
/obj/item/hand_tele/pre_attack(atom/target, mob/user, params)
|
|
if(try_dispel_portal(target, user))
|
|
return FALSE
|
|
return ..()
|
|
|
|
/obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user)
|
|
if(is_parent_of_portal(target))
|
|
qdel(target)
|
|
to_chat(user, "<span class='notice'>You dispel [target] with \the [src]!</span>")
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/item/hand_tele/afterattack(atom/target, mob/user)
|
|
try_dispel_portal(target, user)
|
|
. = ..()
|
|
|
|
/obj/item/hand_tele/attack_self(mob/user)
|
|
var/turf/current_location = get_turf(user)//What turf is the user on?
|
|
var/area/current_area = current_location.loc
|
|
if(!current_location || current_area.noteleport || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
|
|
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
|
return
|
|
var/list/L = list( )
|
|
for(var/obj/machinery/computer/teleporter/com in GLOB.machines)
|
|
if(com.target)
|
|
var/area/A = get_area(com.target)
|
|
if(!A || A.noteleport)
|
|
continue
|
|
if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged)
|
|
L["[get_area(com.target)] (Active)"] = com.target
|
|
else
|
|
L["[get_area(com.target)] (Inactive)"] = com.target
|
|
var/list/turfs = list( )
|
|
for(var/turf/T in urange(10, orange=1))
|
|
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)
|
|
continue
|
|
var/area/A = T.loc
|
|
if(A.noteleport)
|
|
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") as null|anything in L
|
|
if (!t1 || user.get_active_held_item() != src || user.incapacitated())
|
|
return
|
|
if(active_portal_pairs.len >= max_portal_pairs)
|
|
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
|
|
return
|
|
var/atom/T = L[t1]
|
|
var/area/A = get_area(T)
|
|
if(A.noteleport)
|
|
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
|
return
|
|
current_location = get_turf(user) //Recheck.
|
|
current_area = current_location.loc
|
|
if(!current_location || current_area.noteleport || is_away_level(current_location.z) || !isturf(user.loc))//If turf was not found or they're on z level 2 or >7 which does not currently exist. or if user is not located on a turf
|
|
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
|
return
|
|
user.show_message("<span class='notice'>Locked In.</span>", 2)
|
|
var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1, null, atmos_link_override)
|
|
if(!(LAZYLEN(created) == 2))
|
|
return
|
|
try_move_adjacent(created[1])
|
|
active_portal_pairs[created[1]] = created[2]
|
|
var/obj/effect/portal/c1 = created[1]
|
|
var/obj/effect/portal/c2 = created[2]
|
|
investigate_log("was used by [key_name(user)] at [AREACOORD(user)] to create a portal pair with destinations [AREACOORD(c1)] and [AREACOORD(c2)].", INVESTIGATE_PORTAL)
|
|
add_fingerprint(user)
|
|
|
|
/obj/item/hand_tele/proc/on_portal_destroy(obj/effect/portal/P)
|
|
active_portal_pairs -= P //If this portal pair is made by us it'll be erased along with the other portal by the portal.
|
|
|
|
/obj/item/hand_tele/proc/is_parent_of_portal(obj/effect/portal/P)
|
|
if(!istype(P))
|
|
return FALSE
|
|
if(active_portal_pairs[P])
|
|
return SOURCE_PORTAL
|
|
for(var/i in active_portal_pairs)
|
|
if(active_portal_pairs[i] == P)
|
|
return DESTINATION_PORTAL
|
|
return FALSE
|
|
|
|
/obj/item/hand_tele/suicide_act(mob/user)
|
|
if(iscarbon(user))
|
|
user.visible_message("<span class='suicide'>[user] is creating a weak portal and sticking [user.p_their()] head through! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
|
var/mob/living/carbon/itemUser = user
|
|
var/obj/item/bodypart/head/head = itemUser.get_bodypart(BODY_ZONE_HEAD)
|
|
if(head)
|
|
head.drop_limb()
|
|
var/list/safeLevels = SSmapping.levels_by_any_trait(list(ZTRAIT_SPACE_RUINS, ZTRAIT_LAVA_RUINS, ZTRAIT_STATION, ZTRAIT_MINING))
|
|
head.forceMove(locate(rand(1, world.maxx), rand(1, world.maxy), pick(safeLevels)))
|
|
itemUser.visible_message("<span class='suicide'>The portal snaps closed taking [user]'s head with it!</span>")
|
|
else
|
|
itemUser.visible_message("<span class='suicide'>[user] looks even further depressed as they realize they do not have a head...and suddenly dies of shame!</span>")
|
|
return (BRUTELOSS)
|